Merge remote branch 'goog/dalvik-dev' into dalvik-dev-to-master
Change-Id: I99c4289bd34f63b0b970b6ed0fa992b44e805393
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index b7dda0f..5960a4b 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -20,7 +20,7 @@
#
dalvikvm_src_files := \
- Main.c
+ Main.cpp
dalvikvm_c_includes := \
$(JNI_H_INCLUDE) \
diff --git a/dalvikvm/Main.c b/dalvikvm/Main.cpp
similarity index 86%
rename from dalvikvm/Main.c
rename to dalvikvm/Main.cpp
index 666317c..4aa6e20 100644
--- a/dalvikvm/Main.c
+++ b/dalvikvm/Main.cpp
@@ -48,14 +48,14 @@
jobjectArray result = NULL;
int i;
- stringClass = (*env)->FindClass(env, "java/lang/String");
- if ((*env)->ExceptionCheck(env)) {
+ stringClass = env->FindClass("java/lang/String");
+ if (env->ExceptionCheck()) {
fprintf(stderr, "Got exception while finding class String\n");
goto bail;
}
assert(stringClass != NULL);
- strArray = (*env)->NewObjectArray(env, argc, stringClass, NULL);
- if ((*env)->ExceptionCheck(env)) {
+ strArray = env->NewObjectArray(argc, stringClass, NULL);
+ if (env->ExceptionCheck()) {
fprintf(stderr, "Got exception while creating String array\n");
goto bail;
}
@@ -64,14 +64,14 @@
for (i = 0; i < argc; i++) {
jstring argStr;
- argStr = (*env)->NewStringUTF(env, argv[i]);
- if ((*env)->ExceptionCheck(env)) {
+ argStr = env->NewStringUTF(argv[i]);
+ if (env->ExceptionCheck()) {
fprintf(stderr, "Got exception while allocating Strings\n");
goto bail;
}
assert(argStr != NULL);
- (*env)->SetObjectArrayElement(env, strArray, i, argStr);
- (*env)->DeleteLocalRef(env, argStr);
+ env->SetObjectArrayElement(strArray, i, argStr);
+ env->DeleteLocalRef(argStr);
}
/* return the array, and ensure we don't delete the local ref to it */
@@ -79,8 +79,8 @@
strArray = NULL;
bail:
- (*env)->DeleteLocalRef(env, stringClass);
- (*env)->DeleteLocalRef(env, strArray);
+ env->DeleteLocalRef(stringClass);
+ env->DeleteLocalRef(strArray);
return result;
}
@@ -98,7 +98,7 @@
int modifiers;
int result = JNI_FALSE;
- refMethod = (*env)->ToReflectedMethod(env, clazz, methodId, JNI_FALSE);
+ refMethod = env->ToReflectedMethod(clazz, methodId, JNI_FALSE);
if (refMethod == NULL) {
fprintf(stderr, "Dalvik VM unable to get reflected method\n");
goto bail;
@@ -108,19 +108,19 @@
* We now have a Method instance. We need to call
* its getModifiers() method.
*/
- methodClass = (*env)->FindClass(env, "java/lang/reflect/Method");
+ methodClass = env->FindClass("java/lang/reflect/Method");
if (methodClass == NULL) {
fprintf(stderr, "Dalvik VM unable to find class Method\n");
goto bail;
}
- getModifiersId = (*env)->GetMethodID(env, methodClass,
+ getModifiersId = env->GetMethodID(methodClass,
"getModifiers", "()I");
if (getModifiersId == NULL) {
fprintf(stderr, "Dalvik VM unable to find reflect.Method.getModifiers\n");
goto bail;
}
- modifiers = (*env)->CallIntMethod(env, refMethod, getModifiersId);
+ modifiers = env->CallIntMethod(refMethod, getModifiersId);
if ((modifiers & PUBLIC) == 0) {
fprintf(stderr, "Dalvik VM: main() is not public\n");
goto bail;
@@ -129,8 +129,8 @@
result = JNI_TRUE;
bail:
- (*env)->DeleteLocalRef(env, refMethod);
- (*env)->DeleteLocalRef(env, methodClass);
+ env->DeleteLocalRef(refMethod);
+ env->DeleteLocalRef(methodClass);
return result;
}
@@ -246,13 +246,13 @@
if (*cp == '.')
*cp = '/';
- startClass = (*env)->FindClass(env, slashClass);
+ startClass = env->FindClass(slashClass);
if (startClass == NULL) {
fprintf(stderr, "Dalvik VM unable to locate class '%s'\n", slashClass);
goto bail;
}
- startMeth = (*env)->GetStaticMethodID(env, startClass,
+ startMeth = env->GetStaticMethodID(startClass,
"main", "([Ljava/lang/String;)V");
if (startMeth == NULL) {
fprintf(stderr, "Dalvik VM unable to find static main(String[]) in '%s'\n",
@@ -270,9 +270,9 @@
/*
* Invoke main().
*/
- (*env)->CallStaticVoidMethod(env, startClass, startMeth, strArray);
+ env->CallStaticVoidMethod(startClass, startMeth, strArray);
- if (!(*env)->ExceptionCheck(env))
+ if (!env->ExceptionCheck())
result = 0;
bail:
@@ -282,12 +282,12 @@
* This allows join() and isAlive() on the main thread to work
* correctly, and also provides uncaught exception handling.
*/
- if ((*vm)->DetachCurrentThread(vm) != JNI_OK) {
+ if (vm->DetachCurrentThread() != JNI_OK) {
fprintf(stderr, "Warning: unable to detach main thread\n");
result = 1;
}
- if ((*vm)->DestroyJavaVM(vm) != 0)
+ if (vm->DestroyJavaVM() != 0)
fprintf(stderr, "Warning: Dalvik VM did not shut down cleanly\n");
/*printf("\nDalvik VM has exited\n");*/
}
diff --git a/dexdump/Android.mk b/dexdump/Android.mk
index 58fa137..e47acfa 100644
--- a/dexdump/Android.mk
+++ b/dexdump/Android.mk
@@ -18,7 +18,7 @@
LOCAL_PATH:= $(call my-dir)
dexdump_src_files := \
- DexDump.c
+ DexDump.cpp
dexdump_c_includes := \
dalvik \
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.cpp
similarity index 98%
rename from dexdump/DexDump.c
rename to dexdump/DexDump.cpp
index 9353471..59f149b 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.cpp
@@ -52,13 +52,13 @@
static const char* gProgName = "dexdump";
-typedef enum OutputFormat {
+enum OutputFormat {
OUTPUT_PLAIN = 0, /* default */
OUTPUT_XML, /* fancy */
-} OutputFormat;
+};
/* command-line options */
-struct {
+struct Options {
bool checksumOnly;
bool disassemble;
bool showFileHeaders;
@@ -69,14 +69,16 @@
const char* tempFileName;
bool exportsOnly;
bool verbose;
-} gOptions;
+};
+
+struct Options gOptions;
/* basic info about a field or method */
-typedef struct FieldMethodInfo {
+struct FieldMethodInfo {
const char* classDescriptor;
const char* name;
const char* signature;
-} FieldMethodInfo;
+};
/*
* Get 2 little-endian bytes.
@@ -150,7 +152,7 @@
}
}
- newStr = malloc(targetLen + arrayDepth * 2 +1);
+ newStr = (char*)malloc(targetLen + arrayDepth * 2 +1);
/* copy class name over */
int i;
@@ -239,10 +241,10 @@
/*
* Flag for use with createAccessFlagStr().
*/
-typedef enum AccessFor {
+enum AccessFor {
kAccessForClass = 0, kAccessForMethod = 1, kAccessForField = 2,
kAccessForMAX
-} AccessFor;
+};
/*
* Create a new string with human-readable access flags.
@@ -825,7 +827,7 @@
* size, so we add explicit space for it here.
*/
outSize++;
- buf = malloc(outSize);
+ buf = (char*)malloc(outSize);
if (buf == NULL) {
return NULL;
}
@@ -1647,7 +1649,7 @@
*/
void dumpRegisterMaps(DexFile* pDexFile)
{
- const u1* pClassPool = pDexFile->pRegisterMapPool;
+ const u1* pClassPool = (const u1*)pDexFile->pRegisterMapPool;
const u4* classOffsets;
const u1* ptr;
u4 numClasses;
@@ -1781,15 +1783,16 @@
if (gOptions.verbose)
printf("Processing '%s'...\n", fileName);
- if (dexOpenAndMap(fileName, gOptions.tempFileName, &map, false) != 0)
- goto bail;
+ if (dexOpenAndMap(fileName, gOptions.tempFileName, &map, false) != 0) {
+ return result;
+ }
mapped = true;
int flags = kDexParseVerifyChecksum;
if (gOptions.ignoreBadChecksum)
flags |= kDexParseContinueOnError;
- pDexFile = dexFileParse(map.addr, map.length, flags);
+ pDexFile = dexFileParse((u1*)map.addr, map.length, flags);
if (pDexFile == NULL) {
fprintf(stderr, "ERROR: DEX parse failed\n");
goto bail;
diff --git a/dexlist/Android.mk b/dexlist/Android.mk
index aacdfb5..a7dd6e2 100644
--- a/dexlist/Android.mk
+++ b/dexlist/Android.mk
@@ -18,7 +18,7 @@
LOCAL_PATH:= $(call my-dir)
dexdump_src_files := \
- DexList.c
+ DexList.cpp
dexdump_c_includes := \
dalvik \
diff --git a/dexlist/DexList.c b/dexlist/DexList.cpp
similarity index 97%
rename from dexlist/DexList.c
rename to dexlist/DexList.cpp
index 5326692..03f0230 100644
--- a/dexlist/DexList.c
+++ b/dexlist/DexList.cpp
@@ -63,7 +63,7 @@
str++; /* Skip the 'L'. */
}
- newStr = malloc(at + 1); /* Add one for the '\0'. */
+ newStr = (char*)malloc(at + 1); /* Add one for the '\0'. */
newStr[at] = '\0';
while (at > 0) {
@@ -217,7 +217,7 @@
}
mapped = true;
- pDexFile = dexFileParse(map.addr, map.length, kDexParseDefault);
+ pDexFile = dexFileParse((u1*)map.addr, map.length, kDexParseDefault);
if (pDexFile == NULL) {
fprintf(stderr, "Warning: DEX parse failed for '%s'\n", fileName);
goto bail;
diff --git a/dexopt/Android.mk b/dexopt/Android.mk
index 3bb98a5..241893a 100644
--- a/dexopt/Android.mk
+++ b/dexopt/Android.mk
@@ -19,7 +19,7 @@
LOCAL_PATH:= $(call my-dir)
local_src_files := \
- OptMain.c
+ OptMain.cpp
local_c_includes := \
dalvik \
diff --git a/dexopt/OptMain.c b/dexopt/OptMain.cpp
similarity index 98%
rename from dexopt/OptMain.c
rename to dexopt/OptMain.cpp
index 7ecd1e0..a7a898d 100644
--- a/dexopt/OptMain.c
+++ b/dexopt/OptMain.cpp
@@ -65,6 +65,9 @@
off_t dexOffset;
int err;
int result = -1;
+ int dexoptFlags = 0; /* bit flags, from enum DexoptFlags */
+ DexClassVerifyMode verifyMode = VERIFY_MODE_ALL;
+ DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED;
memset(&zippy, 0, sizeof(zippy));
@@ -126,11 +129,6 @@
}
/* Parse the options. */
-
- DexClassVerifyMode verifyMode = VERIFY_MODE_ALL;
- DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED;
- int dexoptFlags = 0; /* bit flags, from enum DexoptFlags */
-
if (dexoptFlagStr[0] != '\0') {
const char* opc;
const char* val;
@@ -208,7 +206,6 @@
static int processZipFile(int zipFd, int cacheFd, const char* zipName,
const char *dexoptFlags)
{
- int result = -1;
char* bcpCopy = NULL;
/*
@@ -218,7 +215,7 @@
const char* bcp = getenv("BOOTCLASSPATH");
if (bcp == NULL) {
LOGE("DexOptZ: BOOTCLASSPATH not set\n");
- goto bail;
+ return -1;
}
bool isBootstrap = false;
@@ -248,10 +245,9 @@
isBootstrap = true;
}
- result = extractAndProcessZip(zipFd, cacheFd, zipName, isBootstrap,
+ int result = extractAndProcessZip(zipFd, cacheFd, zipName, isBootstrap,
bcp, dexoptFlags);
-bail:
free(bcpCopy);
return result;
}
@@ -348,7 +344,7 @@
*/
fprintf(stderr, "Wrong number of args for --preopt (found %d)\n",
argc);
- goto bail;
+ return -1;
}
const char* zipName = argv[2];
@@ -359,13 +355,13 @@
strstr(dexoptFlags, "u=n") == NULL)
{
fprintf(stderr, "Either 'u=y' or 'u=n' must be specified\n");
- goto bail;
+ return -1;
}
zipFd = open(zipName, O_RDONLY);
if (zipFd < 0) {
perror(argv[0]);
- goto bail;
+ return -1;
}
outFd = open(outName, O_RDWR | O_EXCL | O_CREAT, 0666);
@@ -427,6 +423,9 @@
const char* debugFileName;
u4 crc, modWhen;
char* endp;
+ bool onlyOptVerifiedDex = false;
+ DexClassVerifyMode verifyMode;
+ DexOptimizerMode dexOptMode;
if (argc < 10) {
/* don't have all mandatory args */
@@ -492,9 +491,6 @@
LOGV(" bootclasspath is '%s'\n", bootClassPath);
/* start the VM partway */
- bool onlyOptVerifiedDex = false;
- DexClassVerifyMode verifyMode;
- DexOptimizerMode dexOptMode;
/* ugh -- upgrade these to a bit field if they get any more complex */
if ((flags & DEXOPT_VERIFY_ENABLED) != 0) {
diff --git a/docs/dex-format.html b/docs/dex-format.html
index 5a71b59..81c0b36 100644
--- a/docs/dex-format.html
+++ b/docs/dex-format.html
@@ -315,7 +315,7 @@
<h2><code>access_flags</code> Definitions</h2>
<h4>embedded in <code>class_def_item</code>,
-<code>field_item</code>, <code>method_item</code>, and
+<code>encoded_field</code>, <code>encoded_method</code>, and
<code>InnerClass</code></h4>
<p>Bitfields of these flags are used to indicate the accessibility and
@@ -2017,7 +2017,7 @@
</table>
<h2><code>code_item</code></h2>
-<h4>referenced from <code>method_item</code></h4>
+<h4>referenced from <code>encoded_method</code></h4>
<h4>appears in the <code>data</code> section</h4>
<h4>alignment: 4 bytes</h4>
diff --git a/dvz/Android.mk b/dvz/Android.mk
index 4e4387e..22d0950 100644
--- a/dvz/Android.mk
+++ b/dvz/Android.mk
@@ -4,7 +4,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- dvz.c
+ dvz.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils
diff --git a/dvz/dvz.c b/dvz/dvz.cpp
similarity index 100%
rename from dvz/dvz.c
rename to dvz/dvz.cpp
diff --git a/dx/junit-tests/HelloWorldMaker.java b/dx/junit-tests/HelloWorldMaker.java
new file mode 100644
index 0000000..001f31a
--- /dev/null
+++ b/dx/junit-tests/HelloWorldMaker.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+import com.android.dx.gen.BinaryOp;
+import com.android.dx.gen.Code;
+import com.android.dx.gen.DexGenerator;
+import com.android.dx.gen.FieldId;
+import com.android.dx.gen.Local;
+import com.android.dx.gen.MethodId;
+import com.android.dx.gen.Type;
+import com.android.dx.rop.code.AccessFlags;
+import java.io.PrintStream;
+
+public class HelloWorldMaker {
+ private static final Type<PrintStream> PRINT_STREAM = Type.get(PrintStream.class);
+ private static final FieldId<System, PrintStream> SYSTEM_OUT
+ = Type.get(System.class).getField(PRINT_STREAM, "out");
+ private static final MethodId<Integer, String> TO_HEX_STRING
+ = Type.get(Integer.class).getMethod(Type.STRING, "toHexString", Type.INT);
+ private static final MethodId<PrintStream, Void> PRINTLN
+ = PRINT_STREAM.getMethod(Type.VOID, "println", Type.STRING);
+
+ public static void main(String[] args) throws Exception {
+
+ /*
+ * This code generates Dalvik bytecode equivalent to the following
+ * program.
+ *
+ * public class HelloWorld {
+ * public static void hello() {
+ * int a = 0xabcd;
+ * int b = 0xaaaa;
+ * int c = a - b;
+ * String s = Integer.toHexString(c);
+ * System.out.println(s);
+ * }
+ * }
+ */
+
+ DexGenerator generator = new DexGenerator();
+
+ // lookup the symbols of interest
+ Type<?> helloWorld = Type.get("LHelloWorld;");
+ MethodId hello = helloWorld.getMethod(Type.VOID, "hello");
+
+ // create some registers
+ // (I'd like a better syntax for this)
+ Code code = generator.declare(hello, AccessFlags.ACC_STATIC | AccessFlags.ACC_PUBLIC);
+ Local<Integer> a = code.newLocal(Type.INT);
+ Local<Integer> b = code.newLocal(Type.INT);
+ Local<Integer> c = code.newLocal(Type.INT);
+ Local<String> s = code.newLocal(Type.STRING);
+ Local<PrintStream> localSystemOut = code.newLocal(PRINT_STREAM);
+
+ // specify the code instruction-by-instruction (approximately)
+ code.loadConstant(a, 0xabcd);
+ code.loadConstant(b, 0xaaaa);
+ code.op(BinaryOp.SUBTRACT, c, a, b);
+ code.invokeStatic(TO_HEX_STRING, s, c);
+ code.sget(SYSTEM_OUT, localSystemOut);
+ code.invokeVirtual(PRINTLN, null, localSystemOut, s);
+ code.returnVoid();
+
+ // TODO: create the constructor
+
+ generator.declare(helloWorld, "Generated.java", AccessFlags.ACC_PUBLIC, Type.OBJECT);
+
+ // load the dex
+ ClassLoader loader = generator.load(HelloWorldMaker.class.getClassLoader());
+ Class<?> helloWorldClass = loader.loadClass("HelloWorld");
+ helloWorldClass.getMethod("hello").invoke(null);
+ }
+}
diff --git a/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java b/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java
new file mode 100644
index 0000000..99eea85
--- /dev/null
+++ b/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java
@@ -0,0 +1,1628 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import static com.android.dx.rop.code.AccessFlags.ACC_CONSTRUCTOR;
+import static com.android.dx.rop.code.AccessFlags.ACC_FINAL;
+import static com.android.dx.rop.code.AccessFlags.ACC_PRIVATE;
+import static com.android.dx.rop.code.AccessFlags.ACC_PROTECTED;
+import static com.android.dx.rop.code.AccessFlags.ACC_PUBLIC;
+import static com.android.dx.rop.code.AccessFlags.ACC_STATIC;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import junit.framework.TestCase;
+
+/**
+ * This generates a class named 'Generated' with one or more generated methods
+ * and fields. In loads the generated class into the current VM and uses
+ * reflection to invoke its methods.
+ *
+ * <p>This test must run on a Dalvik VM.
+ */
+public final class DexGeneratorTest extends TestCase {
+ private DexGenerator generator;
+ private static Type<DexGeneratorTest> TEST_TYPE = Type.get(DexGeneratorTest.class);
+ private static Type<?> INT_ARRAY = Type.get(int[].class);
+ private static Type<boolean[]> BOOLEAN_ARRAY = Type.get(boolean[].class);
+ private static Type<long[]> LONG_ARRAY = Type.get(long[].class);
+ private static Type<Object[]> OBJECT_ARRAY = Type.get(Object[].class);
+ private static Type<long[][]> LONG_2D_ARRAY = Type.get(long[][].class);
+ private static Type<?> GENERATED = Type.get("LGenerated;");
+ private static Type<Callable> CALLABLE = Type.get(Callable.class);
+ private static MethodId<Callable, Object> CALL = CALLABLE.getMethod(Type.OBJECT, "call");
+
+ @Override protected void setUp() throws Exception {
+ super.setUp();
+ reset();
+ }
+
+ /**
+ * The generator is mutable. Calling reset creates a new empty generator.
+ * This is necessary to generate multiple classes in the same test method.
+ */
+ private void reset() {
+ generator = new DexGenerator();
+ generator.declare(GENERATED, "Generated.java", ACC_PUBLIC, Type.OBJECT);
+ }
+
+ public void testNewInstance() throws Exception {
+ /*
+ * public static Constructable call(long a, boolean b) {
+ * Constructable result = new Constructable(a, b);
+ * return result;
+ * }
+ */
+ Type<Constructable> constructable = Type.get(Constructable.class);
+ MethodId<?, Constructable> methodId = GENERATED.getMethod(
+ constructable, "call", Type.LONG, Type.BOOLEAN);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Long> localA = code.getParameter(0, Type.LONG);
+ Local<Boolean> localB = code.getParameter(1, Type.BOOLEAN);
+ MethodId<Constructable, Void> constructor
+ = constructable.getConstructor(Type.LONG, Type.BOOLEAN);
+ Local<Constructable> localResult = code.newLocal(constructable);
+ code.newInstance(localResult, constructor, localA, localB);
+ code.returnValue(localResult);
+
+ Constructable constructed = (Constructable) getMethod().invoke(null, 5L, false);
+ assertEquals(5L, constructed.a);
+ assertEquals(false, constructed.b);
+ }
+
+ public static class Constructable {
+ private final long a;
+ private final boolean b;
+ public Constructable(long a, boolean b) {
+ this.a = a;
+ this.b = b;
+ }
+ }
+
+ public void testInvokeStatic() throws Exception {
+ /*
+ * public static int call(int a) {
+ * int result = DexGeneratorTest.staticMethod(a);
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localA = code.getParameter(0, Type.INT);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ MethodId<?, Integer> staticMethod
+ = TEST_TYPE.getMethod(Type.INT, "staticMethod", Type.INT);
+ code.invokeStatic(staticMethod, localResult, localA);
+ code.returnValue(localResult);
+
+ assertEquals(10, getMethod().invoke(null, 4));
+ }
+
+ @SuppressWarnings("unused") // called by generated code
+ public static int staticMethod(int a) {
+ return a + 6;
+ }
+
+ public void testInvokeVirtual() throws Exception {
+ /*
+ * public static int call(DexGeneratorTest test, int a) {
+ * int result = test.virtualMethod(a);
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", TEST_TYPE, Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<DexGeneratorTest> localInstance = code.getParameter(0, TEST_TYPE);
+ Local<Integer> localA = code.getParameter(1, Type.INT);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ MethodId<DexGeneratorTest, Integer> virtualMethod
+ = TEST_TYPE.getMethod(Type.INT, "virtualMethod", Type.INT);
+ code.invokeVirtual(virtualMethod, localResult, localInstance, localA);
+ code.returnValue(localResult);
+
+ assertEquals(9, getMethod().invoke(null, this, 4));
+ }
+
+ @SuppressWarnings("unused") // called by generated code
+ public int virtualMethod(int a) {
+ return a + 5;
+ }
+
+ public <G> void testInvokeDirect() throws Exception {
+ /*
+ * private int directMethod() {
+ * int a = 5;
+ * return a;
+ * }
+ *
+ * public static int call(Generated g) {
+ * int b = g.directMethod();
+ * return b;
+ * }
+ */
+ Type<G> generated = Type.get("LGenerated;");
+ MethodId<G, Integer> directMethodId = generated.getMethod(Type.INT, "directMethod");
+ Code directCode = generator.declare(directMethodId, ACC_PRIVATE);
+ directCode.getThis(generated); // 'this' is unused
+ Local<Integer> localA = directCode.newLocal(Type.INT);
+ directCode.loadConstant(localA, 5);
+ directCode.returnValue(localA);
+
+ MethodId<G, Integer> methodId = generated.getMethod(Type.INT, "call", generated);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localB = code.newLocal(Type.INT);
+ Local<G> localG = code.getParameter(0, generated);
+ code.invokeDirect(directMethodId, localB, localG);
+ code.returnValue(localB);
+
+ addDefaultConstructor();
+
+ Class<?> generatedClass = loadAndGenerate();
+ Object instance = generatedClass.newInstance();
+ Method method = generatedClass.getMethod("call", generatedClass);
+ assertEquals(5, method.invoke(null, instance));
+ }
+
+ public <G> void testInvokeSuper() throws Exception {
+ /*
+ * public int superHashCode() {
+ * int result = super.hashCode();
+ * return result;
+ * }
+ * public int hashCode() {
+ * return 0;
+ * }
+ */
+ Type<G> generated = Type.get("LGenerated;");
+ MethodId<Object, Integer> objectHashCode = Type.OBJECT.getMethod(Type.INT, "hashCode");
+ Code superHashCode = generator.declare(
+ GENERATED.getMethod(Type.INT, "superHashCode"), ACC_PUBLIC);
+ Local<Integer> localResult = superHashCode.newLocal(Type.INT);
+ Local<G> localThis = superHashCode.getThis(generated);
+ superHashCode.invokeSuper(objectHashCode, localResult, localThis);
+ superHashCode.returnValue(localResult);
+
+ Code generatedHashCode = generator.declare(
+ GENERATED.getMethod(Type.INT, "hashCode"), ACC_PUBLIC);
+ Local<Integer> localZero = generatedHashCode.newLocal(Type.INT);
+ generatedHashCode.loadConstant(localZero, 0);
+ generatedHashCode.returnValue(localZero);
+
+ addDefaultConstructor();
+
+ Class<?> generatedClass = loadAndGenerate();
+ Object instance = generatedClass.newInstance();
+ Method method = generatedClass.getMethod("superHashCode");
+ assertEquals(System.identityHashCode(instance), method.invoke(instance));
+ }
+
+ @SuppressWarnings("unused") // called by generated code
+ public int superMethod(int a) {
+ return a + 4;
+ }
+
+ public void testInvokeInterface() throws Exception {
+ /*
+ * public static Object call(Callable c) {
+ * Object result = c.call();
+ * return result;
+ * }
+ */
+ MethodId<?, Object> methodId = GENERATED.getMethod(Type.OBJECT, "call", CALLABLE);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Callable> localC = code.getParameter(0, CALLABLE);
+ Local<Object> localResult = code.newLocal(Type.OBJECT);
+ code.invokeInterface(CALL, localResult, localC);
+ code.returnValue(localResult);
+
+ Callable<Object> callable = new Callable<Object>() {
+ public Object call() throws Exception {
+ return "abc";
+ }
+ };
+ assertEquals("abc", getMethod().invoke(null, callable));
+ }
+
+ public void testParameterMismatch() throws Exception {
+ Type<?>[] argTypes = {
+ Type.get(Integer.class), // should fail because the code specifies int
+ Type.OBJECT,
+ };
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", argTypes);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ try {
+ code.getParameter(0, Type.INT);
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ code.getParameter(2, Type.INT);
+ } catch (IndexOutOfBoundsException e) {
+ }
+ }
+
+ public void testInvokeTypeSafety() throws Exception {
+ /*
+ * public static boolean call(DexGeneratorTest test) {
+ * CharSequence cs = test.toString();
+ * boolean result = cs.equals(test);
+ * return result;
+ * }
+ */
+ MethodId<?, Boolean> methodId = GENERATED.getMethod(Type.BOOLEAN, "call", TEST_TYPE);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<DexGeneratorTest> localTest = code.getParameter(0, TEST_TYPE);
+ Type<CharSequence> charSequenceType = Type.get(CharSequence.class);
+ MethodId<Object, String> objectToString = Type.OBJECT.getMethod(Type.STRING, "toString");
+ MethodId<Object, Boolean> objectEquals
+ = Type.OBJECT.getMethod(Type.BOOLEAN, "equals", Type.OBJECT);
+ Local<CharSequence> localCs = code.newLocal(charSequenceType);
+ Local<Boolean> localResult = code.newLocal(Type.BOOLEAN);
+ code.invokeVirtual(objectToString, localCs, localTest);
+ code.invokeVirtual(objectEquals, localResult, localCs, localTest);
+ code.returnValue(localResult);
+
+ assertEquals(false, getMethod().invoke(null, this));
+ }
+
+ public void testReturnTypeMismatch() {
+ MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call");
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ try {
+ code.returnValue(code.newLocal(Type.BOOLEAN));
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ code.returnVoid();
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testDeclareStaticFields() throws Exception {
+ /*
+ * class Generated {
+ * public static int a;
+ * protected static Object b;
+ * }
+ */
+ generator.declare(GENERATED.getField(Type.INT, "a"), ACC_PUBLIC | ACC_STATIC, 3);
+ generator.declare(GENERATED.getField(Type.OBJECT, "b"), ACC_PROTECTED | ACC_STATIC, null);
+ Class<?> generatedClass = loadAndGenerate();
+
+ Field a = generatedClass.getField("a");
+ assertEquals(int.class, a.getType());
+ assertEquals(3, a.get(null));
+
+ Field b = generatedClass.getDeclaredField("b");
+ assertEquals(Object.class, b.getType());
+ b.setAccessible(true);
+ assertEquals(null, b.get(null));
+ }
+
+ public void testDeclareInstanceFields() throws Exception {
+ /*
+ * class Generated {
+ * public int a;
+ * protected Object b;
+ * }
+ */
+ generator.declare(GENERATED.getField(Type.INT, "a"), ACC_PUBLIC, null);
+ generator.declare(GENERATED.getField(Type.OBJECT, "b"), ACC_PROTECTED, null);
+
+ addDefaultConstructor();
+
+ Class<?> generatedClass = loadAndGenerate();
+ Object instance = generatedClass.newInstance();
+
+ Field a = generatedClass.getField("a");
+ assertEquals(int.class, a.getType());
+ assertEquals(0, a.get(instance));
+
+ Field b = generatedClass.getDeclaredField("b");
+ assertEquals(Object.class, b.getType());
+ b.setAccessible(true);
+ assertEquals(null, b.get(instance));
+ }
+
+ /**
+ * Declare a constructor that takes an int parameter and assigns it to a
+ * field.
+ */
+ public <G> void testDeclareConstructor() throws Exception {
+ /*
+ * class Generated {
+ * public final int a;
+ * public Generated(int a) {
+ * this.a = a;
+ * }
+ * }
+ */
+ Type<G> generated = Type.get("LGenerated;");
+ FieldId<G, Integer> fieldId = generated.getField(Type.INT, "a");
+ generator.declare(fieldId, ACC_PUBLIC | ACC_FINAL, null);
+ MethodId<?, Void> constructor = GENERATED.getConstructor(Type.INT);
+ Code code = generator.declare(constructor, ACC_PUBLIC | ACC_CONSTRUCTOR);
+ Local<G> thisRef = code.getThis(generated);
+ Local<Integer> parameter = code.getParameter(0, Type.INT);
+ code.invokeDirect(Type.OBJECT.getConstructor(), null, thisRef);
+ code.iput(fieldId, thisRef, parameter);
+ code.returnVoid();
+
+ Class<?> generatedClass = loadAndGenerate();
+ Field a = generatedClass.getField("a");
+ Object instance = generatedClass.getConstructor(int.class).newInstance(0xabcd);
+ assertEquals(0xabcd, a.get(instance));
+ }
+
+ public void testReturnBoolean() throws Exception {
+ testReturnType(boolean.class, true);
+ testReturnType(byte.class, (byte) 5);
+ testReturnType(char.class, 'E');
+ testReturnType(double.class, 5.0);
+ testReturnType(float.class, 5.0f);
+ testReturnType(int.class, 5);
+ testReturnType(long.class, 5L);
+ testReturnType(short.class, (short) 5);
+ testReturnType(void.class, null);
+ testReturnType(String.class, "foo");
+ testReturnType(Class.class, List.class);
+ }
+
+ private <T> void testReturnType(Class<T> javaType, T value) throws Exception {
+ /*
+ * public int call() {
+ * int a = 5;
+ * return a;
+ * }
+ */
+ reset();
+ Type<T> returnType = Type.get(javaType);
+ Code code = generator.declare(GENERATED.getMethod(returnType, "call"),
+ ACC_PUBLIC | ACC_STATIC);
+ if (value != null) {
+ Local<T> i = code.newLocal(returnType);
+ code.loadConstant(i, value);
+ code.returnValue(i);
+ } else {
+ code.returnVoid();
+ }
+
+ Class<?> generatedClass = loadAndGenerate();
+ Method method = generatedClass.getMethod("call");
+ assertEquals(javaType, method.getReturnType());
+ assertEquals(value, method.invoke(null));
+ }
+
+ public void testBranching() throws Exception {
+ Method lt = branchingMethod(Comparison.LT);
+ assertEquals(Boolean.TRUE, lt.invoke(null, 1, 2));
+ assertEquals(Boolean.FALSE, lt.invoke(null, 1, 1));
+ assertEquals(Boolean.FALSE, lt.invoke(null, 2, 1));
+
+ Method le = branchingMethod(Comparison.LE);
+ assertEquals(Boolean.TRUE, le.invoke(null, 1, 2));
+ assertEquals(Boolean.TRUE, le.invoke(null, 1, 1));
+ assertEquals(Boolean.FALSE, le.invoke(null, 2, 1));
+
+ Method eq = branchingMethod(Comparison.EQ);
+ assertEquals(Boolean.FALSE, eq.invoke(null, 1, 2));
+ assertEquals(Boolean.TRUE, eq.invoke(null, 1, 1));
+ assertEquals(Boolean.FALSE, eq.invoke(null, 2, 1));
+
+ Method ge = branchingMethod(Comparison.GE);
+ assertEquals(Boolean.FALSE, ge.invoke(null, 1, 2));
+ assertEquals(Boolean.TRUE, ge.invoke(null, 1, 1));
+ assertEquals(Boolean.TRUE, ge.invoke(null, 2, 1));
+
+ Method gt = branchingMethod(Comparison.GT);
+ assertEquals(Boolean.FALSE, gt.invoke(null, 1, 2));
+ assertEquals(Boolean.FALSE, gt.invoke(null, 1, 1));
+ assertEquals(Boolean.TRUE, gt.invoke(null, 2, 1));
+
+ Method ne = branchingMethod(Comparison.NE);
+ assertEquals(Boolean.TRUE, ne.invoke(null, 1, 2));
+ assertEquals(Boolean.FALSE, ne.invoke(null, 1, 1));
+ assertEquals(Boolean.TRUE, ne.invoke(null, 2, 1));
+ }
+
+ private Method branchingMethod(Comparison comparison) throws Exception {
+ /*
+ * public static boolean call(int localA, int localB) {
+ * if (a comparison b) {
+ * return true;
+ * }
+ * return false;
+ * }
+ */
+ reset();
+ MethodId<?, Boolean> methodId = GENERATED.getMethod(
+ Type.BOOLEAN, "call", Type.INT, Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localA = code.getParameter(0, Type.INT);
+ Local<Integer> localB = code.getParameter(1, Type.INT);
+ Local<Boolean> result = code.newLocal(Type.get(boolean.class));
+ Label afterIf = code.newLabel();
+ Label ifBody = code.newLabel();
+ code.compare(comparison, localA, localB, ifBody);
+ code.jump(afterIf);
+
+ code.mark(ifBody);
+ code.loadConstant(result, true);
+ code.returnValue(result);
+
+ code.mark(afterIf);
+ code.loadConstant(result, false);
+ code.returnValue(result);
+ return getMethod();
+ }
+
+ public void testCastIntegerToInteger() throws Exception {
+ Method intToLong = numericCastingMethod(int.class, long.class);
+ assertEquals(0x0000000000000000L, intToLong.invoke(null, 0x00000000));
+ assertEquals(0x000000007fffffffL, intToLong.invoke(null, 0x7fffffff));
+ assertEquals(0xffffffff80000000L, intToLong.invoke(null, 0x80000000));
+ assertEquals(0xffffffffffffffffL, intToLong.invoke(null, 0xffffffff));
+
+ Method longToInt = numericCastingMethod(long.class, int.class);
+ assertEquals(0x1234abcd, longToInt.invoke(null, 0x000000001234abcdL));
+ assertEquals(0x1234abcd, longToInt.invoke(null, 0x123456781234abcdL));
+ assertEquals(0x1234abcd, longToInt.invoke(null, 0xffffffff1234abcdL));
+
+ Method intToShort = numericCastingMethod(int.class, short.class);
+ assertEquals((short) 0x1234, intToShort.invoke(null, 0x00001234));
+ assertEquals((short) 0x1234, intToShort.invoke(null, 0xabcd1234));
+ assertEquals((short) 0x1234, intToShort.invoke(null, 0xffff1234));
+
+ Method intToChar = numericCastingMethod(int.class, char.class);
+ assertEquals((char) 0x1234, intToChar.invoke(null, 0x00001234));
+ assertEquals((char) 0x1234, intToChar.invoke(null, 0xabcd1234));
+ assertEquals((char) 0x1234, intToChar.invoke(null, 0xffff1234));
+
+ Method intToByte = numericCastingMethod(int.class, byte.class);
+ assertEquals((byte) 0x34, intToByte.invoke(null, 0x00000034));
+ assertEquals((byte) 0x34, intToByte.invoke(null, 0xabcd1234));
+ assertEquals((byte) 0x34, intToByte.invoke(null, 0xffffff34));
+ }
+
+ public void testCastIntegerToFloatingPoint() throws Exception {
+ Method intToFloat = numericCastingMethod(int.class, float.class);
+ assertEquals(0.0f, intToFloat.invoke(null, 0));
+ assertEquals(-1.0f, intToFloat.invoke(null, -1));
+ assertEquals(16777216f, intToFloat.invoke(null, 16777216));
+ assertEquals(16777216f, intToFloat.invoke(null, 16777217)); // precision
+
+ Method intToDouble = numericCastingMethod(int.class, double.class);
+ assertEquals(0.0, intToDouble.invoke(null, 0));
+ assertEquals(-1.0, intToDouble.invoke(null, -1));
+ assertEquals(16777216.0, intToDouble.invoke(null, 16777216));
+ assertEquals(16777217.0, intToDouble.invoke(null, 16777217));
+
+ Method longToFloat = numericCastingMethod(long.class, float.class);
+ assertEquals(0.0f, longToFloat.invoke(null, 0L));
+ assertEquals(-1.0f, longToFloat.invoke(null, -1L));
+ assertEquals(16777216f, longToFloat.invoke(null, 16777216L));
+ assertEquals(16777216f, longToFloat.invoke(null, 16777217L));
+
+ Method longToDouble = numericCastingMethod(long.class, double.class);
+ assertEquals(0.0, longToDouble.invoke(null, 0L));
+ assertEquals(-1.0, longToDouble.invoke(null, -1L));
+ assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740992L));
+ assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740993L)); // precision
+ }
+
+ public void testCastFloatingPointToInteger() throws Exception {
+ Method floatToInt = numericCastingMethod(float.class, int.class);
+ assertEquals(0, floatToInt.invoke(null, 0.0f));
+ assertEquals(-1, floatToInt.invoke(null, -1.0f));
+ assertEquals(Integer.MAX_VALUE, floatToInt.invoke(null, 10e15f));
+ assertEquals(0, floatToInt.invoke(null, 0.5f));
+ assertEquals(Integer.MIN_VALUE, floatToInt.invoke(null, Float.NEGATIVE_INFINITY));
+ assertEquals(0, floatToInt.invoke(null, Float.NaN));
+
+ Method floatToLong = numericCastingMethod(float.class, long.class);
+ assertEquals(0L, floatToLong.invoke(null, 0.0f));
+ assertEquals(-1L, floatToLong.invoke(null, -1.0f));
+ assertEquals(10000000272564224L, floatToLong.invoke(null, 10e15f));
+ assertEquals(0L, floatToLong.invoke(null, 0.5f));
+ assertEquals(Long.MIN_VALUE, floatToLong.invoke(null, Float.NEGATIVE_INFINITY));
+ assertEquals(0L, floatToLong.invoke(null, Float.NaN));
+
+ Method doubleToInt = numericCastingMethod(double.class, int.class);
+ assertEquals(0, doubleToInt.invoke(null, 0.0));
+ assertEquals(-1, doubleToInt.invoke(null, -1.0));
+ assertEquals(Integer.MAX_VALUE, doubleToInt.invoke(null, 10e15));
+ assertEquals(0, doubleToInt.invoke(null, 0.5));
+ assertEquals(Integer.MIN_VALUE, doubleToInt.invoke(null, Double.NEGATIVE_INFINITY));
+ assertEquals(0, doubleToInt.invoke(null, Double.NaN));
+
+ Method doubleToLong = numericCastingMethod(double.class, long.class);
+ assertEquals(0L, doubleToLong.invoke(null, 0.0));
+ assertEquals(-1L, doubleToLong.invoke(null, -1.0));
+ assertEquals(10000000000000000L, doubleToLong.invoke(null, 10e15));
+ assertEquals(0L, doubleToLong.invoke(null, 0.5));
+ assertEquals(Long.MIN_VALUE, doubleToLong.invoke(null, Double.NEGATIVE_INFINITY));
+ assertEquals(0L, doubleToLong.invoke(null, Double.NaN));
+ }
+
+ public void testCastFloatingPointToFloatingPoint() throws Exception {
+ Method floatToDouble = numericCastingMethod(float.class, double.class);
+ assertEquals(0.0, floatToDouble.invoke(null, 0.0f));
+ assertEquals(-1.0, floatToDouble.invoke(null, -1.0f));
+ assertEquals(0.5, floatToDouble.invoke(null, 0.5f));
+ assertEquals(Double.NEGATIVE_INFINITY, floatToDouble.invoke(null, Float.NEGATIVE_INFINITY));
+ assertEquals(Double.NaN, floatToDouble.invoke(null, Float.NaN));
+
+ Method doubleToFloat = numericCastingMethod(double.class, float.class);
+ assertEquals(0.0f, doubleToFloat.invoke(null, 0.0));
+ assertEquals(-1.0f, doubleToFloat.invoke(null, -1.0));
+ assertEquals(0.5f, doubleToFloat.invoke(null, 0.5));
+ assertEquals(Float.NEGATIVE_INFINITY, doubleToFloat.invoke(null, Double.NEGATIVE_INFINITY));
+ assertEquals(Float.NaN, doubleToFloat.invoke(null, Double.NaN));
+ }
+
+ private Method numericCastingMethod(Class<?> source, Class<?> target)
+ throws Exception {
+ /*
+ * public static short call(int source) {
+ * short casted = (short) source;
+ * return casted;
+ * }
+ */
+ reset();
+ Type<?> sourceType = Type.get(source);
+ Type<?> targetType = Type.get(target);
+ MethodId<?, ?> methodId = GENERATED.getMethod(targetType, "call", sourceType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<?> localSource = code.getParameter(0, sourceType);
+ Local<?> localCasted = code.newLocal(targetType);
+ code.numericCast(localSource, localCasted);
+ code.returnValue(localCasted);
+ return getMethod();
+ }
+
+ public void testNot() throws Exception {
+ Method notInteger = notMethod(int.class);
+ assertEquals(0xffffffff, notInteger.invoke(null, 0x00000000));
+ assertEquals(0x00000000, notInteger.invoke(null, 0xffffffff));
+ assertEquals(0xedcba987, notInteger.invoke(null, 0x12345678));
+
+ Method notLong = notMethod(long.class);
+ assertEquals(0xffffffffffffffffL, notLong.invoke(null, 0x0000000000000000L));
+ assertEquals(0x0000000000000000L, notLong.invoke(null, 0xffffffffffffffffL));
+ assertEquals(0x98765432edcba987L, notLong.invoke(null, 0x6789abcd12345678L));
+ }
+
+ private <T> Method notMethod(Class<T> source) throws Exception {
+ /*
+ * public static short call(int source) {
+ * source = ~source;
+ * return not;
+ * }
+ */
+ reset();
+ Type<T> valueType = Type.get(source);
+ MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<T> localSource = code.getParameter(0, valueType);
+ code.not(localSource, localSource);
+ code.returnValue(localSource);
+ return getMethod();
+ }
+
+ public void testNegate() throws Exception {
+ Method negateInteger = negateMethod(int.class);
+ assertEquals(0, negateInteger.invoke(null, 0));
+ assertEquals(-1, negateInteger.invoke(null, 1));
+ assertEquals(Integer.MIN_VALUE, negateInteger.invoke(null, Integer.MIN_VALUE));
+
+ Method negateLong = negateMethod(long.class);
+ assertEquals(0L, negateLong.invoke(null, 0));
+ assertEquals(-1L, negateLong.invoke(null, 1));
+ assertEquals(Long.MIN_VALUE, negateLong.invoke(null, Long.MIN_VALUE));
+
+ Method negateFloat = negateMethod(float.class);
+ assertEquals(-0.0f, negateFloat.invoke(null, 0.0f));
+ assertEquals(-1.0f, negateFloat.invoke(null, 1.0f));
+ assertEquals(Float.NaN, negateFloat.invoke(null, Float.NaN));
+ assertEquals(Float.POSITIVE_INFINITY, negateFloat.invoke(null, Float.NEGATIVE_INFINITY));
+
+ Method negateDouble = negateMethod(double.class);
+ assertEquals(-0.0, negateDouble.invoke(null, 0.0));
+ assertEquals(-1.0, negateDouble.invoke(null, 1.0));
+ assertEquals(Double.NaN, negateDouble.invoke(null, Double.NaN));
+ assertEquals(Double.POSITIVE_INFINITY, negateDouble.invoke(null, Double.NEGATIVE_INFINITY));
+ }
+
+ private <T> Method negateMethod(Class<T> source) throws Exception {
+ /*
+ * public static short call(int source) {
+ * source = -source;
+ * return not;
+ * }
+ */
+ reset();
+ Type<T> valueType = Type.get(source);
+ MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<T> localSource = code.getParameter(0, valueType);
+ code.negate(localSource, localSource);
+ code.returnValue(localSource);
+ return getMethod();
+ }
+
+ public void testIntBinaryOps() throws Exception {
+ Method add = binaryOpMethod(int.class, BinaryOp.ADD);
+ assertEquals(79, add.invoke(null, 75, 4));
+
+ Method subtract = binaryOpMethod(int.class, BinaryOp.SUBTRACT);
+ assertEquals(71, subtract.invoke(null, 75, 4));
+
+ Method multiply = binaryOpMethod(int.class, BinaryOp.MULTIPLY);
+ assertEquals(300, multiply.invoke(null, 75, 4));
+
+ Method divide = binaryOpMethod(int.class, BinaryOp.DIVIDE);
+ assertEquals(18, divide.invoke(null, 75, 4));
+ try {
+ divide.invoke(null, 75, 0);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(ArithmeticException.class, expected.getCause().getClass());
+ }
+
+ Method remainder = binaryOpMethod(int.class, BinaryOp.REMAINDER);
+ assertEquals(3, remainder.invoke(null, 75, 4));
+ try {
+ remainder.invoke(null, 75, 0);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(ArithmeticException.class, expected.getCause().getClass());
+ }
+
+ Method and = binaryOpMethod(int.class, BinaryOp.AND);
+ assertEquals(0xff000000, and.invoke(null, 0xff00ff00, 0xffff0000));
+
+ Method or = binaryOpMethod(int.class, BinaryOp.OR);
+ assertEquals(0xffffff00, or.invoke(null, 0xff00ff00, 0xffff0000));
+
+ Method xor = binaryOpMethod(int.class, BinaryOp.XOR);
+ assertEquals(0x00ffff00, xor.invoke(null, 0xff00ff00, 0xffff0000));
+
+ Method shiftLeft = binaryOpMethod(int.class, BinaryOp.SHIFT_LEFT);
+ assertEquals(0xcd123400, shiftLeft.invoke(null, 0xabcd1234, 8));
+
+ Method shiftRight = binaryOpMethod(int.class, BinaryOp.SHIFT_RIGHT);
+ assertEquals(0xffabcd12, shiftRight.invoke(null, 0xabcd1234, 8));
+
+ Method unsignedShiftRight = binaryOpMethod(int.class,
+ BinaryOp.UNSIGNED_SHIFT_RIGHT);
+ assertEquals(0x00abcd12, unsignedShiftRight.invoke(null, 0xabcd1234, 8));
+ }
+
+ public void testLongBinaryOps() throws Exception {
+ Method add = binaryOpMethod(long.class, BinaryOp.ADD);
+ assertEquals(79L, add.invoke(null, 75L, 4L));
+
+ Method subtract = binaryOpMethod(long.class, BinaryOp.SUBTRACT);
+ assertEquals(71L, subtract.invoke(null, 75L, 4L));
+
+ Method multiply = binaryOpMethod(long.class, BinaryOp.MULTIPLY);
+ assertEquals(300L, multiply.invoke(null, 75L, 4L));
+
+ Method divide = binaryOpMethod(long.class, BinaryOp.DIVIDE);
+ assertEquals(18L, divide.invoke(null, 75L, 4L));
+ try {
+ divide.invoke(null, 75L, 0L);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(ArithmeticException.class, expected.getCause().getClass());
+ }
+
+ Method remainder = binaryOpMethod(long.class, BinaryOp.REMAINDER);
+ assertEquals(3L, remainder.invoke(null, 75L, 4L));
+ try {
+ remainder.invoke(null, 75L, 0L);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(ArithmeticException.class, expected.getCause().getClass());
+ }
+
+ Method and = binaryOpMethod(long.class, BinaryOp.AND);
+ assertEquals(0xff00ff0000000000L,
+ and.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L));
+
+ Method or = binaryOpMethod(long.class, BinaryOp.OR);
+ assertEquals(0xffffffffff00ff00L,
+ or.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L));
+
+ Method xor = binaryOpMethod(long.class, BinaryOp.XOR);
+ assertEquals(0x00ff00ffff00ff00L,
+ xor.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L));
+
+ Method shiftLeft = binaryOpMethod(long.class, BinaryOp.SHIFT_LEFT);
+ assertEquals(0xcdef012345678900L, shiftLeft.invoke(null, 0xabcdef0123456789L, 8L));
+
+ Method shiftRight = binaryOpMethod(long.class, BinaryOp.SHIFT_RIGHT);
+ assertEquals(0xffabcdef01234567L, shiftRight.invoke(null, 0xabcdef0123456789L, 8L));
+
+ Method unsignedShiftRight = binaryOpMethod(long.class,
+ BinaryOp.UNSIGNED_SHIFT_RIGHT);
+ assertEquals(0x00abcdef01234567L, unsignedShiftRight.invoke(null, 0xabcdef0123456789L, 8L));
+ }
+
+ public void testFloatBinaryOps() throws Exception {
+ Method add = binaryOpMethod(float.class, BinaryOp.ADD);
+ assertEquals(6.75f, add.invoke(null, 5.5f, 1.25f));
+
+ Method subtract = binaryOpMethod(float.class, BinaryOp.SUBTRACT);
+ assertEquals(4.25f, subtract.invoke(null, 5.5f, 1.25f));
+
+ Method multiply = binaryOpMethod(float.class, BinaryOp.MULTIPLY);
+ assertEquals(6.875f, multiply.invoke(null, 5.5f, 1.25f));
+
+ Method divide = binaryOpMethod(float.class, BinaryOp.DIVIDE);
+ assertEquals(4.4f, divide.invoke(null, 5.5f, 1.25f));
+ assertEquals(Float.POSITIVE_INFINITY, divide.invoke(null, 5.5f, 0.0f));
+
+ Method remainder = binaryOpMethod(float.class, BinaryOp.REMAINDER);
+ assertEquals(0.5f, remainder.invoke(null, 5.5f, 1.25f));
+ assertEquals(Float.NaN, remainder.invoke(null, 5.5f, 0.0f));
+ }
+
+ public void testDoubleBinaryOps() throws Exception {
+ Method add = binaryOpMethod(double.class, BinaryOp.ADD);
+ assertEquals(6.75, add.invoke(null, 5.5, 1.25));
+
+ Method subtract = binaryOpMethod(double.class, BinaryOp.SUBTRACT);
+ assertEquals(4.25, subtract.invoke(null, 5.5, 1.25));
+
+ Method multiply = binaryOpMethod(double.class, BinaryOp.MULTIPLY);
+ assertEquals(6.875, multiply.invoke(null, 5.5, 1.25));
+
+ Method divide = binaryOpMethod(double.class, BinaryOp.DIVIDE);
+ assertEquals(4.4, divide.invoke(null, 5.5, 1.25));
+ assertEquals(Double.POSITIVE_INFINITY, divide.invoke(null, 5.5, 0.0));
+
+ Method remainder = binaryOpMethod(double.class, BinaryOp.REMAINDER);
+ assertEquals(0.5, remainder.invoke(null, 5.5, 1.25));
+ assertEquals(Double.NaN, remainder.invoke(null, 5.5, 0.0));
+ }
+
+ private <T> Method binaryOpMethod(Class<T> valueClass, BinaryOp op)
+ throws Exception {
+ /*
+ * public static int binaryOp(int a, int b) {
+ * int result = a + b;
+ * return result;
+ * }
+ */
+ reset();
+ Type<T> valueType = Type.get(valueClass);
+ MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType, valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<T> localA = code.getParameter(0, valueType);
+ Local<T> localB = code.getParameter(1, valueType);
+ Local<T> localResult = code.newLocal(valueType);
+ code.op(op, localResult, localA, localB);
+ code.returnValue(localResult);
+ return getMethod();
+ }
+
+ public void testReadAndWriteInstanceFields() throws Exception {
+ Instance instance = new Instance();
+
+ Method intSwap = instanceSwapMethod(int.class, "intValue");
+ instance.intValue = 5;
+ assertEquals(5, intSwap.invoke(null, instance, 10));
+ assertEquals(10, instance.intValue);
+
+ Method longSwap = instanceSwapMethod(long.class, "longValue");
+ instance.longValue = 500L;
+ assertEquals(500L, longSwap.invoke(null, instance, 1234L));
+ assertEquals(1234L, instance.longValue);
+
+ Method booleanSwap = instanceSwapMethod(boolean.class, "booleanValue");
+ instance.booleanValue = false;
+ assertEquals(false, booleanSwap.invoke(null, instance, true));
+ assertEquals(true, instance.booleanValue);
+
+ Method floatSwap = instanceSwapMethod(float.class, "floatValue");
+ instance.floatValue = 1.5f;
+ assertEquals(1.5f, floatSwap.invoke(null, instance, 0.5f));
+ assertEquals(0.5f, instance.floatValue);
+
+ Method doubleSwap = instanceSwapMethod(double.class, "doubleValue");
+ instance.doubleValue = 155.5;
+ assertEquals(155.5, doubleSwap.invoke(null, instance, 266.6));
+ assertEquals(266.6, instance.doubleValue);
+
+ Method objectSwap = instanceSwapMethod(Object.class, "objectValue");
+ instance.objectValue = "before";
+ assertEquals("before", objectSwap.invoke(null, instance, "after"));
+ assertEquals("after", instance.objectValue);
+
+ Method byteSwap = instanceSwapMethod(byte.class, "byteValue");
+ instance.byteValue = 0x35;
+ assertEquals((byte) 0x35, byteSwap.invoke(null, instance, (byte) 0x64));
+ assertEquals((byte) 0x64, instance.byteValue);
+
+ Method charSwap = instanceSwapMethod(char.class, "charValue");
+ instance.charValue = 'A';
+ assertEquals('A', charSwap.invoke(null, instance, 'B'));
+ assertEquals('B', instance.charValue);
+
+ Method shortSwap = instanceSwapMethod(short.class, "shortValue");
+ instance.shortValue = (short) 0xabcd;
+ assertEquals((short) 0xabcd, shortSwap.invoke(null, instance, (short) 0x1234));
+ assertEquals((short) 0x1234, instance.shortValue);
+ }
+
+ public class Instance {
+ public int intValue;
+ public long longValue;
+ public float floatValue;
+ public double doubleValue;
+ public Object objectValue;
+ public boolean booleanValue;
+ public byte byteValue;
+ public char charValue;
+ public short shortValue;
+ }
+
+ private <V> Method instanceSwapMethod(
+ Class<V> valueClass, String fieldName) throws Exception {
+ /*
+ * public static int call(Instance instance, int newValue) {
+ * int oldValue = instance.intValue;
+ * instance.intValue = newValue;
+ * return oldValue;
+ * }
+ */
+ reset();
+ Type<V> valueType = Type.get(valueClass);
+ Type<Instance> objectType = Type.get(Instance.class);
+ FieldId<Instance, V> fieldId = objectType.getField(valueType, fieldName);
+ MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", objectType, valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Instance> localInstance = code.getParameter(0, objectType);
+ Local<V> localNewValue = code.getParameter(1, valueType);
+ Local<V> localOldValue = code.newLocal(valueType);
+ code.iget(fieldId, localInstance, localOldValue);
+ code.iput(fieldId, localInstance, localNewValue);
+ code.returnValue(localOldValue);
+ return getMethod();
+ }
+
+ public void testReadAndWriteStaticFields() throws Exception {
+ Method intSwap = staticSwapMethod(int.class, "intValue");
+ Static.intValue = 5;
+ assertEquals(5, intSwap.invoke(null, 10));
+ assertEquals(10, Static.intValue);
+
+ Method longSwap = staticSwapMethod(long.class, "longValue");
+ Static.longValue = 500L;
+ assertEquals(500L, longSwap.invoke(null, 1234L));
+ assertEquals(1234L, Static.longValue);
+
+ Method booleanSwap = staticSwapMethod(boolean.class, "booleanValue");
+ Static.booleanValue = false;
+ assertEquals(false, booleanSwap.invoke(null, true));
+ assertEquals(true, Static.booleanValue);
+
+ Method floatSwap = staticSwapMethod(float.class, "floatValue");
+ Static.floatValue = 1.5f;
+ assertEquals(1.5f, floatSwap.invoke(null, 0.5f));
+ assertEquals(0.5f, Static.floatValue);
+
+ Method doubleSwap = staticSwapMethod(double.class, "doubleValue");
+ Static.doubleValue = 155.5;
+ assertEquals(155.5, doubleSwap.invoke(null, 266.6));
+ assertEquals(266.6, Static.doubleValue);
+
+ Method objectSwap = staticSwapMethod(Object.class, "objectValue");
+ Static.objectValue = "before";
+ assertEquals("before", objectSwap.invoke(null, "after"));
+ assertEquals("after", Static.objectValue);
+
+ Method byteSwap = staticSwapMethod(byte.class, "byteValue");
+ Static.byteValue = 0x35;
+ assertEquals((byte) 0x35, byteSwap.invoke(null, (byte) 0x64));
+ assertEquals((byte) 0x64, Static.byteValue);
+
+ Method charSwap = staticSwapMethod(char.class, "charValue");
+ Static.charValue = 'A';
+ assertEquals('A', charSwap.invoke(null, 'B'));
+ assertEquals('B', Static.charValue);
+
+ Method shortSwap = staticSwapMethod(short.class, "shortValue");
+ Static.shortValue = (short) 0xabcd;
+ assertEquals((short) 0xabcd, shortSwap.invoke(null, (short) 0x1234));
+ assertEquals((short) 0x1234, Static.shortValue);
+ }
+
+ public static class Static {
+ public static int intValue;
+ public static long longValue;
+ public static float floatValue;
+ public static double doubleValue;
+ public static Object objectValue;
+ public static boolean booleanValue;
+ public static byte byteValue;
+ public static char charValue;
+ public static short shortValue;
+ }
+
+ private <V> Method staticSwapMethod(Class<V> valueClass, String fieldName)
+ throws Exception {
+ /*
+ * public static int call(int newValue) {
+ * int oldValue = Static.intValue;
+ * Static.intValue = newValue;
+ * return oldValue;
+ * }
+ */
+ reset();
+ Type<V> valueType = Type.get(valueClass);
+ Type<Static> objectType = Type.get(Static.class);
+ FieldId<Static, V> fieldId = objectType.getField(valueType, fieldName);
+ MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<V> localNewValue = code.getParameter(0, valueType);
+ Local<V> localOldValue = code.newLocal(valueType);
+ code.sget(fieldId, localOldValue);
+ code.sput(fieldId, localNewValue);
+ code.returnValue(localOldValue);
+ return getMethod();
+ }
+
+ public void testTypeCast() throws Exception {
+ /*
+ * public static String call(Object o) {
+ * String s = (String) o;
+ * }
+ */
+ MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call", Type.OBJECT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Object> localObject = code.getParameter(0, Type.OBJECT);
+ Local<String> localString = code.newLocal(Type.STRING);
+ code.typeCast(localObject, localString);
+ code.returnValue(localString);
+
+ Method method = getMethod();
+ assertEquals("s", method.invoke(null, "s"));
+ assertEquals(null, method.invoke(null, (String) null));
+ try {
+ method.invoke(null, 5);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(ClassCastException.class, expected.getCause().getClass());
+ }
+ }
+
+ public void testInstanceOf() throws Exception {
+ /*
+ * public static boolean call(Object o) {
+ * boolean result = o instanceof String;
+ * return result;
+ * }
+ */
+ MethodId<?, Boolean> methodId = GENERATED.getMethod(Type.BOOLEAN, "call", Type.OBJECT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Object> localObject = code.getParameter(0, Type.OBJECT);
+ Local<Boolean> localResult = code.newLocal(Type.BOOLEAN);
+ code.instanceOfType(localResult, localObject, Type.STRING);
+ code.returnValue(localResult);
+
+ Method method = getMethod();
+ assertEquals(true, method.invoke(null, "s"));
+ assertEquals(false, method.invoke(null, (String) null));
+ assertEquals(false, method.invoke(null, 5));
+ }
+
+ /**
+ * Tests that we can construct a for loop.
+ */
+ public void testForLoop() throws Exception {
+ /*
+ * public static int call(int count) {
+ * int result = 1;
+ * for (int i = 0; i < count; i += 1) {
+ * result = result * 2;
+ * }
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localCount = code.getParameter(0, Type.INT);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ Local<Integer> localI = code.newLocal(Type.INT);
+ Local<Integer> local1 = code.newLocal(Type.INT);
+ Local<Integer> local2 = code.newLocal(Type.INT);
+ code.loadConstant(local1, 1);
+ code.loadConstant(local2, 2);
+ code.loadConstant(localResult, 1);
+ code.loadConstant(localI, 0);
+ Label loopCondition = code.newLabel();
+ Label loopBody = code.newLabel();
+ Label afterLoop = code.newLabel();
+ code.mark(loopCondition);
+ code.compare(Comparison.LT, localI, localCount, loopBody);
+ code.jump(afterLoop);
+ code.mark(loopBody);
+ code.op(BinaryOp.MULTIPLY, localResult, localResult, local2);
+ code.op(BinaryOp.ADD, localI, localI, local1);
+ code.jump(loopCondition);
+ code.mark(afterLoop);
+ code.returnValue(localResult);
+
+ Method pow2 = getMethod();
+ assertEquals(1, pow2.invoke(null, 0));
+ assertEquals(2, pow2.invoke(null, 1));
+ assertEquals(4, pow2.invoke(null, 2));
+ assertEquals(8, pow2.invoke(null, 3));
+ assertEquals(16, pow2.invoke(null, 4));
+ }
+
+ /**
+ * Tests that we can construct a while loop.
+ */
+ public void testWhileLoop() throws Exception {
+ /*
+ * public static int call(int max) {
+ * int result = 1;
+ * while (result < max) {
+ * result = result * 2;
+ * }
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localMax = code.getParameter(0, Type.INT);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ Local<Integer> local2 = code.newLocal(Type.INT);
+ code.loadConstant(localResult, 1);
+ code.loadConstant(local2, 2);
+ Label loopCondition = code.newLabel();
+ Label loopBody = code.newLabel();
+ Label afterLoop = code.newLabel();
+ code.mark(loopCondition);
+ code.compare(Comparison.LT, localResult, localMax, loopBody);
+ code.jump(afterLoop);
+ code.mark(loopBody);
+ code.op(BinaryOp.MULTIPLY, localResult, localResult, local2);
+ code.jump(loopCondition);
+ code.mark(afterLoop);
+ code.returnValue(localResult);
+
+ Method ceilPow2 = getMethod();
+ assertEquals(1, ceilPow2.invoke(null, 1));
+ assertEquals(2, ceilPow2.invoke(null, 2));
+ assertEquals(4, ceilPow2.invoke(null, 3));
+ assertEquals(16, ceilPow2.invoke(null, 10));
+ assertEquals(128, ceilPow2.invoke(null, 100));
+ assertEquals(1024, ceilPow2.invoke(null, 1000));
+ }
+
+ public void testIfElseBlock() throws Exception {
+ /*
+ * public static int call(int a, int b, int c) {
+ * if (a < b) {
+ * if (a < c) {
+ * return a;
+ * } else {
+ * return c;
+ * }
+ * } else if (b < c) {
+ * return b;
+ * } else {
+ * return c;
+ * }
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(
+ Type.INT, "call", Type.INT, Type.INT, Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localA = code.getParameter(0, Type.INT);
+ Local<Integer> localB = code.getParameter(1, Type.INT);
+ Local<Integer> localC = code.getParameter(2, Type.INT);
+ Label aLessThanB = code.newLabel();
+ Label aLessThanC = code.newLabel();
+ Label bLessThanC = code.newLabel();
+ code.compare(Comparison.LT, localA, localB, aLessThanB);
+ code.compare(Comparison.LT, localB, localC, bLessThanC);
+ code.returnValue(localC);
+ // (a < b)
+ code.mark(aLessThanB);
+ code.compare(Comparison.LT, localA, localC, aLessThanC);
+ code.returnValue(localC);
+ // (a < c)
+ code.mark(aLessThanC);
+ code.returnValue(localA);
+ // (b < c)
+ code.mark(bLessThanC);
+ code.returnValue(localB);
+
+ Method min = getMethod();
+ assertEquals(1, min.invoke(null, 1, 2, 3));
+ assertEquals(1, min.invoke(null, 2, 3, 1));
+ assertEquals(1, min.invoke(null, 2, 1, 3));
+ assertEquals(1, min.invoke(null, 3, 2, 1));
+ }
+
+ public void testRecursion() throws Exception {
+ /*
+ * public static int call(int a) {
+ * if (a < 2) {
+ * return a;
+ * }
+ * a -= 1;
+ * int x = call(a)
+ * a -= 1;
+ * int y = call(a);
+ * int result = x + y;
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localA = code.getParameter(0, Type.INT);
+ Local<Integer> local1 = code.newLocal(Type.INT);
+ Local<Integer> local2 = code.newLocal(Type.INT);
+ Local<Integer> localX = code.newLocal(Type.INT);
+ Local<Integer> localY = code.newLocal(Type.INT);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ Label baseCase = code.newLabel();
+ code.loadConstant(local1, 1);
+ code.loadConstant(local2, 2);
+ code.compare(Comparison.LT, localA, local2, baseCase);
+ code.op(BinaryOp.SUBTRACT, localA, localA, local1);
+ code.invokeStatic(methodId, localX, localA);
+ code.op(BinaryOp.SUBTRACT, localA, localA, local1);
+ code.invokeStatic(methodId, localY, localA);
+ code.op(BinaryOp.ADD, localResult, localX, localY);
+ code.returnValue(localResult);
+ code.mark(baseCase);
+ code.returnValue(localA);
+
+ Method fib = getMethod();
+ assertEquals(0, fib.invoke(null, 0));
+ assertEquals(1, fib.invoke(null, 1));
+ assertEquals(1, fib.invoke(null, 2));
+ assertEquals(2, fib.invoke(null, 3));
+ assertEquals(3, fib.invoke(null, 4));
+ assertEquals(5, fib.invoke(null, 5));
+ assertEquals(8, fib.invoke(null, 6));
+ }
+
+ public void testCatchExceptions() throws Exception {
+ /*
+ * public static String call(int i) {
+ * try {
+ * DexGeneratorTest.thrower(i);
+ * return "NONE";
+ * } catch (IllegalArgumentException e) {
+ * return "IAE";
+ * } catch (IllegalStateException e) {
+ * return "ISE";
+ * } catch (RuntimeException e) {
+ * return "RE";
+ * }
+ */
+ MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localI = code.getParameter(0, Type.INT);
+ Local<String> result = code.newLocal(Type.STRING);
+ Label catchIae = code.newLabel();
+ Label catchIse = code.newLabel();
+ Label catchRe = code.newLabel();
+
+ code.addCatchClause(Type.get(IllegalArgumentException.class), catchIae);
+ code.addCatchClause(Type.get(IllegalStateException.class), catchIse);
+ code.addCatchClause(Type.get(RuntimeException.class), catchRe);
+ MethodId<?, ?> thrower = TEST_TYPE.getMethod(Type.VOID, "thrower", Type.INT);
+ code.invokeStatic(thrower, null, localI);
+ code.loadConstant(result, "NONE");
+ code.returnValue(result);
+
+ code.mark(catchIae);
+ code.loadConstant(result, "IAE");
+ code.returnValue(result);
+
+ code.mark(catchIse);
+ code.loadConstant(result, "ISE");
+ code.returnValue(result);
+
+ code.mark(catchRe);
+ code.loadConstant(result, "RE");
+ code.returnValue(result);
+
+ Method method = getMethod();
+ assertEquals("NONE", method.invoke(null, 0));
+ assertEquals("IAE", method.invoke(null, 1));
+ assertEquals("ISE", method.invoke(null, 2));
+ assertEquals("RE", method.invoke(null, 3));
+ try {
+ method.invoke(null, 4);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(IOException.class, expected.getCause().getClass());
+ }
+ }
+
+ @SuppressWarnings("unused") // called by generated code
+ public static void thrower(int a) throws Exception {
+ switch (a) {
+ case 0:
+ return;
+ case 1:
+ throw new IllegalArgumentException();
+ case 2:
+ throw new IllegalStateException();
+ case 3:
+ throw new UnsupportedOperationException();
+ case 4:
+ throw new IOException();
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public void testNestedCatchClauses() throws Exception {
+ /*
+ * public static String call(int a, int b, int c) {
+ * try {
+ * DexGeneratorTest.thrower(a);
+ * try {
+ * DexGeneratorTest.thrower(b);
+ * } catch (IllegalArgumentException) {
+ * return "INNER";
+ * }
+ * DexGeneratorTest.thrower(c);
+ * return "NONE";
+ * } catch (IllegalArgumentException e) {
+ * return "OUTER";
+ * }
+ */
+ MethodId<?, String> methodId = GENERATED.getMethod(
+ Type.STRING, "call", Type.INT, Type.INT, Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localA = code.getParameter(0, Type.INT);
+ Local<Integer> localB = code.getParameter(1, Type.INT);
+ Local<Integer> localC = code.getParameter(2, Type.INT);
+ Local<String> localResult = code.newLocal(Type.STRING);
+ Label catchInner = code.newLabel();
+ Label catchOuter = code.newLabel();
+
+ Type<IllegalArgumentException> iaeType = Type.get(IllegalArgumentException.class);
+ code.addCatchClause(iaeType, catchOuter);
+
+ MethodId<?, ?> thrower = TEST_TYPE.getMethod(Type.VOID, "thrower", Type.INT);
+ code.invokeStatic(thrower, null, localA);
+
+ // for the inner catch clause, we stash the old label and put it back afterwards.
+ Label previousLabel = code.removeCatchClause(iaeType);
+ code.addCatchClause(iaeType, catchInner);
+ code.invokeStatic(thrower, null, localB);
+ code.removeCatchClause(iaeType);
+ code.addCatchClause(iaeType, previousLabel);
+ code.invokeStatic(thrower, null, localC);
+ code.loadConstant(localResult, "NONE");
+ code.returnValue(localResult);
+
+ code.mark(catchInner);
+ code.loadConstant(localResult, "INNER");
+ code.returnValue(localResult);
+
+ code.mark(catchOuter);
+ code.loadConstant(localResult, "OUTER");
+ code.returnValue(localResult);
+
+ Method method = getMethod();
+ assertEquals("OUTER", method.invoke(null, 1, 0, 0));
+ assertEquals("INNER", method.invoke(null, 0, 1, 0));
+ assertEquals("OUTER", method.invoke(null, 0, 0, 1));
+ assertEquals("NONE", method.invoke(null, 0, 0, 0));
+ }
+
+ public void testThrow() throws Exception {
+ /*
+ * public static void call() {
+ * throw new IllegalStateException();
+ * }
+ */
+ MethodId<?, Void> methodId = GENERATED.getMethod(Type.VOID, "call");
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Type<IllegalStateException> iseType = Type.get(IllegalStateException.class);
+ MethodId<IllegalStateException, Void> iseConstructor = iseType.getConstructor();
+ Local<IllegalStateException> localIse = code.newLocal(iseType);
+ code.newInstance(localIse, iseConstructor);
+ code.throwValue(localIse);
+
+ try {
+ getMethod().invoke(null);
+ fail();
+ } catch (InvocationTargetException expected) {
+ assertEquals(IllegalStateException.class, expected.getCause().getClass());
+ }
+ }
+
+ public void testUnusedParameters() throws Exception {
+ /*
+ * public static void call(int unused1, long unused2, long unused3) {}
+ */
+ MethodId<?, Void> methodId = GENERATED.getMethod(
+ Type.VOID, "call", Type.INT, Type.LONG, Type.LONG);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ code.returnVoid();
+ getMethod().invoke(null, 1, 2, 3);
+ }
+
+ public void testFloatingPointCompare() throws Exception {
+ Method floatG = floatingPointCompareMethod(Type.FLOAT, 1);
+ assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY));
+ assertEquals(-1, floatG.invoke(null, 1.0f, 2.0f));
+ assertEquals(0, floatG.invoke(null, 1.0f, 1.0f));
+ assertEquals(1, floatG.invoke(null, 2.0f, 1.0f));
+ assertEquals(1, floatG.invoke(null, 1.0f, Float.NaN));
+ assertEquals(1, floatG.invoke(null, Float.NaN, 1.0f));
+ assertEquals(1, floatG.invoke(null, Float.NaN, Float.NaN));
+ assertEquals(1, floatG.invoke(null, Float.NaN, Float.POSITIVE_INFINITY));
+
+ Method floatL = floatingPointCompareMethod(Type.FLOAT, -1);
+ assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY));
+ assertEquals(-1, floatL.invoke(null, 1.0f, 2.0f));
+ assertEquals(0, floatL.invoke(null, 1.0f, 1.0f));
+ assertEquals(1, floatL.invoke(null, 2.0f, 1.0f));
+ assertEquals(-1, floatL.invoke(null, 1.0f, Float.NaN));
+ assertEquals(-1, floatL.invoke(null, Float.NaN, 1.0f));
+ assertEquals(-1, floatL.invoke(null, Float.NaN, Float.NaN));
+ assertEquals(-1, floatL.invoke(null, Float.NaN, Float.POSITIVE_INFINITY));
+
+ Method doubleG = floatingPointCompareMethod(Type.DOUBLE, 1);
+ assertEquals(-1, doubleG.invoke(null, 1.0, Double.POSITIVE_INFINITY));
+ assertEquals(-1, doubleG.invoke(null, 1.0, 2.0));
+ assertEquals(0, doubleG.invoke(null, 1.0, 1.0));
+ assertEquals(1, doubleG.invoke(null, 2.0, 1.0));
+ assertEquals(1, doubleG.invoke(null, 1.0, Double.NaN));
+ assertEquals(1, doubleG.invoke(null, Double.NaN, 1.0));
+ assertEquals(1, doubleG.invoke(null, Double.NaN, Double.NaN));
+ assertEquals(1, doubleG.invoke(null, Double.NaN, Double.POSITIVE_INFINITY));
+
+ Method doubleL = floatingPointCompareMethod(Type.DOUBLE, -1);
+ assertEquals(-1, doubleL.invoke(null, 1.0, Double.POSITIVE_INFINITY));
+ assertEquals(-1, doubleL.invoke(null, 1.0, 2.0));
+ assertEquals(0, doubleL.invoke(null, 1.0, 1.0));
+ assertEquals(1, doubleL.invoke(null, 2.0, 1.0));
+ assertEquals(-1, doubleL.invoke(null, 1.0, Double.NaN));
+ assertEquals(-1, doubleL.invoke(null, Double.NaN, 1.0));
+ assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.NaN));
+ assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.POSITIVE_INFINITY));
+ }
+
+ private <T extends Number> Method floatingPointCompareMethod(
+ Type<T> valueType, int nanValue) throws Exception {
+ /*
+ * public static int call(float a, float b) {
+ * int result = a <=> b;
+ * return result;
+ * }
+ */
+ reset();
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", valueType, valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<T> localA = code.getParameter(0, valueType);
+ Local<T> localB = code.getParameter(1, valueType);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ code.compare(localA, localB, localResult, nanValue);
+ code.returnValue(localResult);
+ return getMethod();
+ }
+
+ public void testLongCompare() throws Exception {
+ /*
+ * public static int call(long a, long b) {
+ * int result = a <=> b;
+ * return result;
+ * }
+ */
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.LONG, Type.LONG);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Long> localA = code.getParameter(0, Type.LONG);
+ Local<Long> localB = code.getParameter(1, Type.LONG);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ code.compare(localA, localB, localResult);
+ code.returnValue(localResult);
+
+ Method method = getMethod();
+ assertEquals(0, method.invoke(null, Long.MIN_VALUE, Long.MIN_VALUE));
+ assertEquals(-1, method.invoke(null, Long.MIN_VALUE, 0));
+ assertEquals(-1, method.invoke(null, Long.MIN_VALUE, Long.MAX_VALUE));
+ assertEquals(1, method.invoke(null, 0, Long.MIN_VALUE));
+ assertEquals(0, method.invoke(null, 0, 0));
+ assertEquals(-1, method.invoke(null, 0, Long.MAX_VALUE));
+ assertEquals(1, method.invoke(null, Long.MAX_VALUE, Long.MIN_VALUE));
+ assertEquals(1, method.invoke(null, Long.MAX_VALUE, 0));
+ assertEquals(0, method.invoke(null, Long.MAX_VALUE, Long.MAX_VALUE));
+ }
+
+ public void testArrayLength() throws Exception {
+ Method booleanArrayLength = arrayLengthMethod(BOOLEAN_ARRAY);
+ assertEquals(0, booleanArrayLength.invoke(null, new Object[] { new boolean[0] }));
+ assertEquals(5, booleanArrayLength.invoke(null, new Object[] { new boolean[5] }));
+
+ Method intArrayLength = arrayLengthMethod(INT_ARRAY);
+ assertEquals(0, intArrayLength.invoke(null, new Object[] { new int[0] }));
+ assertEquals(5, intArrayLength.invoke(null, new Object[] { new int[5] }));
+
+ Method longArrayLength = arrayLengthMethod(LONG_ARRAY);
+ assertEquals(0, longArrayLength.invoke(null, new Object[] { new long[0] }));
+ assertEquals(5, longArrayLength.invoke(null, new Object[] { new long[5] }));
+
+ Method objectArrayLength = arrayLengthMethod(OBJECT_ARRAY);
+ assertEquals(0, objectArrayLength.invoke(null, new Object[] { new Object[0] }));
+ assertEquals(5, objectArrayLength.invoke(null, new Object[] { new Object[5] }));
+
+ Method long2dArrayLength = arrayLengthMethod(LONG_2D_ARRAY);
+ assertEquals(0, long2dArrayLength.invoke(null, new Object[] { new long[0][0] }));
+ assertEquals(5, long2dArrayLength.invoke(null, new Object[] { new long[5][10] }));
+ }
+
+ private <T> Method arrayLengthMethod(Type<T> valueType) throws Exception {
+ /*
+ * public static int call(long[] array) {
+ * int result = array.length;
+ * return result;
+ * }
+ */
+ reset();
+ MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", valueType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<T> localArray = code.getParameter(0, valueType);
+ Local<Integer> localResult = code.newLocal(Type.INT);
+ code.arrayLength(localArray, localResult);
+ code.returnValue(localResult);
+ return getMethod();
+ }
+
+ public void testNewArray() throws Exception {
+ Method newBooleanArray = newArrayMethod(BOOLEAN_ARRAY);
+ assertEquals("[]", Arrays.toString((boolean[]) newBooleanArray.invoke(null, 0)));
+ assertEquals("[false, false, false]",
+ Arrays.toString((boolean[]) newBooleanArray.invoke(null, 3)));
+
+ Method newIntArray = newArrayMethod(INT_ARRAY);
+ assertEquals("[]", Arrays.toString((int[]) newIntArray.invoke(null, 0)));
+ assertEquals("[0, 0, 0]", Arrays.toString((int[]) newIntArray.invoke(null, 3)));
+
+ Method newLongArray = newArrayMethod(LONG_ARRAY);
+ assertEquals("[]", Arrays.toString((long[]) newLongArray.invoke(null, 0)));
+ assertEquals("[0, 0, 0]", Arrays.toString((long[]) newLongArray.invoke(null, 3)));
+
+ Method newObjectArray = newArrayMethod(OBJECT_ARRAY);
+ assertEquals("[]", Arrays.toString((Object[]) newObjectArray.invoke(null, 0)));
+ assertEquals("[null, null, null]",
+ Arrays.toString((Object[]) newObjectArray.invoke(null, 3)));
+
+ Method new2dLongArray = newArrayMethod(LONG_2D_ARRAY);
+ assertEquals("[]", Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 0)));
+ assertEquals("[null, null, null]",
+ Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 3)));
+ }
+
+ private <T> Method newArrayMethod(Type<T> valueType) throws Exception {
+ /*
+ * public static long[] call(int length) {
+ * long[] result = new long[length];
+ * return result;
+ * }
+ */
+ reset();
+ MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", Type.INT);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<Integer> localLength = code.getParameter(0, Type.INT);
+ Local<T> localResult = code.newLocal(valueType);
+ code.newArray(localLength, localResult);
+ code.returnValue(localResult);
+ return getMethod();
+ }
+
+ public void testReadAndWriteArray() throws Exception {
+ Method swapBooleanArray = arraySwapMethod(BOOLEAN_ARRAY, Type.BOOLEAN);
+ boolean[] booleans = new boolean[3];
+ assertEquals(false, swapBooleanArray.invoke(null, booleans, 1, true));
+ assertEquals("[false, true, false]", Arrays.toString(booleans));
+
+ Method swapIntArray = arraySwapMethod(INT_ARRAY, Type.INT);
+ int[] ints = new int[3];
+ assertEquals(0, swapIntArray.invoke(null, ints, 1, 5));
+ assertEquals("[0, 5, 0]", Arrays.toString(ints));
+
+ Method swapLongArray = arraySwapMethod(LONG_ARRAY, Type.LONG);
+ long[] longs = new long[3];
+ assertEquals(0L, swapLongArray.invoke(null, longs, 1, 6L));
+ assertEquals("[0, 6, 0]", Arrays.toString(longs));
+
+ Method swapObjectArray = arraySwapMethod(OBJECT_ARRAY, Type.OBJECT);
+ Object[] objects = new Object[3];
+ assertEquals(null, swapObjectArray.invoke(null, objects, 1, "X"));
+ assertEquals("[null, X, null]", Arrays.toString(objects));
+
+ Method swapLong2dArray = arraySwapMethod(LONG_2D_ARRAY, LONG_ARRAY);
+ long[][] longs2d = new long[3][];
+ assertEquals(null, swapLong2dArray.invoke(null, longs2d, 1, new long[] { 7 }));
+ assertEquals("[null, [7], null]", Arrays.deepToString(longs2d));
+ }
+
+ private <A, T> Method arraySwapMethod(Type<A> arrayType, Type<T> singleType)
+ throws Exception {
+ /*
+ * public static long swap(long[] array, int index, long newValue) {
+ * long result = array[index];
+ * array[index] = newValue;
+ * return result;
+ * }
+ */
+ reset();
+ MethodId<?, T> methodId = GENERATED.getMethod(
+ singleType, "call", arrayType, Type.INT, singleType);
+ Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC);
+ Local<A> localArray = code.getParameter(0, arrayType);
+ Local<Integer> localIndex = code.getParameter(1, Type.INT);
+ Local<T> localNewValue = code.getParameter(2, singleType);
+ Local<T> localResult = code.newLocal(singleType);
+ code.aget(localArray, localIndex, localResult);
+ code.aput(localArray, localIndex, localNewValue);
+ code.returnValue(localResult);
+ return getMethod();
+ }
+
+ // TODO: fail if a label is unreachable (never navigated to)
+
+ // TODO: more strict type parameters: Integer on methods
+
+ // TODO: don't generate multiple times (?)
+
+ private void addDefaultConstructor() {
+ Code code = generator.declare(GENERATED.getConstructor(), ACC_PUBLIC | ACC_CONSTRUCTOR);
+ Local<?> thisRef = code.getThis(GENERATED);
+ code.invokeDirect(Type.OBJECT.getConstructor(), null, thisRef);
+ code.returnVoid();
+ }
+
+ /**
+ * Returns the generated method.
+ */
+ private Method getMethod() throws Exception {
+ Class<?> generated = loadAndGenerate();
+ for (Method method : generated.getMethods()) {
+ if (method.getName().equals("call")) {
+ return method;
+ }
+ }
+ throw new IllegalStateException("no call() method");
+ }
+
+ private Class<?> loadAndGenerate() throws IOException, ClassNotFoundException {
+ return generator.load(DexGeneratorTest.class.getClassLoader()).loadClass("Generated");
+ }
+}
diff --git a/dx/junit-tests/com/android/dx/gen/TypeTest.java b/dx/junit-tests/com/android/dx/gen/TypeTest.java
new file mode 100644
index 0000000..c2f4f04
--- /dev/null
+++ b/dx/junit-tests/com/android/dx/gen/TypeTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import junit.framework.TestCase;
+
+public final class TypeTest extends TestCase {
+
+ private final DexGenerator generator = new DexGenerator();
+
+ public void testGetType() {
+ assertEquals("Ljava/lang/String;", Type.get(String.class).getName());
+ assertEquals("[Ljava/lang/String;", Type.get(String[].class).getName());
+ assertEquals("[[Ljava/lang/String;", Type.get(String[][].class).getName());
+ assertEquals("I", Type.get(int.class).getName());
+ assertEquals("[I", Type.get(int[].class).getName());
+ assertEquals("[[I", Type.get(int[][].class).getName());
+ }
+}
diff --git a/dx/src/com/android/dx/cf/attrib/AttSignature.java b/dx/src/com/android/dx/cf/attrib/AttSignature.java
index f6023f3..52def9c 100644
--- a/dx/src/com/android/dx/cf/attrib/AttSignature.java
+++ b/dx/src/com/android/dx/cf/attrib/AttSignature.java
@@ -16,7 +16,7 @@
package com.android.dx.cf.attrib;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
/**
* Attribute class for standards-track {@code Signature} attributes.
@@ -26,14 +26,14 @@
public static final String ATTRIBUTE_NAME = "Signature";
/** {@code non-null;} the signature string */
- private final CstUtf8 signature;
+ private final CstString signature;
/**
* Constructs an instance.
*
* @param signature {@code non-null;} the signature string
*/
- public AttSignature(CstUtf8 signature) {
+ public AttSignature(CstString signature) {
super(ATTRIBUTE_NAME);
if (signature == null) {
@@ -53,7 +53,7 @@
*
* @return {@code non-null;} the signature string
*/
- public CstUtf8 getSignature() {
+ public CstString getSignature() {
return signature;
}
}
diff --git a/dx/src/com/android/dx/cf/attrib/AttSourceFile.java b/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
index b84ff4d..cc19d27 100644
--- a/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
+++ b/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
@@ -16,7 +16,7 @@
package com.android.dx.cf.attrib;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
/**
* Attribute class for standard {@code SourceFile} attributes.
@@ -26,14 +26,14 @@
public static final String ATTRIBUTE_NAME = "SourceFile";
/** {@code non-null;} name of the source file */
- private final CstUtf8 sourceFile;
+ private final CstString sourceFile;
/**
* Constructs an instance.
*
* @param sourceFile {@code non-null;} the name of the source file
*/
- public AttSourceFile(CstUtf8 sourceFile) {
+ public AttSourceFile(CstString sourceFile) {
super(ATTRIBUTE_NAME);
if (sourceFile == null) {
@@ -53,7 +53,7 @@
*
* @return {@code non-null;} the source file
*/
- public CstUtf8 getSourceFile() {
+ public CstString getSourceFile() {
return sourceFile;
}
}
diff --git a/dx/src/com/android/dx/cf/attrib/InnerClassList.java b/dx/src/com/android/dx/cf/attrib/InnerClassList.java
index 96e1b60..830118c 100644
--- a/dx/src/com/android/dx/cf/attrib/InnerClassList.java
+++ b/dx/src/com/android/dx/cf/attrib/InnerClassList.java
@@ -16,8 +16,8 @@
package com.android.dx.cf.attrib;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.FixedSizeList;
/**
@@ -56,7 +56,7 @@
* @param accessFlags original declared access flags
*/
public void set(int n, CstType innerClass, CstType outerClass,
- CstUtf8 innerName, int accessFlags) {
+ CstString innerName, int accessFlags) {
set0(n, new Item(innerClass, outerClass, innerName, accessFlags));
}
@@ -71,7 +71,7 @@
private final CstType outerClass;
/** {@code null-ok;} original simple name of this class, if not anonymous */
- private final CstUtf8 innerName;
+ private final CstString innerName;
/** original declared access flags */
private final int accessFlags;
@@ -87,7 +87,7 @@
* @param accessFlags original declared access flags
*/
public Item(CstType innerClass, CstType outerClass,
- CstUtf8 innerName, int accessFlags) {
+ CstString innerName, int accessFlags) {
if (innerClass == null) {
throw new NullPointerException("innerClass == null");
}
@@ -121,7 +121,7 @@
*
* @return {@code null-ok;} the name
*/
- public CstUtf8 getInnerName() {
+ public CstString getInnerName() {
return innerName;
}
diff --git a/dx/src/com/android/dx/cf/code/BasicBlocker.java b/dx/src/com/android/dx/cf/code/BasicBlocker.java
index 8fb9560..56d3991 100644
--- a/dx/src/com/android/dx/cf/code/BasicBlocker.java
+++ b/dx/src/com/android/dx/cf/code/BasicBlocker.java
@@ -18,8 +18,8 @@
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstMemberRef;
-import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.util.Bits;
import com.android.dx.util.IntList;
diff --git a/dx/src/com/android/dx/cf/code/ConcreteMethod.java b/dx/src/com/android/dx/cf/code/ConcreteMethod.java
index da6cff7..39c2399 100644
--- a/dx/src/com/android/dx/cf/code/ConcreteMethod.java
+++ b/dx/src/com/android/dx/cf/code/ConcreteMethod.java
@@ -20,15 +20,14 @@
import com.android.dx.cf.attrib.AttLineNumberTable;
import com.android.dx.cf.attrib.AttLocalVariableTable;
import com.android.dx.cf.attrib.AttLocalVariableTypeTable;
-import com.android.dx.cf.attrib.AttSourceFile;
import com.android.dx.cf.iface.AttributeList;
import com.android.dx.cf.iface.ClassFile;
import com.android.dx.cf.iface.Method;
import com.android.dx.rop.code.AccessFlags;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Prototype;
/**
@@ -45,7 +44,7 @@
* {@code null-ok;} the class's {@code SourceFile} attribute value,
* if any
*/
- private final CstUtf8 sourceFile;
+ private final CstString sourceFile;
/**
* whether the class that this method is part of is defined with
@@ -72,11 +71,15 @@
* @param keepLocals whether to keep the local variable
* information (if any)
*/
- public ConcreteMethod(Method method, ClassFile cf, boolean keepLines,
- boolean keepLocals) {
+ public ConcreteMethod(Method method, ClassFile cf, boolean keepLines, boolean keepLocals) {
+ this(method, cf.getAccessFlags(), cf.getSourceFile(), keepLines, keepLocals);
+ }
+
+ public ConcreteMethod(Method method, int accessFlags, CstString sourceFile,
+ boolean keepLines, boolean keepLocals) {
this.method = method;
- this.accSuper = (cf.getAccessFlags() & AccessFlags.ACC_SUPER) != 0;
- this.sourceFile = cf.getSourceFile();
+ this.accSuper = (accessFlags & AccessFlags.ACC_SUPER) != 0;
+ this.sourceFile = sourceFile;
AttributeList attribs = method.getAttributes();
this.attCode = (AttCode) attribs.findFirst(AttCode.ATTRIBUTE_NAME);
@@ -147,12 +150,12 @@
}
/** {@inheritDoc} */
- public CstUtf8 getName() {
+ public CstString getName() {
return method.getName();
}
/** {@inheritDoc} */
- public CstUtf8 getDescriptor() {
+ public CstString getDescriptor() {
return method.getDescriptor();
}
diff --git a/dx/src/com/android/dx/cf/code/LocalVariableList.java b/dx/src/com/android/dx/cf/code/LocalVariableList.java
index dbf8ba2..2962698 100644
--- a/dx/src/com/android/dx/cf/code/LocalVariableList.java
+++ b/dx/src/com/android/dx/cf/code/LocalVariableList.java
@@ -16,7 +16,7 @@
package com.android.dx.cf.code;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.code.LocalItem;
import com.android.dx.util.FixedSizeList;
@@ -84,7 +84,7 @@
Item item = descriptorList.get(i);
Item signatureItem = signatureList.itemToLocal(item);
if (signatureItem != null) {
- CstUtf8 signature = signatureItem.getSignature();
+ CstString signature = signatureItem.getSignature();
item = item.withSignature(signature);
}
result.set(i, item);
@@ -142,8 +142,8 @@
* @param signature {@code null-ok;} the variable's type signature
* @param index {@code >= 0;} the variable's local index
*/
- public void set(int n, int startPc, int length, CstUtf8 name,
- CstUtf8 descriptor, CstUtf8 signature, int index) {
+ public void set(int n, int startPc, int length, CstString name,
+ CstString descriptor, CstString signature, int index) {
set0(n, new Item(startPc, length, name, descriptor, signature, index));
}
@@ -207,13 +207,13 @@
private final int length;
/** {@code non-null;} the variable's name */
- private final CstUtf8 name;
+ private final CstString name;
/** {@code null-ok;} the variable's type descriptor */
- private final CstUtf8 descriptor;
+ private final CstString descriptor;
/** {@code null-ok;} the variable's type signature */
- private final CstUtf8 signature;
+ private final CstString signature;
/** {@code >= 0;} the variable's local index */
private final int index;
@@ -232,8 +232,8 @@
* @param signature {@code null-ok;} the variable's type signature
* @param index {@code >= 0;} the variable's local index
*/
- public Item(int startPc, int length, CstUtf8 name,
- CstUtf8 descriptor, CstUtf8 signature, int index) {
+ public Item(int startPc, int length, CstString name,
+ CstString descriptor, CstString signature, int index) {
if (startPc < 0) {
throw new IllegalArgumentException("startPc < 0");
}
@@ -286,7 +286,7 @@
*
* @return {@code null-ok;} the variable's type descriptor
*/
- public CstUtf8 getDescriptor() {
+ public CstString getDescriptor() {
return descriptor;
}
@@ -305,7 +305,7 @@
*
* @return {@code null-ok;} the variable's type signature
*/
- private CstUtf8 getSignature() {
+ private CstString getSignature() {
return signature;
}
@@ -335,7 +335,7 @@
* @param newSignature {@code non-null;} the new signature
* @return {@code non-null;} an appropriately-constructed instance
*/
- public Item withSignature(CstUtf8 newSignature) {
+ public Item withSignature(CstString newSignature) {
return new Item(startPc, length, name, descriptor, newSignature,
index);
}
diff --git a/dx/src/com/android/dx/cf/code/RopperMachine.java b/dx/src/com/android/dx/cf/code/RopperMachine.java
index 5da2588..f45bc1f 100644
--- a/dx/src/com/android/dx/cf/code/RopperMachine.java
+++ b/dx/src/com/android/dx/cf/code/RopperMachine.java
@@ -35,8 +35,8 @@
import com.android.dx.rop.cst.CstInteger;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeBearer;
import com.android.dx.rop.type.TypeList;
@@ -58,8 +58,8 @@
*/
private static final CstMethodRef MULTIANEWARRAY_METHOD =
new CstMethodRef(ARRAY_REFLECT_TYPE,
- new CstNat(new CstUtf8("newInstance"),
- new CstUtf8("(Ljava/lang/Class;[I)" +
+ new CstNat(new CstString("newInstance"),
+ new CstString("(Ljava/lang/Class;[I)" +
"Ljava/lang/Object;")));
/** {@code non-null;} {@link Ropper} controlling this instance */
diff --git a/dx/src/com/android/dx/cf/code/Simulator.java b/dx/src/com/android/dx/cf/code/Simulator.java
index eedc379..c097831 100644
--- a/dx/src/com/android/dx/cf/code/Simulator.java
+++ b/dx/src/com/android/dx/cf/code/Simulator.java
@@ -22,15 +22,11 @@
import com.android.dx.rop.cst.CstInterfaceMethodRef;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.Type;
-import com.android.dx.rop.type.TypeBearer;
import com.android.dx.rop.code.LocalItem;
import com.android.dx.util.Hex;
-import com.android.dx.util.IntList;
-import java.util.List;
import java.util.ArrayList;
/**
diff --git a/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java b/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
index 5eecfa6..7ec2fba 100644
--- a/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
+++ b/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
@@ -16,6 +16,17 @@
package com.android.dx.cf.cst;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Class;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Double;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Fieldref;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Float;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Integer;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_InterfaceMethodref;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Long;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Methodref;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_NameAndType;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_String;
+import static com.android.dx.cf.cst.ConstantTags.CONSTANT_Utf8;
import com.android.dx.cf.iface.ParseException;
import com.android.dx.cf.iface.ParseObserver;
import com.android.dx.rop.cst.Constant;
@@ -29,13 +40,11 @@
import com.android.dx.rop.cst.CstNat;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.cst.StdConstantPool;
import com.android.dx.rop.type.Type;
import com.android.dx.util.ByteArray;
import com.android.dx.util.Hex;
-
-import static com.android.dx.cf.cst.ConstantTags.*;
+import java.util.BitSet;
/**
* Parser for a constant pool embedded in a class file.
@@ -126,10 +135,16 @@
observer.changeIndent(1);
}
+ /*
+ * Track the constant value's original string type. True if constants[i] was
+ * a CONSTANT_Utf8, false for any other type including CONSTANT_string.
+ */
+ BitSet wasUtf8 = new BitSet(offsets.length);
+
for (int i = 1; i < offsets.length; i++) {
int offset = offsets[i];
if ((offset != 0) && (pool.getOrNull(i) == null)) {
- parse0(i);
+ parse0(i, wasUtf8);
}
}
@@ -148,8 +163,10 @@
break;
}
}
- observer.parsed(bytes, offset, nextOffset - offset,
- Hex.u2(i) + ": " + cst.toString());
+ String human = wasUtf8.get(i)
+ ? Hex.u2(i) + ": utf8{\"" + cst.toHuman() + "\"}"
+ : Hex.u2(i) + ": " + cst.toString();
+ observer.parsed(bytes, offset, nextOffset - offset, human);
}
observer.changeIndent(-1);
@@ -217,7 +234,7 @@
* @param idx which constant
* @return {@code non-null;} the parsed constant
*/
- private Constant parse0(int idx) {
+ private Constant parse0(int idx, BitSet wasUtf8) {
Constant cst = pool.getOrNull(idx);
if (cst != null) {
return cst;
@@ -230,6 +247,7 @@
switch (tag) {
case CONSTANT_Utf8: {
cst = parseUtf8(at);
+ wasUtf8.set(idx);
break;
}
case CONSTANT_Integer: {
@@ -254,45 +272,44 @@
}
case CONSTANT_Class: {
int nameIndex = bytes.getUnsignedShort(at + 1);
- CstUtf8 name = (CstUtf8) parse0(nameIndex);
+ CstString name = (CstString) parse0(nameIndex, wasUtf8);
cst = new CstType(Type.internClassName(name.getString()));
break;
}
case CONSTANT_String: {
int stringIndex = bytes.getUnsignedShort(at + 1);
- CstUtf8 string = (CstUtf8) parse0(stringIndex);
- cst = new CstString(string);
+ cst = parse0(stringIndex, wasUtf8);
break;
}
case CONSTANT_Fieldref: {
int classIndex = bytes.getUnsignedShort(at + 1);
- CstType type = (CstType) parse0(classIndex);
+ CstType type = (CstType) parse0(classIndex, wasUtf8);
int natIndex = bytes.getUnsignedShort(at + 3);
- CstNat nat = (CstNat) parse0(natIndex);
+ CstNat nat = (CstNat) parse0(natIndex, wasUtf8);
cst = new CstFieldRef(type, nat);
break;
}
case CONSTANT_Methodref: {
int classIndex = bytes.getUnsignedShort(at + 1);
- CstType type = (CstType) parse0(classIndex);
+ CstType type = (CstType) parse0(classIndex, wasUtf8);
int natIndex = bytes.getUnsignedShort(at + 3);
- CstNat nat = (CstNat) parse0(natIndex);
+ CstNat nat = (CstNat) parse0(natIndex, wasUtf8);
cst = new CstMethodRef(type, nat);
break;
}
case CONSTANT_InterfaceMethodref: {
int classIndex = bytes.getUnsignedShort(at + 1);
- CstType type = (CstType) parse0(classIndex);
+ CstType type = (CstType) parse0(classIndex, wasUtf8);
int natIndex = bytes.getUnsignedShort(at + 3);
- CstNat nat = (CstNat) parse0(natIndex);
+ CstNat nat = (CstNat) parse0(natIndex, wasUtf8);
cst = new CstInterfaceMethodRef(type, nat);
break;
}
case CONSTANT_NameAndType: {
int nameIndex = bytes.getUnsignedShort(at + 1);
- CstUtf8 name = (CstUtf8) parse0(nameIndex);
+ CstString name = (CstString) parse0(nameIndex, wasUtf8);
int descriptorIndex = bytes.getUnsignedShort(at + 3);
- CstUtf8 descriptor = (CstUtf8) parse0(descriptorIndex);
+ CstString descriptor = (CstString) parse0(descriptorIndex, wasUtf8);
cst = new CstNat(name, descriptor);
break;
}
@@ -318,7 +335,7 @@
* @param at offset to the start of the constant (where the tag byte is)
* @return {@code non-null;} the parsed value
*/
- private CstUtf8 parseUtf8(int at) {
+ private CstString parseUtf8(int at) {
int length = bytes.getUnsignedShort(at + 1);
at += 3; // Skip to the data.
@@ -326,7 +343,7 @@
ByteArray ubytes = bytes.slice(at, at + length);
try {
- return new CstUtf8(ubytes);
+ return new CstString(ubytes);
} catch (IllegalArgumentException ex) {
// Translate the exception
throw new ParseException(ex);
diff --git a/dx/src/com/android/dx/cf/direct/AnnotationParser.java b/dx/src/com/android/dx/cf/direct/AnnotationParser.java
index ca38fc5..fdbc990 100644
--- a/dx/src/com/android/dx/cf/direct/AnnotationParser.java
+++ b/dx/src/com/android/dx/cf/direct/AnnotationParser.java
@@ -32,7 +32,6 @@
import com.android.dx.rop.cst.CstChar;
import com.android.dx.rop.cst.CstDouble;
import com.android.dx.rop.cst.CstEnumRef;
-import com.android.dx.rop.cst.CstFieldRef;
import com.android.dx.rop.cst.CstFloat;
import com.android.dx.rop.cst.CstInteger;
import com.android.dx.rop.cst.CstLong;
@@ -40,7 +39,6 @@
import com.android.dx.rop.cst.CstShort;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Type;
import com.android.dx.util.ByteArray;
import com.android.dx.util.Hex;
@@ -247,8 +245,8 @@
int typeIndex = input.readUnsignedShort();
int numElements = input.readUnsignedShort();
- CstUtf8 typeUtf8 = (CstUtf8) pool.get(typeIndex);
- CstType type = new CstType(Type.intern(typeUtf8.getString()));
+ CstString typeString = (CstString) pool.get(typeIndex);
+ CstType type = new CstType(Type.intern(typeString.getString()));
if (observer != null) {
parsed(2, "type: " + type.toHuman());
@@ -284,7 +282,7 @@
requireLength(5);
int elementNameIndex = input.readUnsignedShort();
- CstUtf8 elementName = (CstUtf8) pool.get(elementNameIndex);
+ CstString elementName = (CstString) pool.get(elementNameIndex);
if (observer != null) {
parsed(2, "element_name: " + elementName.toHuman());
@@ -310,7 +308,7 @@
int tag = input.readUnsignedByte();
if (observer != null) {
- CstUtf8 humanTag = new CstUtf8(Character.toString((char) tag));
+ CstString humanTag = new CstString(Character.toString((char) tag));
parsed(1, "tag: " + humanTag.toQuoted());
}
@@ -350,7 +348,7 @@
}
case 'c': {
int classInfoIndex = input.readUnsignedShort();
- CstUtf8 value = (CstUtf8) pool.get(classInfoIndex);
+ CstString value = (CstString) pool.get(classInfoIndex);
Type type = Type.internReturnType(value.getString());
if (observer != null) {
@@ -360,16 +358,15 @@
return new CstType(type);
}
case 's': {
- CstString value = new CstString((CstUtf8) parseConstant());
- return value;
+ return parseConstant();
}
case 'e': {
requireLength(4);
int typeNameIndex = input.readUnsignedShort();
int constNameIndex = input.readUnsignedShort();
- CstUtf8 typeName = (CstUtf8) pool.get(typeNameIndex);
- CstUtf8 constName = (CstUtf8) pool.get(constNameIndex);
+ CstString typeName = (CstString) pool.get(typeNameIndex);
+ CstString constName = (CstString) pool.get(constNameIndex);
if (observer != null) {
parsed(2, "type_name: " + typeName.toHuman());
@@ -428,8 +425,8 @@
Constant value = (Constant) pool.get(constValueIndex);
if (observer != null) {
- String human = (value instanceof CstUtf8)
- ? ((CstUtf8) value).toQuoted()
+ String human = (value instanceof CstString)
+ ? ((CstString) value).toQuoted()
: value.toHuman();
parsed(2, "constant_value: " + human);
}
diff --git a/dx/src/com/android/dx/cf/direct/AttributeFactory.java b/dx/src/com/android/dx/cf/direct/AttributeFactory.java
index f98372c..f7486eb 100644
--- a/dx/src/com/android/dx/cf/direct/AttributeFactory.java
+++ b/dx/src/com/android/dx/cf/direct/AttributeFactory.java
@@ -21,7 +21,7 @@
import com.android.dx.cf.iface.ParseException;
import com.android.dx.cf.iface.ParseObserver;
import com.android.dx.rop.cst.ConstantPool;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.ByteArray;
import com.android.dx.util.Hex;
@@ -76,7 +76,7 @@
throw new IllegalArgumentException("bad context");
}
- CstUtf8 name = null;
+ CstString name = null;
try {
ByteArray bytes = cf.getBytes();
@@ -84,7 +84,7 @@
int nameIdx = bytes.getUnsignedShort(offset);
int length = bytes.getInt(offset + 2);
- name = (CstUtf8) pool.get(nameIdx);
+ name = (CstString) pool.get(nameIdx);
if (observer != null) {
observer.parsed(bytes, offset, 2,
diff --git a/dx/src/com/android/dx/cf/direct/DirectClassFile.java b/dx/src/com/android/dx/cf/direct/DirectClassFile.java
index b194572..405f0e9 100644
--- a/dx/src/com/android/dx/cf/direct/DirectClassFile.java
+++ b/dx/src/com/android/dx/cf/direct/DirectClassFile.java
@@ -29,7 +29,7 @@
import com.android.dx.rop.code.AccessFlags;
import com.android.dx.rop.cst.ConstantPool;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.StdConstantPool;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
@@ -300,7 +300,7 @@
}
/** {@inheritDoc} */
- public CstUtf8 getSourceFile() {
+ public CstString getSourceFile() {
AttributeList attribs = getAttributes();
Attribute attSf = attribs.findFirst(AttSourceFile.ATTRIBUTE_NAME);
diff --git a/dx/src/com/android/dx/cf/direct/MemberListParser.java b/dx/src/com/android/dx/cf/direct/MemberListParser.java
index 91a5e1d..605bab8 100644
--- a/dx/src/com/android/dx/cf/direct/MemberListParser.java
+++ b/dx/src/com/android/dx/cf/direct/MemberListParser.java
@@ -23,8 +23,8 @@
import com.android.dx.cf.iface.StdAttributeList;
import com.android.dx.rop.cst.ConstantPool;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.ByteArray;
import com.android.dx.util.Hex;
@@ -187,8 +187,8 @@
int accessFlags = bytes.getUnsignedShort(at);
int nameIdx = bytes.getUnsignedShort(at + 2);
int descIdx = bytes.getUnsignedShort(at + 4);
- CstUtf8 name = (CstUtf8) pool.get(nameIdx);
- CstUtf8 desc = (CstUtf8) pool.get(descIdx);
+ CstString name = (CstString) pool.get(nameIdx);
+ CstString desc = (CstString) pool.get(descIdx);
if (observer != null) {
observer.startParsingMember(bytes, at, name.getString(),
diff --git a/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java b/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
index a6a97af..ae04a13 100644
--- a/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
+++ b/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
@@ -42,7 +42,6 @@
import com.android.dx.cf.iface.ParseException;
import com.android.dx.cf.iface.ParseObserver;
import com.android.dx.cf.iface.StdAttributeList;
-import com.android.dx.rop.annotation.Annotation;
import com.android.dx.rop.annotation.AnnotationVisibility;
import com.android.dx.rop.annotation.Annotations;
import com.android.dx.rop.annotation.AnnotationsList;
@@ -50,8 +49,8 @@
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.ConstantPool;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.cst.TypedConstant;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.ByteArray;
@@ -435,7 +434,7 @@
int accessFlags = bytes.getUnsignedShort(offset + 6);
CstType innerClass = (CstType) pool.get(innerClassIdx);
CstType outerClass = (CstType) pool.get0Ok(outerClassIdx);
- CstUtf8 name = (CstUtf8) pool.get0Ok(nameIdx);
+ CstString name = (CstString) pool.get0Ok(nameIdx);
list.set(i, innerClass, outerClass, name, accessFlags);
if (observer != null) {
observer.parsed(bytes, offset, 2,
@@ -574,10 +573,10 @@
int nameIdx = in.readUnsignedShort();
int typeIdx = in.readUnsignedShort();
int index = in.readUnsignedShort();
- CstUtf8 name = (CstUtf8) pool.get(nameIdx);
- CstUtf8 type = (CstUtf8) pool.get(typeIdx);
- CstUtf8 descriptor = null;
- CstUtf8 signature = null;
+ CstString name = (CstString) pool.get(nameIdx);
+ CstString type = (CstString) pool.get(typeIdx);
+ CstString descriptor = null;
+ CstString signature = null;
if (typeTable) {
signature = type;
@@ -683,7 +682,7 @@
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
- CstUtf8 cst = (CstUtf8) pool.get(idx);
+ CstString cst = (CstString) pool.get(idx);
Attribute result = new AttSignature(cst);
if (observer != null) {
@@ -705,7 +704,7 @@
ByteArray bytes = cf.getBytes();
ConstantPool pool = cf.getConstantPool();
int idx = bytes.getUnsignedShort(offset);
- CstUtf8 cst = (CstUtf8) pool.get(idx);
+ CstString cst = (CstString) pool.get(idx);
Attribute result = new AttSourceFile(cst);
if (observer != null) {
diff --git a/dx/src/com/android/dx/cf/iface/ClassFile.java b/dx/src/com/android/dx/cf/iface/ClassFile.java
index 0f584ba..cb5237a 100644
--- a/dx/src/com/android/dx/cf/iface/ClassFile.java
+++ b/dx/src/com/android/dx/cf/iface/ClassFile.java
@@ -17,8 +17,8 @@
package com.android.dx.cf.iface;
import com.android.dx.rop.cst.ConstantPool;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.TypeList;
/**
@@ -119,5 +119,5 @@
*
* @return {@code non-null;} the constant pool
*/
- public CstUtf8 getSourceFile();
+ public CstString getSourceFile();
}
diff --git a/dx/src/com/android/dx/cf/iface/Member.java b/dx/src/com/android/dx/cf/iface/Member.java
index 0453a6f..b346de4 100644
--- a/dx/src/com/android/dx/cf/iface/Member.java
+++ b/dx/src/com/android/dx/cf/iface/Member.java
@@ -17,8 +17,8 @@
package com.android.dx.cf.iface;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
/**
* Interface representing members of class files (that is, fields and methods).
@@ -44,7 +44,7 @@
*
* @return {@code non-null;} the name
*/
- public CstUtf8 getName();
+ public CstString getName();
/**
* Get the field {@code descriptor_index} of the member. This is
@@ -52,7 +52,7 @@
*
* @return {@code non-null;} the descriptor
*/
- public CstUtf8 getDescriptor();
+ public CstString getDescriptor();
/**
* Get the name and type associated with this member. This is a
diff --git a/dx/src/com/android/dx/cf/iface/StdMember.java b/dx/src/com/android/dx/cf/iface/StdMember.java
index 9f15585..e67b216 100644
--- a/dx/src/com/android/dx/cf/iface/StdMember.java
+++ b/dx/src/com/android/dx/cf/iface/StdMember.java
@@ -17,8 +17,8 @@
package com.android.dx.cf.iface;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
/**
* Standard implementation of {@link Member}, which directly stores
@@ -94,12 +94,12 @@
}
/** {@inheritDoc} */
- public final CstUtf8 getName() {
+ public final CstString getName() {
return nat.getName();
}
/** {@inheritDoc} */
- public final CstUtf8 getDescriptor() {
+ public final CstString getDescriptor() {
return nat.getDescriptor();
}
diff --git a/dx/src/com/android/dx/command/dexer/Main.java b/dx/src/com/android/dx/command/dexer/Main.java
index e810bca..bb6830d 100644
--- a/dx/src/com/android/dx/command/dexer/Main.java
+++ b/dx/src/com/android/dx/command/dexer/Main.java
@@ -38,7 +38,7 @@
import com.android.dx.rop.annotation.Annotations;
import com.android.dx.rop.annotation.AnnotationsList;
import com.android.dx.rop.cst.CstNat;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.FileUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -829,7 +829,7 @@
* The (default) source file is an attribute of the class, but
* it's useful to see it in method dumps.
*/
- CstUtf8 sourceFile = clazz.getSourceFile();
+ CstString sourceFile = clazz.getSourceFile();
if (sourceFile != null) {
pw.println(" source file: " + sourceFile.toQuoted());
}
diff --git a/dx/src/com/android/dx/command/dump/BlockDumper.java b/dx/src/com/android/dx/command/dump/BlockDumper.java
index 2326ae4..6919b09 100644
--- a/dx/src/com/android/dx/command/dump/BlockDumper.java
+++ b/dx/src/com/android/dx/command/dump/BlockDumper.java
@@ -188,6 +188,11 @@
return;
}
+ if ((member.getAccessFlags() & (AccessFlags.ACC_ABSTRACT |
+ AccessFlags.ACC_NATIVE)) != 0) {
+ return;
+ }
+
ConcreteMethod meth =
new ConcreteMethod((Method) member, classFile, true, true);
diff --git a/dx/src/com/android/dx/command/dump/SsaDumper.java b/dx/src/com/android/dx/command/dump/SsaDumper.java
index de44c83..0572a30 100644
--- a/dx/src/com/android/dx/command/dump/SsaDumper.java
+++ b/dx/src/com/android/dx/command/dump/SsaDumper.java
@@ -90,6 +90,11 @@
return;
}
+ if ((member.getAccessFlags() & (AccessFlags.ACC_ABSTRACT |
+ AccessFlags.ACC_NATIVE)) != 0) {
+ return;
+ }
+
ConcreteMethod meth =
new ConcreteMethod((Method) member, classFile, true, true);
TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
diff --git a/dx/src/com/android/dx/command/findusages/FindUsages.java b/dx/src/com/android/dx/command/findusages/FindUsages.java
index 0fb6aa4..6651f53 100644
--- a/dx/src/com/android/dx/command/findusages/FindUsages.java
+++ b/dx/src/com/android/dx/command/findusages/FindUsages.java
@@ -28,7 +28,9 @@
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
public final class FindUsages {
private final DexBuffer dex;
@@ -40,46 +42,57 @@
private ClassDef currentClass;
private ClassData.Method currentMethod;
- public FindUsages(DexBuffer dex, String declaredBy, String memberName, final PrintWriter out) {
+ public FindUsages(final DexBuffer dex, String declaredBy, String memberName, final PrintWriter out) {
this.dex = dex;
this.out = out;
- int typeStringIndex = Collections.binarySearch(dex.strings(), declaredBy);
- int memberNameIndex = Collections.binarySearch(dex.strings(), memberName);
- if (typeStringIndex < 0 || memberNameIndex < 0) {
- methodIds = null;
- fieldIds = null;
+ Set<Integer> typeStringIndexes = new HashSet<Integer>();
+ Set<Integer> memberNameIndexes = new HashSet<Integer>();
+ Pattern declaredByPattern = Pattern.compile(declaredBy);
+ Pattern memberNamePattern = Pattern.compile(memberName);
+ List<String> strings = dex.strings();
+ for (int i = 0; i < strings.size(); ++i) {
+ String string = strings.get(i);
+ if (declaredByPattern.matcher(string).matches()) {
+ typeStringIndexes.add(i);
+ }
+ if (memberNamePattern.matcher(string).matches()) {
+ memberNameIndexes.add(i);
+ }
+ }
+ if (typeStringIndexes.isEmpty() || memberNameIndexes.isEmpty()) {
+ methodIds = fieldIds = null;
return; // these symbols are not mentioned in this dex
}
- int typeIndex = Collections.binarySearch(dex.typeIds(), typeStringIndex);
- if (typeIndex < 0) {
- methodIds = null;
- fieldIds = null;
- return; // this type name isn't used as a type in this dex
+ methodIds = new HashSet<Integer>();
+ fieldIds = new HashSet<Integer>();
+ for (int typeStringIndex : typeStringIndexes) {
+ int typeIndex = Collections.binarySearch(dex.typeIds(), typeStringIndex);
+ if (typeIndex < 0) {
+ continue; // this type name isn't used as a type in this dex
+ }
+ methodIds.addAll(getMethodIds(dex, memberNameIndexes, typeIndex));
+ fieldIds.addAll(getFieldIds(dex, memberNameIndexes, typeIndex));
}
- methodIds = getMethodIds(dex, memberNameIndex, typeIndex);
- fieldIds = getFieldIds(dex, memberNameIndex, typeIndex);
-
codeReader.setFieldVisitor(new CodeReader.Visitor() {
public void visit(DecodedInstruction[] all,
DecodedInstruction one) {
int fieldId = one.getIndex();
if (fieldIds.contains(fieldId)) {
- out.println(location() + ": field reference ("
- + OpcodeInfo.getName(one.getOpcode()) + ")");
+ out.println(location() + ": field reference " + dex.fieldIds().get(fieldId)
+ + " (" + OpcodeInfo.getName(one.getOpcode()) + ")");
}
}
});
codeReader.setMethodVisitor(new CodeReader.Visitor() {
- public void visit(DecodedInstruction[] all,
- DecodedInstruction one) {
+ public void visit(DecodedInstruction[] all, DecodedInstruction one) {
int methodId = one.getIndex();
if (methodIds.contains(methodId)) {
- out.println(location() + ": method reference ("
- + OpcodeInfo.getName(one.getOpcode()) + ")");
+ out.println(location() + ": method reference " + dex.methodIds().get(methodId)
+ + " (" + OpcodeInfo.getName(one.getOpcode()) + ")");
}
}
});
@@ -113,15 +126,17 @@
ClassData classData = dex.readClassData(classDef);
for (ClassData.Field field : classData.allFields()) {
- if (fieldIds.contains(field.getFieldIndex())) {
- out.println(location() + " field declared");
+ int fieldIndex = field.getFieldIndex();
+ if (fieldIds.contains(fieldIndex)) {
+ out.println(location() + " field declared " + dex.fieldIds().get(fieldIndex));
}
}
for (ClassData.Method method : classData.allMethods()) {
currentMethod = method;
- if (methodIds.contains(method.getMethodIndex())) {
- out.println(location() + " method declared");
+ int methodIndex = method.getMethodIndex();
+ if (methodIds.contains(methodIndex)) {
+ out.println(location() + " method declared " + dex.methodIds().get(methodIndex));
}
if (method.getCodeOffset() != 0) {
codeReader.visitAll(dex.readCode(method).getInstructions());
@@ -137,11 +152,11 @@
* Returns the fields with {@code memberNameIndex} declared by {@code
* declaringType}.
*/
- private Set<Integer> getFieldIds(DexBuffer dex, int memberNameIndex, int declaringType) {
+ private Set<Integer> getFieldIds(DexBuffer dex, Set<Integer> memberNameIndexes, int declaringType) {
Set<Integer> fields = new HashSet<Integer>();
int fieldIndex = 0;
for (FieldId fieldId : dex.fieldIds()) {
- if (fieldId.getNameIndex() == memberNameIndex
+ if (memberNameIndexes.contains(fieldId.getNameIndex())
&& declaringType == fieldId.getDeclaringClassIndex()) {
fields.add(fieldIndex);
}
@@ -154,13 +169,13 @@
* Returns the methods with {@code memberNameIndex} declared by {@code
* declaringType} and its subtypes.
*/
- private Set<Integer> getMethodIds(DexBuffer dex, int memberNameIndex, int declaringType) {
+ private Set<Integer> getMethodIds(DexBuffer dex, Set<Integer> memberNameIndexes, int declaringType) {
Set<Integer> subtypes = findAssignableTypes(dex, declaringType);
Set<Integer> methods = new HashSet<Integer>();
int methodIndex = 0;
for (MethodId method : dex.methodIds()) {
- if (method.getNameIndex() == memberNameIndex
+ if (memberNameIndexes.contains(method.getNameIndex())
&& subtypes.contains(method.getDeclaringClassIndex())) {
methods.add(methodIndex);
}
diff --git a/dx/src/com/android/dx/command/findusages/Main.java b/dx/src/com/android/dx/command/findusages/Main.java
index 8203890..ba29787 100644
--- a/dx/src/com/android/dx/command/findusages/Main.java
+++ b/dx/src/com/android/dx/command/findusages/Main.java
@@ -28,6 +28,8 @@
String memberName = args[2];
DexBuffer dex = new DexBuffer(new File(dexFile));
- new FindUsages(dex, declaredBy, memberName, new PrintWriter(System.out)).findUsages();
+ PrintWriter out = new PrintWriter(System.out);
+ new FindUsages(dex, declaredBy, memberName, out).findUsages();
+ out.flush();
}
}
diff --git a/dx/src/com/android/dx/dex/cf/AttributeTranslator.java b/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
index 2508a59..8dc8b92 100644
--- a/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
+++ b/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
@@ -27,7 +27,6 @@
import com.android.dx.cf.attrib.AttSignature;
import com.android.dx.cf.attrib.InnerClassList;
import com.android.dx.cf.direct.DirectClassFile;
-import com.android.dx.cf.direct.StdAttributeFactory;
import com.android.dx.cf.iface.AttributeList;
import com.android.dx.cf.iface.Method;
import com.android.dx.cf.iface.MethodList;
@@ -41,7 +40,6 @@
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstNat;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
diff --git a/dx/src/com/android/dx/dex/cf/CfTranslator.java b/dx/src/com/android/dx/dex/cf/CfTranslator.java
index 8bcfa3d..8b94f91 100644
--- a/dx/src/com/android/dx/dex/cf/CfTranslator.java
+++ b/dx/src/com/android/dx/dex/cf/CfTranslator.java
@@ -47,8 +47,8 @@
import com.android.dx.rop.cst.CstInteger;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstShort;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.cst.TypedConstant;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
@@ -118,7 +118,7 @@
CstType thisClass = cf.getThisClass();
int classAccessFlags = cf.getAccessFlags() & ~AccessFlags.ACC_SUPER;
- CstUtf8 sourceFile = (cfOptions.positionInfo == PositionList.NONE) ? null :
+ CstString sourceFile = (cfOptions.positionInfo == PositionList.NONE) ? null :
cf.getSourceFile();
ClassDefItem out =
new ClassDefItem(thisClass, classAccessFlags,
diff --git a/dx/src/com/android/dx/dex/code/InsnFormat.java b/dx/src/com/android/dx/dex/code/InsnFormat.java
index a86a003..bf9f08e 100644
--- a/dx/src/com/android/dx/dex/code/InsnFormat.java
+++ b/dx/src/com/android/dx/dex/code/InsnFormat.java
@@ -23,6 +23,7 @@
import com.android.dx.rop.cst.CstKnownNull;
import com.android.dx.rop.cst.CstLiteral64;
import com.android.dx.rop.cst.CstLiteralBits;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -336,7 +337,7 @@
CstInsn ci = (CstInsn) insn;
Constant cst = ci.getConstant();
- return cst.toHuman();
+ return cst instanceof CstString ? ((CstString) cst).toQuoted() : cst.toHuman();
}
/**
diff --git a/dx/src/com/android/dx/dex/code/LocalList.java b/dx/src/com/android/dx/dex/code/LocalList.java
index 94ca663..ab8343a 100644
--- a/dx/src/com/android/dx/dex/code/LocalList.java
+++ b/dx/src/com/android/dx/dex/code/LocalList.java
@@ -19,7 +19,7 @@
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecSet;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.util.FixedSizeList;
@@ -236,7 +236,7 @@
*
* @return {@code null-ok;} the variable name
*/
- public CstUtf8 getName() {
+ public CstString getName() {
return spec.getLocalItem().getName();
}
@@ -245,7 +245,7 @@
*
* @return {@code null-ok;} the variable signature
*/
- public CstUtf8 getSignature() {
+ public CstString getSignature() {
return spec.getLocalItem().getSignature();
}
diff --git a/dx/src/com/android/dx/dex/code/OutputFinisher.java b/dx/src/com/android/dx/dex/code/OutputFinisher.java
index 1b13fab..ff0d75c 100644
--- a/dx/src/com/android/dx/dex/code/OutputFinisher.java
+++ b/dx/src/com/android/dx/dex/code/OutputFinisher.java
@@ -26,7 +26,7 @@
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstMemberRef;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import java.util.ArrayList;
@@ -196,8 +196,8 @@
}
LocalItem local = spec.getLocalItem();
- CstUtf8 name = local.getName();
- CstUtf8 signature = local.getSignature();
+ CstString name = local.getName();
+ CstString signature = local.getSignature();
Type type = spec.getType();
if (type != Type.KNOWN_NULL) {
@@ -520,7 +520,11 @@
* @return {@code non-null;} the opcode that fits
*/
private Dop findExpandedOpcodeForInsn(DalvInsn insn) {
- return findOpcodeForInsn(insn.getLowRegVersion(), insn.getOpcode());
+ Dop result = findOpcodeForInsn(insn.getLowRegVersion(), insn.getOpcode());
+ if (result == null) {
+ throw new AssertionError();
+ }
+ return result;
}
/**
diff --git a/dx/src/com/android/dx/dex/code/RopToDop.java b/dx/src/com/android/dx/dex/code/RopToDop.java
index 5292d3c..0330113 100644
--- a/dx/src/com/android/dx/dex/code/RopToDop.java
+++ b/dx/src/com/android/dx/dex/code/RopToDop.java
@@ -24,8 +24,8 @@
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import java.util.HashMap;
diff --git a/dx/src/com/android/dx/dex/file/AnnotationItem.java b/dx/src/com/android/dx/dex/file/AnnotationItem.java
index 1febd9e..1d92247 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationItem.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationItem.java
@@ -20,9 +20,7 @@
import com.android.dx.rop.annotation.AnnotationVisibility;
import com.android.dx.rop.annotation.NameValuePair;
import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.ByteArrayAnnotatedOutput;
import com.android.dx.util.AnnotatedOutput;
@@ -176,7 +174,7 @@
out.annotate(0, prefix + "type: " + annotation.getType().toHuman());
for (NameValuePair pair : annotation.getNameValuePairs()) {
- CstUtf8 name = pair.getName();
+ CstString name = pair.getName();
Constant value = pair.getValue();
out.annotate(0, prefix + name.toHuman() + ": " +
diff --git a/dx/src/com/android/dx/dex/file/AnnotationUtils.java b/dx/src/com/android/dx/dex/file/AnnotationUtils.java
index d500ec4..350ed9a 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationUtils.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationUtils.java
@@ -26,7 +26,6 @@
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
@@ -67,13 +66,13 @@
CstType.intern(Type.intern("Ldalvik/annotation/Throws;"));
/** {@code non-null;} the UTF-8 constant {@code "accessFlags"} */
- private static final CstUtf8 ACCESS_FLAGS_UTF = new CstUtf8("accessFlags");
+ private static final CstString ACCESS_FLAGS_STRING = new CstString("accessFlags");
/** {@code non-null;} the UTF-8 constant {@code "name"} */
- private static final CstUtf8 NAME_UTF = new CstUtf8("name");
+ private static final CstString NAME_STRING = new CstString("name");
/** {@code non-null;} the UTF-8 constant {@code "value"} */
- private static final CstUtf8 VALUE_UTF = new CstUtf8("value");
+ private static final CstString VALUE_STRING = new CstString("value");
/**
* This class is uninstantiable.
@@ -91,7 +90,7 @@
public static Annotation makeAnnotationDefault(Annotation defaults) {
Annotation result = new Annotation(ANNOTATION_DEFAULT_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, new CstAnnotation(defaults)));
+ result.put(new NameValuePair(VALUE_STRING, new CstAnnotation(defaults)));
result.setImmutable();
return result;
}
@@ -105,7 +104,7 @@
public static Annotation makeEnclosingClass(CstType clazz) {
Annotation result = new Annotation(ENCLOSING_CLASS_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, clazz));
+ result.put(new NameValuePair(VALUE_STRING, clazz));
result.setImmutable();
return result;
}
@@ -119,7 +118,7 @@
public static Annotation makeEnclosingMethod(CstMethodRef method) {
Annotation result = new Annotation(ENCLOSING_METHOD_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, method));
+ result.put(new NameValuePair(VALUE_STRING, method));
result.setImmutable();
return result;
}
@@ -132,13 +131,12 @@
* @param accessFlags the original access flags
* @return {@code non-null;} the annotation
*/
- public static Annotation makeInnerClass(CstUtf8 name, int accessFlags) {
+ public static Annotation makeInnerClass(CstString name, int accessFlags) {
Annotation result = new Annotation(INNER_CLASS_TYPE, SYSTEM);
- Constant nameCst =
- (name != null) ? new CstString(name) : CstKnownNull.THE_ONE;
+ Constant nameCst = (name != null) ? name : CstKnownNull.THE_ONE;
- result.put(new NameValuePair(NAME_UTF, nameCst));
- result.put(new NameValuePair(ACCESS_FLAGS_UTF,
+ result.put(new NameValuePair(NAME_STRING, nameCst));
+ result.put(new NameValuePair(ACCESS_FLAGS_STRING,
CstInteger.make(accessFlags)));
result.setImmutable();
return result;
@@ -153,7 +151,7 @@
public static Annotation makeMemberClasses(TypeList types) {
CstArray array = makeCstArray(types);
Annotation result = new Annotation(MEMBER_CLASSES_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, array));
+ result.put(new NameValuePair(VALUE_STRING, array));
result.setImmutable();
return result;
}
@@ -164,7 +162,7 @@
* @param signature {@code non-null;} the signature string
* @return {@code non-null;} the annotation
*/
- public static Annotation makeSignature(CstUtf8 signature) {
+ public static Annotation makeSignature(CstString signature) {
Annotation result = new Annotation(SIGNATURE_TYPE, SYSTEM);
/*
@@ -215,7 +213,7 @@
list.setImmutable();
- result.put(new NameValuePair(VALUE_UTF, new CstArray(list)));
+ result.put(new NameValuePair(VALUE_STRING, new CstArray(list)));
result.setImmutable();
return result;
}
@@ -229,7 +227,7 @@
public static Annotation makeThrows(TypeList types) {
CstArray array = makeCstArray(types);
Annotation result = new Annotation(THROWS_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, array));
+ result.put(new NameValuePair(VALUE_STRING, array));
result.setImmutable();
return result;
}
diff --git a/dx/src/com/android/dx/dex/file/ClassDefItem.java b/dx/src/com/android/dx/dex/file/ClassDefItem.java
index 4132fb9..df3945a 100644
--- a/dx/src/com/android/dx/dex/file/ClassDefItem.java
+++ b/dx/src/com/android/dx/dex/file/ClassDefItem.java
@@ -24,8 +24,8 @@
import com.android.dx.rop.cst.CstArray;
import com.android.dx.rop.cst.CstFieldRef;
import com.android.dx.rop.cst.CstMethodRef;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.AnnotatedOutput;
@@ -59,7 +59,7 @@
private TypeListItem interfaces;
/** {@code null-ok;} source file name or {@code null} if unknown */
- private final CstUtf8 sourceFile;
+ private final CstString sourceFile;
/** {@code non-null;} associated class data object */
private final ClassDataItem classData;
@@ -86,7 +86,7 @@
* {@code null} if unknown
*/
public ClassDefItem(CstType thisClass, int accessFlags,
- CstType superclass, TypeList interfaces, CstUtf8 sourceFile) {
+ CstType superclass, TypeList interfaces, CstString sourceFile) {
if (thisClass == null) {
throw new NullPointerException("thisClass == null");
}
@@ -264,7 +264,7 @@
*
* @return {@code null-ok;} the source file name or {@code null} if unknown
*/
- public CstUtf8 getSourceFile() {
+ public CstString getSourceFile() {
return sourceFile;
}
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
index 781caec..9fb4845 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
@@ -21,7 +21,7 @@
import com.android.dx.dex.code.LocalList;
import com.android.dx.dex.code.PositionList;
import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
@@ -112,7 +112,7 @@
int idx = -1;
try {
- idx = file.getStringIds().indexOf(new CstUtf8("this"));
+ idx = file.getStringIds().indexOf(new CstString("this"));
} catch (IllegalArgumentException ex) {
/*
* Silently tolerate not finding "this". It just means that
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
index d9d4ebc..ae87fc3 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
@@ -22,7 +22,7 @@
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
@@ -470,7 +470,7 @@
continue;
}
- CstUtf8 signature = arg.getSignature();
+ CstString signature = arg.getSignature();
if (signature != null) {
emitLocalStartExtended(arg);
@@ -576,7 +576,7 @@
sb.append(e.getRegister());
sb.append(' ');
- CstUtf8 name = e.getName();
+ CstString name = e.getName();
if (name == null) {
sb.append("null");
} else {
@@ -591,7 +591,7 @@
sb.append(type.toHuman());
}
- CstUtf8 signature = e.getSignature();
+ CstString signature = e.getSignature();
if (signature != null) {
sb.append(' ');
@@ -636,7 +636,7 @@
* @param string {@code null-ok;} string to emit
* @throws IOException
*/
- private void emitStringIndex(CstUtf8 string) throws IOException {
+ private void emitStringIndex(CstString string) throws IOException {
if ((string == null) || (file == null)) {
output.writeUleb128(0);
} else {
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoItem.java b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
index 6a41b18..09b2712 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoItem.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
@@ -21,8 +21,6 @@
import com.android.dx.dex.code.LocalList;
import com.android.dx.dex.code.PositionList;
import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;
diff --git a/dx/src/com/android/dx/dex/file/DexFile.java b/dx/src/com/android/dx/dex/file/DexFile.java
index 73f0864..dc004f4 100644
--- a/dx/src/com/android/dx/dex/file/DexFile.java
+++ b/dx/src/com/android/dx/dex/file/DexFile.java
@@ -22,7 +22,6 @@
import com.android.dx.rop.cst.CstFieldRef;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Type;
import com.android.dx.util.ByteArrayAnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;
@@ -430,8 +429,6 @@
/*package*/ void internIfAppropriate(Constant cst) {
if (cst instanceof CstString) {
stringIds.intern((CstString) cst);
- } else if (cst instanceof CstUtf8) {
- stringIds.intern((CstUtf8) cst);
} else if (cst instanceof CstType) {
typeIds.intern((CstType) cst);
} else if (cst instanceof CstBaseMethodRef) {
diff --git a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java b/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
index 4d904e7..3d05ab3 100644
--- a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
+++ b/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
@@ -16,19 +16,10 @@
package com.android.dx.dex.file;
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.AnnotationVisibility;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.ByteArrayAnnotatedOutput;
import com.android.dx.util.AnnotatedOutput;
-import java.util.Arrays;
-import java.util.Comparator;
-
/**
* Encoded array of constant values.
*/
diff --git a/dx/src/com/android/dx/dex/file/EncodedField.java b/dx/src/com/android/dx/dex/file/EncodedField.java
index d972479..fdfa5d2 100644
--- a/dx/src/com/android/dx/dex/file/EncodedField.java
+++ b/dx/src/com/android/dx/dex/file/EncodedField.java
@@ -18,7 +18,7 @@
import com.android.dx.rop.code.AccessFlags;
import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
import com.android.dx.util.Leb128Utils;
@@ -103,7 +103,7 @@
/** {@inheritDoc} */
@Override
- public CstUtf8 getName() {
+ public CstString getName() {
return field.getNat().getName();
}
diff --git a/dx/src/com/android/dx/dex/file/EncodedMember.java b/dx/src/com/android/dx/dex/file/EncodedMember.java
index 5099325..6277646 100644
--- a/dx/src/com/android/dx/dex/file/EncodedMember.java
+++ b/dx/src/com/android/dx/dex/file/EncodedMember.java
@@ -16,7 +16,7 @@
package com.android.dx.dex.file;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ToHuman;
@@ -53,7 +53,7 @@
*
* @return {@code non-null;} the name
*/
- public abstract CstUtf8 getName();
+ public abstract CstString getName();
/**
* Does a human-friendly dump of this instance.
diff --git a/dx/src/com/android/dx/dex/file/EncodedMethod.java b/dx/src/com/android/dx/dex/file/EncodedMethod.java
index e707de4..c3f71b7 100644
--- a/dx/src/com/android/dx/dex/file/EncodedMethod.java
+++ b/dx/src/com/android/dx/dex/file/EncodedMethod.java
@@ -19,7 +19,7 @@
import com.android.dx.dex.code.DalvCode;
import com.android.dx.rop.code.AccessFlags;
import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -131,7 +131,7 @@
/** {@inheritDoc} */
@Override
- public final CstUtf8 getName() {
+ public final CstString getName() {
return method.getNat().getName();
}
diff --git a/dx/src/com/android/dx/dex/file/HeaderItem.java b/dx/src/com/android/dx/dex/file/HeaderItem.java
index 98b938d..d851ffd 100644
--- a/dx/src/com/android/dx/dex/file/HeaderItem.java
+++ b/dx/src/com/android/dx/dex/file/HeaderItem.java
@@ -18,7 +18,7 @@
import com.android.dx.dex.DexFormat;
import com.android.dx.dex.SizeOf;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -62,7 +62,7 @@
lastDataSection.writeSize() - dataOff;
if (out.annotates()) {
- out.annotate(8, "magic: " + new CstUtf8(DexFormat.MAGIC).toQuoted());
+ out.annotate(8, "magic: " + new CstString(DexFormat.MAGIC).toQuoted());
out.annotate(4, "checksum");
out.annotate(20, "signature");
out.annotate(4, "file_size: " +
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdItem.java b/dx/src/com/android/dx/dex/file/ProtoIdItem.java
index ffb6167..235a8c8 100644
--- a/dx/src/com/android/dx/dex/file/ProtoIdItem.java
+++ b/dx/src/com/android/dx/dex/file/ProtoIdItem.java
@@ -17,7 +17,7 @@
package com.android.dx.dex.file;
import com.android.dx.dex.SizeOf;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
@@ -32,7 +32,7 @@
private final Prototype prototype;
/** {@code non-null;} the short-form of the prototype */
- private final CstUtf8 shortForm;
+ private final CstString shortForm;
/**
* {@code null-ok;} the list of parameter types or {@code null} if this
@@ -64,7 +64,7 @@
* @param prototype {@code non-null;} the prototype
* @return {@code non-null;} the short form
*/
- private static CstUtf8 makeShortForm(Prototype prototype) {
+ private static CstString makeShortForm(Prototype prototype) {
StdTypeList parameters = prototype.getParameterTypes();
int size = parameters.size();
StringBuilder sb = new StringBuilder(size + 1);
@@ -75,7 +75,7 @@
sb.append(shortFormCharFor(parameters.getType(i)));
}
- return new CstUtf8(sb.toString());
+ return new CstString(sb.toString());
}
/**
diff --git a/dx/src/com/android/dx/dex/file/StringDataItem.java b/dx/src/com/android/dx/dex/file/StringDataItem.java
index 3752cb2..e85a823 100644
--- a/dx/src/com/android/dx/dex/file/StringDataItem.java
+++ b/dx/src/com/android/dx/dex/file/StringDataItem.java
@@ -16,7 +16,7 @@
package com.android.dx.dex.file;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ByteArray;
import com.android.dx.util.Hex;
@@ -27,14 +27,14 @@
*/
public final class StringDataItem extends OffsettedItem {
/** {@code non-null;} the string value */
- private final CstUtf8 value;
+ private final CstString value;
/**
* Constructs an instance.
*
* @param value {@code non-null;} the string value
*/
- public StringDataItem(CstUtf8 value) {
+ public StringDataItem(CstString value) {
super(1, writeSize(value));
this.value = value;
@@ -46,7 +46,7 @@
* @param value {@code non-null;} the string value
* @return {@code >= 2}; the write size, in bytes
*/
- private static int writeSize(CstUtf8 value) {
+ private static int writeSize(CstString value) {
int utf16Size = value.getUtf16Size();
// The +1 is for the '\0' termination byte.
diff --git a/dx/src/com/android/dx/dex/file/StringIdItem.java b/dx/src/com/android/dx/dex/file/StringIdItem.java
index 8037df7..533427d 100644
--- a/dx/src/com/android/dx/dex/file/StringIdItem.java
+++ b/dx/src/com/android/dx/dex/file/StringIdItem.java
@@ -17,7 +17,7 @@
package com.android.dx.dex.file;
import com.android.dx.dex.SizeOf;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -27,7 +27,7 @@
public final class StringIdItem
extends IndexedItem implements Comparable {
/** {@code non-null;} the string value */
- private final CstUtf8 value;
+ private final CstString value;
/** {@code null-ok;} associated string data object, if known */
private StringDataItem data;
@@ -37,7 +37,7 @@
*
* @param value {@code non-null;} the string value
*/
- public StringIdItem(CstUtf8 value) {
+ public StringIdItem(CstString value) {
if (value == null) {
throw new NullPointerException("value == null");
}
@@ -110,7 +110,7 @@
*
* @return {@code non-null;} the value
*/
- public CstUtf8 getValue() {
+ public CstString getValue() {
return value;
}
diff --git a/dx/src/com/android/dx/dex/file/StringIdsSection.java b/dx/src/com/android/dx/dex/file/StringIdsSection.java
index 9039f43..2f7c40b 100644
--- a/dx/src/com/android/dx/dex/file/StringIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/StringIdsSection.java
@@ -19,7 +19,6 @@
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstNat;
import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -35,7 +34,7 @@
* {@code non-null;} map from string constants to {@link
* StringIdItem} instances
*/
- private final TreeMap<CstUtf8, StringIdItem> strings;
+ private final TreeMap<CstString, StringIdItem> strings;
/**
* Constructs an instance. The file offset is initially unknown.
@@ -45,7 +44,7 @@
public StringIdsSection(DexFile file) {
super("string_ids", file, 4);
- strings = new TreeMap<CstUtf8, StringIdItem>();
+ strings = new TreeMap<CstString, StringIdItem>();
}
/** {@inheritDoc} */
@@ -63,11 +62,7 @@
throwIfNotPrepared();
- if (cst instanceof CstString) {
- cst = ((CstString) cst).getString();
- }
-
- IndexedItem result = strings.get((CstUtf8) cst);
+ IndexedItem result = strings.get((CstString) cst);
if (result == null) {
throw new IllegalArgumentException("not found");
@@ -104,19 +99,7 @@
* @return {@code non-null;} the interned string
*/
public StringIdItem intern(String string) {
- CstUtf8 utf8 = new CstUtf8(string);
- return intern(new StringIdItem(utf8));
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param string {@code non-null;} the string to intern, as a {@link CstString}
- * @return {@code non-null;} the interned string
- */
- public StringIdItem intern(CstString string) {
- CstUtf8 utf8 = string.getString();
- return intern(new StringIdItem(utf8));
+ return intern(new StringIdItem(new CstString(string)));
}
/**
@@ -125,7 +108,7 @@
* @param string {@code non-null;} the string to intern, as a constant
* @return {@code non-null;} the interned string
*/
- public StringIdItem intern(CstUtf8 string) {
+ public StringIdItem intern(CstString string) {
return intern(new StringIdItem(string));
}
@@ -142,7 +125,7 @@
throwIfPrepared();
- CstUtf8 value = string.getValue();
+ CstString value = string.getValue();
StringIdItem already = strings.get(value);
if (already != null) {
@@ -170,7 +153,7 @@
* @param string {@code non-null;} the string to look up
* @return {@code >= 0;} the string's index
*/
- public int indexOf(CstUtf8 string) {
+ public int indexOf(CstString string) {
if (string == null) {
throw new NullPointerException("string == null");
}
@@ -186,17 +169,6 @@
return s.getIndex();
}
- /**
- * Gets the index of the given string, which must have been added
- * to this instance.
- *
- * @param string {@code non-null;} the string to look up
- * @return {@code >= 0;} the string's index
- */
- public int indexOf(CstString string) {
- return indexOf(string.getString());
- }
-
/** {@inheritDoc} */
@Override
protected void orderItems() {
diff --git a/dx/src/com/android/dx/dex/file/TypeIdItem.java b/dx/src/com/android/dx/dex/file/TypeIdItem.java
index 6ace661..04be2a1 100644
--- a/dx/src/com/android/dx/dex/file/TypeIdItem.java
+++ b/dx/src/com/android/dx/dex/file/TypeIdItem.java
@@ -18,7 +18,7 @@
import com.android.dx.dex.SizeOf;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
@@ -57,7 +57,7 @@
@Override
public void writeTo(DexFile file, AnnotatedOutput out) {
CstType type = getDefiningClass();
- CstUtf8 descriptor = type.getDescriptor();
+ CstString descriptor = type.getDescriptor();
int idx = file.getStringIds().indexOf(descriptor);
if (out.annotates()) {
diff --git a/dx/src/com/android/dx/dex/file/ValueEncoder.java b/dx/src/com/android/dx/dex/file/ValueEncoder.java
index 7a608e0..9c433a3 100644
--- a/dx/src/com/android/dx/dex/file/ValueEncoder.java
+++ b/dx/src/com/android/dx/dex/file/ValueEncoder.java
@@ -36,10 +36,8 @@
import com.android.dx.rop.cst.CstShort;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
-
import java.util.Collection;
/**
@@ -332,7 +330,7 @@
int at = 0;
for (NameValuePair pair : pairs) {
- CstUtf8 name = pair.getName();
+ CstString name = pair.getName();
int nameIdx = stringIds.indexOf(name);
Constant value = pair.getValue();
diff --git a/dx/src/com/android/dx/gen/BinaryOp.java b/dx/src/com/android/dx/gen/BinaryOp.java
new file mode 100644
index 0000000..65a2998
--- /dev/null
+++ b/dx/src/com/android/dx/gen/BinaryOp.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.code.Rop;
+import com.android.dx.rop.code.Rops;
+import com.android.dx.rop.type.TypeList;
+
+/**
+ * An operation on two values of the same type.
+ *
+ * <p>Math operations ({@link #ADD}, {@link #SUBTRACT}, {@link #MULTIPLY},
+ * {@link #DIVIDE}, and {@link #REMAINDER}) support ints, longs, floats and
+ * doubles.
+ *
+ * <p>Bit operations ({@link #AND}, {@link #OR}, {@link #XOR}, {@link
+ * #SHIFT_LEFT}, {@link #SHIFT_RIGHT}, {@link #UNSIGNED_SHIFT_RIGHT}) support
+ * ints and longs.
+ *
+ * <p>Division by zero behaves differently depending on the operand type.
+ * For int and long operands, {@link #DIVIDE} and {@link #REMAINDER} throw
+ * {@link ArithmeticException} if {@code b == 0}. For float and double operands,
+ * the operations return {@code NaN}.
+ */
+public enum BinaryOp {
+ /** {@code a + b} */
+ ADD() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opAdd(types);
+ }
+ },
+
+ /** {@code a - b} */
+ SUBTRACT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opSub(types);
+ }
+ },
+
+ /** {@code a * b} */
+ MULTIPLY() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opMul(types);
+ }
+ },
+
+ /** {@code a / b} */
+ DIVIDE() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opDiv(types);
+ }
+ },
+
+ /** {@code a % b} */
+ REMAINDER() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opRem(types);
+ }
+ },
+
+ /** {@code a & b} */
+ AND() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opAnd(types);
+ }
+ },
+
+ /** {@code a | b} */
+ OR() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opOr(types);
+ }
+ },
+
+ /** {@code a ^ b} */
+ XOR() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opXor(types);
+ }
+ },
+
+ /** {@code a << b} */
+ SHIFT_LEFT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opShl(types);
+ }
+ },
+
+ /** {@code a >> b} */
+ SHIFT_RIGHT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opShr(types);
+ }
+ },
+
+ /** {@code a >>> b} */
+ UNSIGNED_SHIFT_RIGHT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opUshr(types);
+ }
+ };
+
+ abstract Rop rop(com.android.dx.rop.type.TypeList types);
+}
diff --git a/dx/src/com/android/dx/gen/Code.java b/dx/src/com/android/dx/gen/Code.java
new file mode 100644
index 0000000..b44d01c
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Code.java
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.code.BasicBlockList;
+import com.android.dx.rop.code.Insn;
+import com.android.dx.rop.code.PlainCstInsn;
+import com.android.dx.rop.code.PlainInsn;
+import com.android.dx.rop.code.RegisterSpecList;
+import com.android.dx.rop.code.Rop;
+import static com.android.dx.rop.code.Rop.BRANCH_GOTO;
+import static com.android.dx.rop.code.Rop.BRANCH_NONE;
+import static com.android.dx.rop.code.Rop.BRANCH_RETURN;
+import com.android.dx.rop.code.Rops;
+import com.android.dx.rop.code.SourcePosition;
+import com.android.dx.rop.code.ThrowingCstInsn;
+import com.android.dx.rop.code.ThrowingInsn;
+import com.android.dx.rop.cst.CstInteger;
+import com.android.dx.rop.type.StdTypeList;
+import static com.android.dx.rop.type.Type.BT_BYTE;
+import static com.android.dx.rop.type.Type.BT_CHAR;
+import static com.android.dx.rop.type.Type.BT_INT;
+import static com.android.dx.rop.type.Type.BT_SHORT;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Builds a sequence of instructions.
+ */
+public final class Code {
+ private final MethodId<?, ?> method;
+ /**
+ * All allocated labels. Although the order of the labels in this list
+ * shouldn't impact behavior, it is used to determine basic block indices.
+ */
+ private final List<Label> labels = new ArrayList<Label>();
+
+ /**
+ * The label currently receiving instructions. This is null if the most
+ * recent instruction was a return or goto.
+ */
+ private Label currentLabel;
+
+ /** true once we've fixed the positions of the parameter registers */
+ private boolean localsInitialized;
+
+ private final Local<?> thisLocal;
+ private final List<Local<?>> parameters = new ArrayList<Local<?>>();
+ private final List<Local<?>> locals = new ArrayList<Local<?>>();
+ private SourcePosition sourcePosition = SourcePosition.NO_INFO;
+ private final List<Type<?>> catchTypes = new ArrayList<Type<?>>();
+ private final List<Label> catchLabels = new ArrayList<Label>();
+ private StdTypeList catches = StdTypeList.EMPTY;
+
+ Code(DexGenerator.MethodDeclaration methodDeclaration) {
+ this.method = methodDeclaration.method;
+ this.thisLocal = methodDeclaration.isStatic()
+ ? null
+ : Local.get(this, method.declaringType);
+ for (Type<?> parameter : method.parameters.types) {
+ parameters.add(Local.get(this, parameter));
+ }
+ this.currentLabel = newLabel();
+ this.currentLabel.marked = true;
+ }
+
+ public <T> Local<T> newLocal(Type<T> type) {
+ if (localsInitialized) {
+ throw new IllegalStateException("Cannot allocate locals after adding instructions");
+ }
+ Local<T> result = Local.get(this, type);
+ locals.add(result);
+ return result;
+ }
+
+ public <T> Local<T> getParameter(int index, Type<T> type) {
+ return coerce(parameters.get(index), type);
+ }
+
+ public <T> Local<T> getThis(Type<T> type) {
+ if (thisLocal == null) {
+ throw new IllegalStateException("static methods cannot access 'this'");
+ }
+ return coerce(thisLocal, type);
+ }
+
+ @SuppressWarnings("unchecked") // guarded by an equals check
+ private <T> Local<T> coerce(Local<?> local, Type<T> expectedType) {
+ if (!local.type.equals(expectedType)) {
+ throw new IllegalArgumentException(
+ "requested " + expectedType + " but was " + local.type);
+ }
+ return (Local<T>) local;
+ }
+
+ /**
+ * Assigns registers to locals. From the spec:
+ * "the N arguments to a method land in the last N registers of the
+ * method's invocation frame, in order. Wide arguments consume two
+ * registers. Instance methods are passed a this reference as their
+ * first argument."
+ *
+ * In addition to assigning registers to each of the locals, this creates
+ * instructions to move parameters into their initial registers. These
+ * instructions are inserted before the code's first real instruction.
+ */
+ void initializeLocals() {
+ if (localsInitialized) {
+ throw new AssertionError();
+ }
+ localsInitialized = true;
+
+ int reg = 0;
+ for (Local<?> local : locals) {
+ reg += local.initialize(reg);
+ }
+ if (thisLocal != null) {
+ reg += thisLocal.initialize(reg);
+ }
+ int firstParamReg = reg;
+
+ List<Insn> moveParameterInstructions = new ArrayList<Insn>();
+ for (Local<?> local : parameters) {
+ CstInteger paramConstant = CstInteger.make(reg - firstParamReg);
+ reg += local.initialize(reg);
+ moveParameterInstructions.add(new PlainCstInsn(Rops.opMoveParam(local.type.ropType),
+ sourcePosition, local.spec(), RegisterSpecList.EMPTY, paramConstant));
+ }
+ labels.get(0).instructions.addAll(0, moveParameterInstructions);
+ }
+
+ int paramSize() {
+ int result = 0;
+ for (Local<?> local : parameters) {
+ result += local.size();
+ }
+ return result;
+ }
+
+ // labels
+
+ /**
+ * Creates a new label for use as a branch target. The new label must have
+ * code attached to it later by calling {@link #mark(Label)}.
+ */
+ public Label newLabel() {
+ Label result = new Label();
+ labels.add(result);
+ return result;
+ }
+
+ /**
+ * Start defining instructions for the named label.
+ */
+ public void mark(Label label) {
+ if (label.marked) {
+ throw new IllegalStateException("already marked");
+ }
+ label.marked = true;
+ if (currentLabel != null) {
+ jump(label); // blocks must end with a branch, return or throw
+ }
+ currentLabel = label;
+ }
+
+ public void jump(Label target) {
+ addInstruction(new PlainInsn(Rops.GOTO, sourcePosition, null, RegisterSpecList.EMPTY),
+ target);
+ }
+
+ public void addCatchClause(Type<?> throwable, Label catchClause) {
+ if (catchTypes.contains(throwable)) {
+ throw new IllegalArgumentException("Already caught: " + throwable);
+ }
+ catchTypes.add(throwable);
+ catches = toTypeList(catchTypes);
+ catchLabels.add(catchClause);
+ }
+
+ public Label removeCatchClause(Type<?> throwable) {
+ int index = catchTypes.indexOf(throwable);
+ if (index == -1) {
+ throw new IllegalArgumentException("No catch clause: " + throwable);
+ }
+ catchTypes.remove(index);
+ catches = toTypeList(catchTypes);
+ return catchLabels.remove(index);
+ }
+
+ public void throwValue(Local<?> throwable) {
+ addInstruction(new ThrowingInsn(Rops.THROW, sourcePosition,
+ RegisterSpecList.make(throwable.spec()), catches));
+ }
+
+ private StdTypeList toTypeList(List<Type<?>> types) {
+ StdTypeList result = new StdTypeList(types.size());
+ for (int i = 0; i < types.size(); i++) {
+ result.set(i, types.get(i).ropType);
+ }
+ return result;
+ }
+
+ private void addInstruction(Insn insn) {
+ addInstruction(insn, null);
+ }
+
+ /**
+ * @param branch the branches to follow; interpretation depends on the
+ * instruction's branchingness.
+ */
+ private void addInstruction(Insn insn, Label branch) {
+ if (currentLabel == null || !currentLabel.marked) {
+ throw new IllegalStateException("no current label");
+ }
+ currentLabel.instructions.add(insn);
+
+ switch (insn.getOpcode().getBranchingness()) {
+ case BRANCH_NONE:
+ if (branch != null) {
+ throw new IllegalArgumentException("unexpected branch: " + branch);
+ }
+ return;
+
+ case BRANCH_RETURN:
+ if (branch != null) {
+ throw new IllegalArgumentException("unexpected branch: " + branch);
+ }
+ currentLabel = null;
+ break;
+
+ case BRANCH_GOTO:
+ if (branch == null) {
+ throw new IllegalArgumentException("branch == null");
+ }
+ currentLabel.primarySuccessor = branch;
+ currentLabel = null;
+ break;
+
+ case Rop.BRANCH_IF:
+ if (branch == null) {
+ throw new IllegalArgumentException("branch == null");
+ }
+ splitCurrentLabel(branch, Collections.<Label>emptyList());
+ break;
+
+ case Rop.BRANCH_THROW:
+ if (branch != null) {
+ throw new IllegalArgumentException("unexpected branch: " + branch);
+ }
+ splitCurrentLabel(null, new ArrayList<Label>(catchLabels));
+ break;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Closes the current label and starts a new one.
+ *
+ * @param catchLabels an immutable list of catch labels
+ */
+ private void splitCurrentLabel(Label alternateSuccessor, List<Label> catchLabels) {
+ Label newLabel = newLabel();
+ currentLabel.primarySuccessor = newLabel;
+ currentLabel.alternateSuccessor = alternateSuccessor;
+ currentLabel.catchLabels = catchLabels;
+ currentLabel = newLabel;
+ currentLabel.marked = true;
+ }
+
+ // instructions: constants
+
+ public <T> void loadConstant(Local<T> target, T value) {
+ Rop rop = Rops.opConst(target.type.ropType);
+ if (rop.getBranchingness() == BRANCH_NONE) {
+ addInstruction(new PlainCstInsn(rop, sourcePosition, target.spec(),
+ RegisterSpecList.EMPTY, Constants.getConstant(value)));
+ } else {
+ addInstruction(new ThrowingCstInsn(rop, sourcePosition,
+ RegisterSpecList.EMPTY, catches, Constants.getConstant(value)));
+ moveResult(target, true);
+ }
+ }
+
+ // instructions: unary
+
+ public <T> void negate(Local<T> source, Local<T> target) {
+ unary(Rops.opNeg(source.type.ropType), source, target);
+ }
+
+ public <T> void not(Local<T> source, Local<T> target) {
+ unary(Rops.opNot(source.type.ropType), source, target);
+ }
+
+ public void numericCast(Local<?> source, Local<?> target) {
+ unary(getCastRop(source.type.ropType, target.type.ropType), source, target);
+ }
+
+ private Rop getCastRop(com.android.dx.rop.type.Type sourceType,
+ com.android.dx.rop.type.Type targetType) {
+ if (sourceType.getBasicType() == BT_INT) {
+ switch (targetType.getBasicType()) {
+ case BT_SHORT:
+ return Rops.TO_SHORT;
+ case BT_CHAR:
+ return Rops.TO_CHAR;
+ case BT_BYTE:
+ return Rops.TO_BYTE;
+ }
+ }
+ return Rops.opConv(targetType, sourceType);
+ }
+
+ private void unary(Rop rop, Local<?> source, Local<?> target) {
+ addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), source.spec()));
+ }
+
+ // instructions: binary
+
+ public <T> void op(BinaryOp op, Local<T> target, Local<T> a, Local<T> b) {
+ Rop rop = op.rop(StdTypeList.make(a.type.ropType, b.type.ropType));
+ RegisterSpecList sources = RegisterSpecList.make(a.spec(), b.spec());
+
+ if (rop.getBranchingness() == BRANCH_NONE) {
+ addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), sources));
+ } else {
+ addInstruction(new ThrowingInsn(rop, sourcePosition, sources, catches));
+ moveResult(target, true);
+ }
+ }
+
+ // instructions: branches
+
+ /**
+ * Compare ints. If the comparison is true, execution jumps to {@code
+ * trueLabel}. If it is false, execution continues to the next instruction.
+ */
+ public <T> void compare(Comparison comparison, Local<T> a, Local<T> b, Label trueLabel) {
+ if (trueLabel == null) {
+ throw new IllegalArgumentException();
+ }
+ Rop rop = comparison.rop(StdTypeList.make(a.type.ropType, b.type.ropType));
+ addInstruction(new PlainInsn(rop, sourcePosition, null,
+ RegisterSpecList.make(a.spec(), b.spec())), trueLabel);
+ }
+
+ /**
+ * Compare floats or doubles.
+ */
+ public <T extends Number> void compare(Local<T> a, Local<T> b, Local<Integer> target,
+ int nanValue) {
+ Rop rop;
+ if (nanValue == 1) {
+ rop = Rops.opCmpg(a.type.ropType);
+ } else if (nanValue == -1) {
+ rop = Rops.opCmpl(a.type.ropType);
+ } else {
+ throw new IllegalArgumentException("expected 1 or -1 but was " + nanValue);
+ }
+ addInstruction(new PlainInsn(rop, sourcePosition, target.spec(),
+ RegisterSpecList.make(a.spec(), b.spec())));
+ }
+
+ /**
+ * Compare longs.
+ */
+ public <T> void compare(Local<T> a, Local<T> b, Local<?> target) {
+ addInstruction(new PlainInsn(Rops.CMPL_LONG, sourcePosition, target.spec(),
+ RegisterSpecList.make(a.spec(), b.spec())));
+ }
+
+ // instructions: fields
+
+ public <D, V> void iget(FieldId<D, V> fieldId, Local<D> instance, Local<V> target) {
+ addInstruction(new ThrowingCstInsn(Rops.opGetField(target.type.ropType), sourcePosition,
+ RegisterSpecList.make(instance.spec()), catches, fieldId.constant));
+ moveResult(target, true);
+ }
+
+ public <D, V> void iput(FieldId<D, V> fieldId, Local<D> instance, Local<V> source) {
+ addInstruction(new ThrowingCstInsn(Rops.opPutField(source.type.ropType), sourcePosition,
+ RegisterSpecList.make(source.spec(), instance.spec()), catches, fieldId.constant));
+ }
+
+ public <V> void sget(FieldId<?, V> fieldId, Local<V> target) {
+ addInstruction(new ThrowingCstInsn(Rops.opGetStatic(target.type.ropType), sourcePosition,
+ RegisterSpecList.EMPTY, catches, fieldId.constant));
+ moveResult(target, true);
+ }
+
+ public <V> void sput(FieldId<?, V> fieldId, Local<V> source) {
+ addInstruction(new ThrowingCstInsn(Rops.opPutStatic(source.type.ropType), sourcePosition,
+ RegisterSpecList.make(source.spec()), catches, fieldId.constant));
+ }
+
+ // instructions: invoke
+
+ public <T> void newInstance(Local<T> target, MethodId<T, Void> constructor, Local<?>... args) {
+ if (target == null) {
+ throw new IllegalArgumentException();
+ }
+ addInstruction(new ThrowingCstInsn(Rops.NEW_INSTANCE, sourcePosition,
+ RegisterSpecList.EMPTY, catches, constructor.declaringType.constant));
+ moveResult(target, true);
+ invokeDirect(constructor, null, target, args);
+ }
+
+ public <R> void invokeStatic(MethodId<?, R> method, Local<? super R> target, Local<?>... args) {
+ invoke(Rops.opInvokeStatic(method.prototype(true)), method, target, null, args);
+ }
+
+ public <D, R> void invokeVirtual(MethodId<D, R> method, Local<? super R> target,
+ Local<? extends D> object, Local<?>... args) {
+ invoke(Rops.opInvokeVirtual(method.prototype(true)), method, target, object, args);
+ }
+
+ public <D, R> void invokeDirect(MethodId<D, R> method, Local<? super R> target,
+ Local<? extends D> object, Local<?>... args) {
+ invoke(Rops.opInvokeDirect(method.prototype(true)), method, target, object, args);
+ }
+
+ public <D, R> void invokeSuper(MethodId<D, R> method, Local<? super R> target,
+ Local<? extends D> object, Local<?>... args) {
+ invoke(Rops.opInvokeSuper(method.prototype(true)), method, target, object, args);
+ }
+
+ public <D, R> void invokeInterface(MethodId<D, R> method, Local<? super R> target,
+ Local<? extends D> object, Local<?>... args) {
+ invoke(Rops.opInvokeInterface(method.prototype(true)), method, target, object, args);
+ }
+
+ private <D, R> void invoke(Rop rop, MethodId<D, R> method, Local<? super R> target,
+ Local<? extends D> object, Local<?>... args) {
+ addInstruction(new ThrowingCstInsn(rop, sourcePosition, concatenate(object, args),
+ catches, method.constant));
+ if (target != null) {
+ moveResult(target, false);
+ }
+ }
+
+ // instructions: types
+
+ public void instanceOfType(Local<?> target, Local<?> source, Type<?> type) {
+ addInstruction(new ThrowingCstInsn(Rops.INSTANCE_OF, sourcePosition,
+ RegisterSpecList.make(source.spec()), catches, type.constant));
+ moveResult(target, true);
+ }
+
+ public void typeCast(Local<?> source, Local<?> target) {
+ addInstruction(new ThrowingCstInsn(Rops.CHECK_CAST, sourcePosition,
+ RegisterSpecList.make(source.spec()), catches, target.type.constant));
+ moveResult(target, true);
+ }
+
+ // instructions: arrays
+
+ public <T> void arrayLength(Local<T> array, Local<Integer> target) {
+ addInstruction(new ThrowingInsn(Rops.ARRAY_LENGTH, sourcePosition,
+ RegisterSpecList.make(array.spec()), catches));
+ moveResult(target, true);
+ }
+
+ public <T> void newArray(Local<Integer> length, Local<T> target) {
+ addInstruction(new ThrowingCstInsn(Rops.opNewArray(target.type.ropType), sourcePosition,
+ RegisterSpecList.make(length.spec()), catches, target.type.constant));
+ moveResult(target, true);
+ }
+
+ public void aget(Local<?> array, Local<Integer> index, Local<?> target) {
+ addInstruction(new ThrowingInsn(Rops.opAget(target.type.ropType), sourcePosition,
+ RegisterSpecList.make(array.spec(), index.spec()), catches));
+ moveResult(target, true);
+ }
+
+ public void aput(Local<?> array, Local<Integer> index, Local<?> source) {
+ addInstruction(new ThrowingInsn(Rops.opAput(source.type.ropType), sourcePosition,
+ RegisterSpecList.make(source.spec(), array.spec(), index.spec()), catches));
+ }
+
+ // instructions: return
+
+ public void returnVoid() {
+ if (!method.returnType.equals(Type.VOID)) {
+ throw new IllegalArgumentException("declared " + method.returnType
+ + " but returned void");
+ }
+ addInstruction(new PlainInsn(Rops.RETURN_VOID, sourcePosition, null,
+ RegisterSpecList.EMPTY));
+ }
+
+ public void returnValue(Local<?> result) {
+ if (!result.type.equals(method.returnType)) {
+ // TODO: this is probably too strict.
+ throw new IllegalArgumentException("declared " + method.returnType
+ + " but returned " + result.type);
+ }
+ addInstruction(new PlainInsn(Rops.opReturn(result.type.ropType), sourcePosition,
+ null, RegisterSpecList.make(result.spec())));
+ }
+
+ private void moveResult(Local<?> target, boolean afterNonInvokeThrowingInsn) {
+ Rop rop = afterNonInvokeThrowingInsn
+ ? Rops.opMoveResultPseudo(target.type.ropType)
+ : Rops.opMoveResult(target.type.ropType);
+ addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), RegisterSpecList.EMPTY));
+ }
+
+ // produce BasicBlocks for dex
+
+ BasicBlockList toBasicBlocks() {
+ if (!localsInitialized) {
+ initializeLocals();
+ }
+
+ cleanUpLabels();
+
+ BasicBlockList result = new BasicBlockList(labels.size());
+ for (int i = 0; i < labels.size(); i++) {
+ result.set(i, labels.get(i).toBasicBlock());
+ }
+ return result;
+ }
+
+ /**
+ * Removes empty labels and assigns IDs to non-empty labels.
+ */
+ private void cleanUpLabels() {
+ int id = 0;
+ for (Iterator<Label> i = labels.iterator(); i.hasNext();) {
+ Label label = i.next();
+ if (label.isEmpty()) {
+ i.remove();
+ } else {
+ label.compact();
+ label.id = id++;
+ }
+ }
+ }
+
+ private static RegisterSpecList concatenate(Local<?> first, Local<?>[] rest) {
+ int offset = (first != null) ? 1 : 0;
+ RegisterSpecList result = new RegisterSpecList(offset + rest.length);
+ if (first != null) {
+ result.set(0, first.spec());
+ }
+ for (int i = 0; i < rest.length; i++) {
+ result.set(i + offset, rest[i].spec());
+ }
+ return result;
+ }
+}
diff --git a/dx/src/com/android/dx/gen/Comparison.java b/dx/src/com/android/dx/gen/Comparison.java
new file mode 100644
index 0000000..40a6e97
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Comparison.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.code.Rop;
+import com.android.dx.rop.code.Rops;
+import com.android.dx.rop.type.TypeList;
+
+/**
+ * A comparison between two values of the same type.
+ */
+public enum Comparison {
+
+ /** {@code a < b} */
+ LT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfLt(types);
+ }
+ },
+
+ /** {@code a <= b} */
+ LE() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfLe(types);
+ }
+ },
+
+ /** {@code a == b} */
+ EQ() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfEq(types);
+ }
+ },
+
+ /** {@code a >= b} */
+ GE() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfGe(types);
+ }
+ },
+
+ /** {@code a > b} */
+ GT() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfGt(types);
+ }
+ },
+
+ /** {@code a != b} */
+ NE() {
+ @Override Rop rop(TypeList types) {
+ return Rops.opIfNe(types);
+ }
+ };
+
+ abstract Rop rop(TypeList types);
+}
diff --git a/dx/src/com/android/dx/gen/Constants.java b/dx/src/com/android/dx/gen/Constants.java
new file mode 100644
index 0000000..255c2e4
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Constants.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.cst.CstBoolean;
+import com.android.dx.rop.cst.CstByte;
+import com.android.dx.rop.cst.CstChar;
+import com.android.dx.rop.cst.CstDouble;
+import com.android.dx.rop.cst.CstFloat;
+import com.android.dx.rop.cst.CstInteger;
+import com.android.dx.rop.cst.CstKnownNull;
+import com.android.dx.rop.cst.CstLong;
+import com.android.dx.rop.cst.CstShort;
+import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.cst.CstType;
+import com.android.dx.rop.cst.TypedConstant;
+
+/**
+ * Factory for rop constants.
+ */
+final class Constants {
+ private Constants() {}
+
+ /**
+ * Returns a rop constant for the specified value.
+ *
+ * @param value null, a boxed primitive, String, Class, or Type.
+ */
+ static TypedConstant getConstant(Object value) {
+ if (value == null) {
+ return CstKnownNull.THE_ONE;
+ } else if (value instanceof Boolean) {
+ return CstBoolean.make((Boolean) value);
+ } else if (value instanceof Byte) {
+ return CstByte.make((Byte) value);
+ } else if (value instanceof Character) {
+ return CstChar.make((Character) value);
+ } else if (value instanceof Double) {
+ return CstDouble.make(Double.doubleToLongBits((Double) value));
+ } else if (value instanceof Float) {
+ return CstFloat.make(Float.floatToIntBits((Float) value));
+ } else if (value instanceof Integer) {
+ return CstInteger.make((Integer) value);
+ } else if (value instanceof Long) {
+ return CstLong.make((Long) value);
+ } else if (value instanceof Short) {
+ return CstShort.make((Short) value);
+ } else if (value instanceof String) {
+ return new CstString((String) value);
+ } else if (value instanceof Class) {
+ return new CstType(Type.get((Class<?>) value).ropType);
+ } else if (value instanceof Type) {
+ return new CstType(((Type) value).ropType);
+ } else {
+ throw new UnsupportedOperationException("Not a constant: " + value);
+ }
+ }
+}
diff --git a/dx/src/com/android/dx/gen/DexGenerator.java b/dx/src/com/android/dx/gen/DexGenerator.java
new file mode 100644
index 0000000..9445be8
--- /dev/null
+++ b/dx/src/com/android/dx/gen/DexGenerator.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.dex.DexFormat;
+import com.android.dx.dex.DexOptions;
+import com.android.dx.dex.code.DalvCode;
+import com.android.dx.dex.code.PositionList;
+import com.android.dx.dex.code.RopTranslator;
+import com.android.dx.dex.file.ClassDefItem;
+import com.android.dx.dex.file.DexFile;
+import com.android.dx.dex.file.EncodedField;
+import com.android.dx.dex.file.EncodedMethod;
+import com.android.dx.rop.code.AccessFlags;
+import static com.android.dx.rop.code.AccessFlags.*;
+import com.android.dx.rop.code.LocalVariableInfo;
+import com.android.dx.rop.code.RopMethod;
+import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.cst.CstType;
+import com.android.dx.rop.type.StdTypeList;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+/**
+ * Define types, fields and methods.
+ */
+public final class DexGenerator {
+ private final Map<Type<?>, TypeDeclaration> types
+ = new LinkedHashMap<Type<?>, TypeDeclaration>();
+
+ private TypeDeclaration getTypeDeclaration(Type<?> type) {
+ TypeDeclaration result = types.get(type);
+ if (result == null) {
+ result = new TypeDeclaration(type);
+ types.put(type, result);
+ }
+ return result;
+ }
+
+ /**
+ * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#CLASS_FLAGS}.
+ */
+ public void declare(Type<?> type, String sourceFile, int flags,
+ Type<?> supertype, Type<?>... interfaces) {
+ TypeDeclaration declaration = getTypeDeclaration(type);
+ if (declaration.declared) {
+ throw new IllegalStateException("already declared: " + type);
+ }
+ declaration.declared = true;
+ declaration.flags = flags;
+ declaration.supertype = supertype;
+ declaration.sourceFile = sourceFile;
+ declaration.interfaces = new TypeList(interfaces);
+ }
+
+ /**
+ * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#METHOD_FLAGS}.
+ */
+ public Code declare(MethodId<?, ?> method, int flags) {
+ TypeDeclaration typeDeclaration = getTypeDeclaration(method.declaringType);
+ if (typeDeclaration.methods.containsKey(method)) {
+ throw new IllegalStateException("already declared: " + method);
+ }
+ MethodDeclaration methodDeclaration = new MethodDeclaration(method, flags);
+ typeDeclaration.methods.put(method, methodDeclaration);
+ return methodDeclaration.code;
+ }
+
+ /**
+ * @param flags any flags masked by {@link AccessFlags#FIELD_FLAGS}.
+ */
+ public void declare(FieldId<?, ?> fieldId, int flags, Object staticValue) {
+ TypeDeclaration typeDeclaration = getTypeDeclaration(fieldId.declaringType);
+ if (typeDeclaration.fields.containsKey(fieldId)) {
+ throw new IllegalStateException("already declared: " + fieldId);
+ }
+ FieldDeclaration fieldDeclaration = new FieldDeclaration(fieldId, flags, staticValue);
+ typeDeclaration.fields.put(fieldId, fieldDeclaration);
+ }
+
+ /**
+ * Returns a .dex formatted file.
+ */
+ public byte[] generate() {
+ DexFile outputDex = new DexFile();
+
+ for (TypeDeclaration typeDeclaration : types.values()) {
+ outputDex.add(typeDeclaration.toClassDefItem());
+ }
+
+ try {
+ return outputDex.toDex(null, false);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Loads the generated types into the current dalvikvm process.
+ */
+ public ClassLoader load(ClassLoader parent) throws IOException {
+ byte[] dex = generate();
+
+ /*
+ * This implementation currently dumps the dex to the filesystem. It
+ * jars the emitted .dex for the benefit of Gingerbread and earlier
+ * devices, which can't load .dex files directly.
+ *
+ * TODO: load the dex from memory where supported.
+ */
+ File result = File.createTempFile("Generated", ".jar");
+ result.deleteOnExit();
+ JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
+ jarOut.putNextEntry(new JarEntry(DexFormat.DEX_IN_JAR_NAME));
+ jarOut.write(dex);
+ jarOut.closeEntry();
+ jarOut.close();
+ try {
+ Class<?> pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
+ return (ClassLoader) pathClassLoader.getConstructor(String.class, ClassLoader.class)
+ .newInstance(result.getPath(), parent);
+ } catch (ClassNotFoundException e) {
+ throw new UnsupportedOperationException("load() requires a Dalvik VM", e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ } catch (InstantiationException e) {
+ throw new AssertionError();
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError();
+ } catch (IllegalAccessException e) {
+ throw new AssertionError();
+ }
+ }
+
+ private static class TypeDeclaration {
+ private final Type<?> type;
+
+ /** declared state */
+ private boolean declared;
+ private int flags;
+ private Type<?> supertype;
+ private String sourceFile;
+ private TypeList interfaces;
+
+ private final Map<FieldId, FieldDeclaration> fields
+ = new LinkedHashMap<FieldId, FieldDeclaration>();
+ private final Map<MethodId, MethodDeclaration> methods
+ = new LinkedHashMap<MethodId, MethodDeclaration>();
+
+ TypeDeclaration(Type<?> type) {
+ this.type = type;
+ }
+
+ ClassDefItem toClassDefItem() {
+ if (!declared) {
+ throw new IllegalStateException("Undeclared type " + type + " declares members: "
+ + fields.keySet() + " " + methods.keySet());
+ }
+
+ DexOptions dexOptions = new DexOptions();
+ dexOptions.enableExtendedOpcodes = false;
+
+ CstType thisType = type.constant;
+
+ ClassDefItem out = new ClassDefItem(thisType, flags, supertype.constant,
+ interfaces.ropTypes, new CstString(sourceFile));
+
+ for (MethodDeclaration method : methods.values()) {
+ EncodedMethod encoded = method.toEncodedMethod(dexOptions);
+ if (method.isDirect()) {
+ out.addDirectMethod(encoded);
+ } else {
+ out.addVirtualMethod(encoded);
+ }
+ }
+ for (FieldDeclaration field : fields.values()) {
+ EncodedField encoded = field.toEncodedField();
+ if (field.isStatic()) {
+ out.addStaticField(encoded, Constants.getConstant(field.staticValue));
+ } else {
+ out.addInstanceField(encoded);
+ }
+ }
+
+ return out;
+ }
+ }
+
+ static class FieldDeclaration {
+ final FieldId<?, ?> fieldId;
+ private final int accessFlags;
+ private final Object staticValue;
+
+ FieldDeclaration(FieldId<?, ?> fieldId, int accessFlags, Object staticValue) {
+ if ((accessFlags & (AccessFlags.ACC_STATIC)) == 0 && staticValue != null) {
+ throw new IllegalArgumentException("instance fields may not have a value");
+ }
+ this.fieldId = fieldId;
+ this.accessFlags = accessFlags;
+ this.staticValue = staticValue;
+ }
+
+ EncodedField toEncodedField() {
+ return new EncodedField(fieldId.constant, accessFlags);
+ }
+
+ public boolean isStatic() {
+ return (accessFlags & (AccessFlags.ACC_STATIC)) != 0;
+ }
+ }
+
+ static class MethodDeclaration {
+ final MethodId<?, ?> method;
+ private final int flags;
+ private final Code code;
+
+ public MethodDeclaration(MethodId<?, ?> method, int flags) {
+ this.method = method;
+ this.flags = flags;
+ this.code = new Code(this);
+ }
+
+ boolean isStatic() {
+ return (flags & ACC_STATIC) != 0;
+ }
+
+ boolean isDirect() {
+ return (flags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0;
+ }
+
+ EncodedMethod toEncodedMethod(DexOptions dexOptions) {
+ RopMethod ropMethod = new RopMethod(code.toBasicBlocks(), 0);
+ LocalVariableInfo locals = null;
+ DalvCode dalvCode = RopTranslator.translate(
+ ropMethod, PositionList.NONE, locals, code.paramSize(), dexOptions);
+ return new EncodedMethod(method.constant, flags, dalvCode, StdTypeList.EMPTY);
+ }
+ }
+}
diff --git a/dx/src/com/android/dx/gen/FieldId.java b/dx/src/com/android/dx/gen/FieldId.java
new file mode 100644
index 0000000..62ef73b
--- /dev/null
+++ b/dx/src/com/android/dx/gen/FieldId.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.cst.CstFieldRef;
+import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
+
+/**
+ * A field.
+ */
+public final class FieldId<D, V> {
+ final Type<D> declaringType;
+ final Type<V> type;
+ final String name;
+
+ /** cached converted state */
+ final CstNat nat;
+ final CstFieldRef constant;
+
+ FieldId(Type<D> declaringType, Type<V> type, String name) {
+ if (declaringType == null || type == null || name == null) {
+ throw new NullPointerException();
+ }
+ this.declaringType = declaringType;
+ this.type = type;
+ this.name = name;
+ this.nat = new CstNat(new CstString(name), new CstString(type.name));
+ this.constant = new CstFieldRef(declaringType.constant, nat);
+ }
+
+ public Type<D> getDeclaringType() {
+ return declaringType;
+ }
+
+ public Type<V> getType() {
+ return type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof FieldId
+ && ((FieldId<?, ?>) o).declaringType.equals(declaringType)
+ && ((FieldId<?, ?>) o).name.equals(name);
+ }
+
+ @Override public int hashCode() {
+ return declaringType.hashCode() + 37 * name.hashCode();
+ }
+
+ @Override public String toString() {
+ return declaringType + "." + name;
+ }
+}
diff --git a/dx/src/com/android/dx/gen/Label.java b/dx/src/com/android/dx/gen/Label.java
new file mode 100644
index 0000000..633b5f1
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Label.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.code.BasicBlock;
+import com.android.dx.rop.code.Insn;
+import com.android.dx.rop.code.InsnList;
+import com.android.dx.util.IntList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A branch target in a list of instructions.
+ */
+public final class Label {
+
+ final List<Insn> instructions = new ArrayList<Insn>();
+
+ boolean marked = false;
+
+ /** an immutable list of labels corresponding to the types in the catch list */
+ List<Label> catchLabels = Collections.emptyList();
+
+ /** contains the next instruction if no branch occurs */
+ Label primarySuccessor;
+
+ /** contains the instruction to jump to if the if is true */
+ Label alternateSuccessor;
+
+ int id = -1;
+
+ Label() {}
+
+ boolean isEmpty() {
+ return instructions.isEmpty();
+ }
+
+ void compact() {
+ for (int i = 0; i < catchLabels.size(); i++) {
+ while (catchLabels.get(i).isEmpty()) {
+ catchLabels.set(i, catchLabels.get(i).primarySuccessor);
+ }
+ }
+ while (primarySuccessor != null && primarySuccessor.isEmpty()) {
+ primarySuccessor = primarySuccessor.primarySuccessor;
+ }
+ while (alternateSuccessor != null && alternateSuccessor.isEmpty()) {
+ alternateSuccessor = alternateSuccessor.primarySuccessor;
+ }
+ }
+
+ BasicBlock toBasicBlock() {
+ InsnList result = new InsnList(instructions.size());
+ for (int i = 0; i < instructions.size(); i++) {
+ result.set(i, instructions.get(i));
+ }
+ result.setImmutable();
+
+ int primarySuccessorIndex = -1;
+ IntList successors = new IntList();
+ for (Label catchLabel : catchLabels) {
+ successors.add(catchLabel.id);
+ }
+ if (primarySuccessor != null) {
+ primarySuccessorIndex = primarySuccessor.id;
+ successors.add(primarySuccessorIndex);
+ }
+ if (alternateSuccessor != null) {
+ successors.add(alternateSuccessor.id);
+ }
+ successors.setImmutable();
+
+ return new BasicBlock(id, result, successors, primarySuccessorIndex);
+ }
+}
diff --git a/dx/src/com/android/dx/gen/Local.java b/dx/src/com/android/dx/gen/Local.java
new file mode 100644
index 0000000..b98759c
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Local.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.code.RegisterSpec;
+
+/**
+ * A temporary variable that holds a single value.
+ */
+public final class Local<T> {
+ private final Code code;
+ final Type<T> type;
+ private int reg = -1;
+ private RegisterSpec spec;
+
+ private Local(Code code, Type<T> type) {
+ this.code = code;
+ this.type = type;
+ }
+
+ static <T> Local<T> get(Code code, Type<T> type) {
+ return new Local<T>(code, type);
+ }
+
+ /**
+ * Assigns registers to this local.
+ *
+ * @return the number of registers required.
+ */
+ int initialize(int reg) {
+ this.reg = reg;
+ this.spec = RegisterSpec.make(reg, type.ropType);
+ return size();
+ }
+
+ int size() {
+ return type.ropType.getCategory();
+ }
+
+ RegisterSpec spec() {
+ if (spec == null) {
+ code.initializeLocals();
+ if (spec == null) {
+ throw new AssertionError();
+ }
+ }
+ return spec;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ @Override public String toString() {
+ return "v" + reg + "(" + type + ")";
+ }
+}
diff --git a/dx/src/com/android/dx/gen/MethodId.java b/dx/src/com/android/dx/gen/MethodId.java
new file mode 100644
index 0000000..29d088a
--- /dev/null
+++ b/dx/src/com/android/dx/gen/MethodId.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.cst.CstMethodRef;
+import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.type.Prototype;
+import java.util.List;
+
+/**
+ * A method or constructor.
+ */
+public final class MethodId<D, R> {
+ final Type<D> declaringType;
+ final Type<R> returnType;
+ final String name;
+ final TypeList parameters;
+
+ /** cached converted state */
+ final CstNat nat;
+ final CstMethodRef constant;
+
+ MethodId(Type<D> declaringType, Type<R> returnType, String name, TypeList parameters) {
+ if (declaringType == null || returnType == null || name == null || parameters == null) {
+ throw new NullPointerException();
+ }
+ this.declaringType = declaringType;
+ this.returnType = returnType;
+ this.name = name;
+ this.parameters = parameters;
+ this.nat = new CstNat(new CstString(name), new CstString(descriptor(false)));
+ this.constant = new CstMethodRef(declaringType.constant, nat);
+ }
+
+ public Type<D> getDeclaringType() {
+ return declaringType;
+ }
+
+ public Type<R> getReturnType() {
+ return returnType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<Type<?>> getParameters() {
+ return parameters.asList();
+ }
+
+ /**
+ * Returns a descriptor like "(Ljava/lang/Class;[I)Ljava/lang/Object;".
+ */
+ String descriptor(boolean includeThis) {
+ StringBuilder result = new StringBuilder();
+ result.append("(");
+ if (includeThis) {
+ result.append(declaringType.name);
+ }
+ for (Type t : parameters.types) {
+ result.append(t.name);
+ }
+ result.append(")");
+ result.append(returnType.name);
+ return result.toString();
+ }
+
+ Prototype prototype(boolean includeThis) {
+ return Prototype.intern(descriptor(includeThis));
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof MethodId
+ && ((MethodId<?, ?>) o).declaringType.equals(declaringType)
+ && ((MethodId<?, ?>) o).name.equals(name)
+ && ((MethodId<?, ?>) o).parameters.equals(parameters)
+ && ((MethodId<?, ?>) o).returnType.equals(returnType);
+ }
+
+ @Override public int hashCode() {
+ int result = 17;
+ result = 31 * result + declaringType.hashCode();
+ result = 31 * result + name.hashCode();
+ result = 31 * result + parameters.hashCode();
+ result = 31 * result + returnType.hashCode();
+ return result;
+ }
+
+ @Override public String toString() {
+ return declaringType + "." + name + "(" + parameters + ")";
+ }
+}
diff --git a/dx/src/com/android/dx/gen/Type.java b/dx/src/com/android/dx/gen/Type.java
new file mode 100644
index 0000000..3b81f6d
--- /dev/null
+++ b/dx/src/com/android/dx/gen/Type.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.cst.CstType;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A primitive type, interface or class.
+ */
+public final class Type<T> {
+ /** The {@code boolean} primitive type. */
+ public static final Type<Boolean> BOOLEAN
+ = new Type<Boolean>(com.android.dx.rop.type.Type.BOOLEAN);
+
+ /** The {@code byte} primitive type. */
+ public static final Type<Byte> BYTE = new Type<Byte>(com.android.dx.rop.type.Type.BYTE);
+
+ /** The {@code char} primitive type. */
+ public static final Type<Character> CHAR
+ = new Type<Character>(com.android.dx.rop.type.Type.CHAR);
+
+ /** The {@code double} primitive type. */
+ public static final Type<Double> DOUBLE = new Type<Double>(com.android.dx.rop.type.Type.DOUBLE);
+
+ /** The {@code float} primitive type. */
+ public static final Type<Float> FLOAT = new Type<Float>(com.android.dx.rop.type.Type.FLOAT);
+
+ /** The {@code int} primitive type. */
+ public static final Type<Integer> INT = new Type<Integer>(com.android.dx.rop.type.Type.INT);
+
+ /** The {@code long} primitive type. */
+ public static final Type<Long> LONG = new Type<Long>(com.android.dx.rop.type.Type.LONG);
+
+ /** The {@code short} primitive type. */
+ public static final Type<Short> SHORT = new Type<Short>(com.android.dx.rop.type.Type.SHORT);
+
+ /** The {@code void} primitive type. Only used as a return type. */
+ public static final Type<Void> VOID = new Type<Void>(com.android.dx.rop.type.Type.VOID);
+
+ /** The {@code Object} type. */
+ public static final Type<Object> OBJECT = new Type<Object>(com.android.dx.rop.type.Type.OBJECT);
+
+ /** The {@code String} type. */
+ public static final Type<String> STRING = new Type<String>(com.android.dx.rop.type.Type.STRING);
+
+ private static final Map<Class<?>, Type<?>> PRIMITIVE_TO_TYPE
+ = new HashMap<Class<?>, Type<?>>();
+ static {
+ PRIMITIVE_TO_TYPE.put(boolean.class, BOOLEAN);
+ PRIMITIVE_TO_TYPE.put(byte.class, BYTE);
+ PRIMITIVE_TO_TYPE.put(char.class, CHAR);
+ PRIMITIVE_TO_TYPE.put(double.class, DOUBLE);
+ PRIMITIVE_TO_TYPE.put(float.class, FLOAT);
+ PRIMITIVE_TO_TYPE.put(int.class, INT);
+ PRIMITIVE_TO_TYPE.put(long.class, LONG);
+ PRIMITIVE_TO_TYPE.put(short.class, SHORT);
+ PRIMITIVE_TO_TYPE.put(void.class, VOID);
+ }
+
+ final String name;
+
+ /** cached converted values */
+ final com.android.dx.rop.type.Type ropType;
+ final CstType constant;
+
+ Type(com.android.dx.rop.type.Type ropType) {
+ this(ropType.getDescriptor(), ropType);
+ }
+
+ Type(String name, com.android.dx.rop.type.Type ropType) {
+ if (name == null || ropType == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ this.ropType = ropType;
+ this.constant = CstType.intern(ropType);
+ }
+
+ /**
+ * @param name a descriptor like "Ljava/lang/Class;".
+ */
+ public static <T> Type<T> get(String name) {
+ return new Type<T>(name, com.android.dx.rop.type.Type.internReturnType(name));
+ }
+
+ public static <T> Type<T> get(Class<T> type) {
+ if (type.isPrimitive()) {
+ @SuppressWarnings("unchecked") // guarded by equals
+ Type<T> result = (Type<T>) PRIMITIVE_TO_TYPE.get(type);
+ return result;
+ }
+ String name = type.getName().replace('.', '/');
+ return get(type.isArray() ? name : 'L' + name + ';');
+ }
+
+ public <V> FieldId<T, V> getField(Type<V> type, String name) {
+ return new FieldId<T, V>(this, type, name);
+ }
+
+ public MethodId<T, Void> getConstructor(Type<?>... parameters) {
+ return new MethodId<T, Void>(this, VOID, "<init>", new TypeList(parameters));
+ }
+
+ public <R> MethodId<T, R> getMethod(Type<R> returnType, String name, Type<?>... parameters) {
+ return new MethodId<T, R>(this, returnType, name, new TypeList(parameters));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof Type
+ && ((Type) o).name.equals(name);
+ }
+
+ @Override public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override public String toString() {
+ return name;
+ }
+}
diff --git a/dx/src/com/android/dx/gen/TypeList.java b/dx/src/com/android/dx/gen/TypeList.java
new file mode 100644
index 0000000..e18ed4a
--- /dev/null
+++ b/dx/src/com/android/dx/gen/TypeList.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.dx.gen;
+
+import com.android.dx.rop.type.StdTypeList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * An immutable of types.
+ */
+final class TypeList {
+ final Type<?>[] types;
+ final StdTypeList ropTypes;
+
+ TypeList(Type<?>[] types) {
+ this.types = types.clone();
+ this.ropTypes = new StdTypeList(types.length);
+ for (int i = 0; i < types.length; i++) {
+ ropTypes.set(i, types[i].ropType);
+ }
+ }
+
+ /**
+ * Returns an immutable list.
+ */
+ public List<Type<?>> asList() {
+ return Collections.unmodifiableList(Arrays.asList(types));
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof TypeList && Arrays.equals(((TypeList) o).types, types);
+ }
+
+ @Override public int hashCode() {
+ return Arrays.hashCode(types);
+ }
+
+ @Override public String toString() {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < types.length; i++) {
+ if (i > 0) {
+ result.append(", ");
+ }
+ result.append(types[i]);
+ }
+ return result.toString();
+ }
+}
diff --git a/dx/src/com/android/dx/io/FieldId.java b/dx/src/com/android/dx/io/FieldId.java
index 712675f..da409fa 100644
--- a/dx/src/com/android/dx/io/FieldId.java
+++ b/dx/src/com/android/dx/io/FieldId.java
@@ -63,8 +63,6 @@
if (buffer == null) {
return declaringClassIndex + " " + typeIndex + " " + nameIndex;
}
- return buffer.typeNames().get(declaringClassIndex)
- + " { " + buffer.typeNames().get(typeIndex)
- + " " + buffer.strings().get(nameIndex) + " }";
+ return buffer.typeNames().get(typeIndex) + "." + buffer.strings().get(nameIndex);
}
}
diff --git a/dx/src/com/android/dx/io/MethodId.java b/dx/src/com/android/dx/io/MethodId.java
index 614e97f..e653661 100644
--- a/dx/src/com/android/dx/io/MethodId.java
+++ b/dx/src/com/android/dx/io/MethodId.java
@@ -64,7 +64,7 @@
return declaringClassIndex + " " + protoIndex + " " + nameIndex;
}
return buffer.typeNames().get(declaringClassIndex)
- + " " + buffer.protoIds().get(protoIndex)
- + " " + buffer.strings().get(nameIndex);
+ + "." + buffer.strings().get(nameIndex)
+ + buffer.readTypeList(buffer.protoIds().get(protoIndex).getParametersOffset());
}
}
diff --git a/dx/src/com/android/dx/merge/TypeList.java b/dx/src/com/android/dx/merge/TypeList.java
index 1619f19..62984e2 100644
--- a/dx/src/com/android/dx/merge/TypeList.java
+++ b/dx/src/com/android/dx/merge/TypeList.java
@@ -46,20 +46,12 @@
}
@Override public String toString() {
- if (buffer == null) {
- return Arrays.toString(types);
- }
-
StringBuilder result = new StringBuilder();
- result.append("[");
+ result.append("(");
for (int i = 0, typesLength = types.length; i < typesLength; i++) {
- short parameter = types[i];
- if (i > 0) {
- result.append(", ");
- }
- result.append(buffer.typeNames().get(parameter));
+ result.append(buffer != null ? buffer.typeNames().get(types[i]) : types[i]);
}
- result.append("]");
+ result.append(")");
return result.toString();
}
}
diff --git a/dx/src/com/android/dx/rop/annotation/Annotation.java b/dx/src/com/android/dx/rop/annotation/Annotation.java
index ad6d67e..8f9e976 100644
--- a/dx/src/com/android/dx/rop/annotation/Annotation.java
+++ b/dx/src/com/android/dx/rop/annotation/Annotation.java
@@ -16,16 +16,8 @@
package com.android.dx.rop.annotation;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstLiteralBits;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.cst.TypedConstant;
-import com.android.dx.util.Hex;
import com.android.dx.util.MutabilityControl;
import com.android.dx.util.ToHuman;
@@ -48,7 +40,7 @@
private final AnnotationVisibility visibility;
/** {@code non-null;} map from names to {@link NameValuePair} instances */
- private final TreeMap<CstUtf8, NameValuePair> elements;
+ private final TreeMap<CstString, NameValuePair> elements;
/**
* Construct an instance. It initially contains no elements.
@@ -67,7 +59,7 @@
this.type = type;
this.visibility = visibility;
- this.elements = new TreeMap<CstUtf8, NameValuePair>();
+ this.elements = new TreeMap<CstString, NameValuePair>();
}
/** {@inheritDoc} */
@@ -211,7 +203,7 @@
throw new NullPointerException("pair == null");
}
- CstUtf8 name = pair.getName();
+ CstString name = pair.getName();
if (elements.get(name) != null) {
throw new IllegalArgumentException("name already added: " + name);
diff --git a/dx/src/com/android/dx/rop/annotation/NameValuePair.java b/dx/src/com/android/dx/rop/annotation/NameValuePair.java
index 39a9dfd..56c4936 100644
--- a/dx/src/com/android/dx/rop/annotation/NameValuePair.java
+++ b/dx/src/com/android/dx/rop/annotation/NameValuePair.java
@@ -18,14 +18,13 @@
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstUtf8;
/**
* A (name, value) pair. These are used as the contents of an annotation.
*/
public final class NameValuePair implements Comparable<NameValuePair> {
/** {@code non-null;} the name */
- private final CstUtf8 name;
+ private final CstString name;
/** {@code non-null;} the value */
private final Constant value;
@@ -36,7 +35,7 @@
* @param name {@code non-null;} the name
* @param value {@code non-null;} the value
*/
- public NameValuePair(CstUtf8 name, Constant value) {
+ public NameValuePair(CstString name, Constant value) {
if (name == null) {
throw new NullPointerException("name == null");
}
@@ -45,11 +44,6 @@
throw new NullPointerException("value == null");
}
- // Reject CstUtf8 values. (They should be CstStrings.)
- if (value instanceof CstUtf8) {
- throw new IllegalArgumentException("bad value: " + value);
- }
-
this.name = name;
this.value = value;
}
@@ -97,7 +91,7 @@
*
* @return {@code non-null;} the name
*/
- public CstUtf8 getName() {
+ public CstString getName() {
return name;
}
diff --git a/dx/src/com/android/dx/rop/code/BasicBlock.java b/dx/src/com/android/dx/rop/code/BasicBlock.java
index d6ee886..9d99833 100644
--- a/dx/src/com/android/dx/rop/code/BasicBlock.java
+++ b/dx/src/com/android/dx/rop/code/BasicBlock.java
@@ -103,7 +103,7 @@
if (primarySuccessor >= 0 && !successors.contains(primarySuccessor)) {
throw new IllegalArgumentException(
- "primarySuccessor not in successors");
+ "primarySuccessor " + primarySuccessor + " not in successors " + successors);
}
this.label = label;
diff --git a/dx/src/com/android/dx/rop/code/Insn.java b/dx/src/com/android/dx/rop/code/Insn.java
index 7b79422..5031f89 100644
--- a/dx/src/com/android/dx/rop/code/Insn.java
+++ b/dx/src/com/android/dx/rop/code/Insn.java
@@ -16,8 +16,6 @@
package com.android.dx.rop.code;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
diff --git a/dx/src/com/android/dx/rop/code/LocalItem.java b/dx/src/com/android/dx/rop/code/LocalItem.java
index 82b227c..d238f21 100644
--- a/dx/src/com/android/dx/rop/code/LocalItem.java
+++ b/dx/src/com/android/dx/rop/code/LocalItem.java
@@ -16,17 +16,17 @@
package com.android.dx.rop.code;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
/**
* A local variable item: either a name or a signature or both.
*/
public class LocalItem implements Comparable<LocalItem> {
/** {@code null-ok;} local variable name */
- private final CstUtf8 name;
+ private final CstString name;
/** {@code null-ok;} local variable signature */
- private final CstUtf8 signature;
+ private final CstString signature;
/**
* Make a new item. If both name and signature are null, null is returned.
@@ -37,7 +37,7 @@
* @param signature {@code null-ok;} local variable signature
* @return {@code non-null;} appropriate instance.
*/
- public static LocalItem make(CstUtf8 name, CstUtf8 signature) {
+ public static LocalItem make(CstString name, CstString signature) {
if (name == null && signature == null) {
return null;
}
@@ -51,7 +51,7 @@
* @param name {@code null-ok;} local variable name
* @param signature {@code null-ok;} local variable signature
*/
- private LocalItem(CstUtf8 name, CstUtf8 signature) {
+ private LocalItem(CstString name, CstString signature) {
this.name = name;
this.signature = signature;
}
@@ -75,7 +75,7 @@
* @return negative integer, zero, or positive integer in accordance
* with Comparable.compareTo()
*/
- private static int compareHandlesNulls(CstUtf8 a, CstUtf8 b) {
+ private static int compareHandlesNulls(CstString a, CstString b) {
if (a == b) {
return 0;
} else if (a == null) {
@@ -128,7 +128,7 @@
*
* @return {@code null-ok;} name
*/
- public CstUtf8 getName() {
+ public CstString getName() {
return name;
}
@@ -137,7 +137,7 @@
*
* @return {@code null-ok;} signature
*/
- public CstUtf8 getSignature() {
+ public CstString getSignature() {
return signature;
}
}
diff --git a/dx/src/com/android/dx/rop/code/PlainInsn.java b/dx/src/com/android/dx/rop/code/PlainInsn.java
index 027249f..3b52efa 100644
--- a/dx/src/com/android/dx/rop/code/PlainInsn.java
+++ b/dx/src/com/android/dx/rop/code/PlainInsn.java
@@ -106,31 +106,41 @@
TypeBearer lastType = sources.get(szSources - 1).getTypeBearer();
- // TODO: Check for reverse subtraction, where first source is constant
if (!lastType.isConstant()) {
- return this;
- }
-
- Constant cst = (Constant) lastType;
-
- RegisterSpecList newSources = sources.withoutLast();
-
- Rop newRop;
- try {
- // Check for constant subtraction and flip them to be addition
- int opcode = getOpcode().getOpcode();
- if (opcode == RegOps.SUB && cst instanceof CstInteger) {
- opcode = RegOps.ADD;
- cst = CstInteger.make(-((CstInteger)cst).getValue());
+ // Check for reverse subtraction, where first source is constant
+ TypeBearer firstType = sources.get(0).getTypeBearer();
+ if (szSources == 2 && firstType.isConstant()) {
+ Constant cst = (Constant) firstType;
+ RegisterSpecList newSources = sources.withoutFirst();
+ Rop newRop = Rops.ropFor(getOpcode().getOpcode(), getResult(),
+ newSources, cst);
+ return new PlainCstInsn(newRop, getPosition(), getResult(),
+ newSources, cst);
}
- newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
- } catch (IllegalArgumentException ex) {
- // There's no rop for this case
return this;
- }
+ } else {
- return new PlainCstInsn(newRop, getPosition(),
- getResult(), newSources, cst);
+ Constant cst = (Constant) lastType;
+
+ RegisterSpecList newSources = sources.withoutLast();
+
+ Rop newRop;
+ try {
+ // Check for constant subtraction and flip it to be addition
+ int opcode = getOpcode().getOpcode();
+ if (opcode == RegOps.SUB && cst instanceof CstInteger) {
+ opcode = RegOps.ADD;
+ cst = CstInteger.make(-((CstInteger)cst).getValue());
+ }
+ newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
+ } catch (IllegalArgumentException ex) {
+ // There's no rop for this case
+ return this;
+ }
+
+ return new PlainCstInsn(newRop, getPosition(),
+ getResult(), newSources, cst);
+ }
}
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpec.java b/dx/src/com/android/dx/rop/code/RegisterSpec.java
index 0042cf2..e5f908b 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpec.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpec.java
@@ -17,7 +17,7 @@
package com.android.dx.rop.code;
import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeBearer;
import com.android.dx.util.ToHuman;
@@ -581,8 +581,10 @@
if (justType != type) {
sb.append("=");
- if (human && (type instanceof Constant)) {
- sb.append(((Constant) type).toHuman());
+ if (human && (type instanceof CstString)) {
+ sb.append(((CstString) type).toQuoted());
+ } else if (human && (type instanceof Constant)) {
+ sb.append(type.toHuman());
} else {
sb.append(type);
}
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
index d16a82a..14ef778 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
@@ -17,7 +17,6 @@
package com.android.dx.rop.code;
import com.android.dx.util.MutabilityControl;
-import com.android.dx.rop.cst.CstUtf8;
/**
* Set of {@link RegisterSpec} instances, where a given register number
diff --git a/dx/src/com/android/dx/rop/code/Rops.java b/dx/src/com/android/dx/rop/code/Rops.java
index 9085ff4..c1f4f46 100644
--- a/dx/src/com/android/dx/rop/code/Rops.java
+++ b/dx/src/com/android/dx/rop/code/Rops.java
@@ -1720,6 +1720,7 @@
case Type.BT_LONG: return CONV_I2L;
case Type.BT_FLOAT: return CONV_I2F;
case Type.BT_DOUBLE: return CONV_I2D;
+ default: break;
}
}
case Type.BT_LONG: {
@@ -1727,6 +1728,7 @@
case Type.BT_INT: return CONV_L2I;
case Type.BT_FLOAT: return CONV_L2F;
case Type.BT_DOUBLE: return CONV_L2D;
+ default: break;
}
}
case Type.BT_FLOAT: {
@@ -1734,13 +1736,15 @@
case Type.BT_INT: return CONV_F2I;
case Type.BT_LONG: return CONV_F2L;
case Type.BT_DOUBLE: return CONV_F2D;
+ default: break;
}
}
case Type.BT_DOUBLE: {
switch (dbt) {
- case Type.BT_INT: return CONV_D2I;
- case Type.BT_LONG: return CONV_D2L;
- case Type.BT_FLOAT: return CONV_D2F;
+ case Type.BT_INT: return CONV_D2I;
+ case Type.BT_LONG: return CONV_D2L;
+ case Type.BT_FLOAT: return CONV_D2F;
+ default: break;
}
}
}
diff --git a/dx/src/com/android/dx/rop/code/SourcePosition.java b/dx/src/com/android/dx/rop/code/SourcePosition.java
index f7a7961..11ac992 100644
--- a/dx/src/com/android/dx/rop/code/SourcePosition.java
+++ b/dx/src/com/android/dx/rop/code/SourcePosition.java
@@ -16,7 +16,7 @@
package com.android.dx.rop.code;
-import com.android.dx.rop.cst.CstUtf8;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.util.Hex;
/**
@@ -29,7 +29,7 @@
new SourcePosition(null, -1, -1);
/** {@code null-ok;} name of the file of origin or {@code null} if unknown */
- private final CstUtf8 sourceFile;
+ private final CstString sourceFile;
/**
* {@code >= -1;} the bytecode address, or {@code -1} if that
@@ -53,7 +53,7 @@
* @param line {@code >= -1;} original line number or {@code -1} if
* unknown
*/
- public SourcePosition(CstUtf8 sourceFile, int address, int line) {
+ public SourcePosition(CstString sourceFile, int address, int line) {
if (address < -1) {
throw new IllegalArgumentException("address < -1");
}
@@ -143,7 +143,7 @@
*
* @return {@code null-ok;} the source file or {@code null} if unknown
*/
- public CstUtf8 getSourceFile() {
+ public CstString getSourceFile() {
return sourceFile;
}
diff --git a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java b/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
index cdd21d1..dee01b5 100644
--- a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
+++ b/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
@@ -17,6 +17,7 @@
package com.android.dx.rop.code;
import com.android.dx.rop.cst.Constant;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
@@ -57,8 +58,12 @@
/** {@inheritDoc} */
@Override
public String getInlineString() {
- return getConstant().toHuman() + " " +
- ThrowingInsn.toCatchString(catches);
+ Constant cst = getConstant();
+ String constantString = cst.toHuman();
+ if (cst instanceof CstString) {
+ constantString = ((CstString) cst).toQuoted();
+ }
+ return constantString + " " + ThrowingInsn.toCatchString(catches);
}
/** {@inheritDoc} */
diff --git a/dx/src/com/android/dx/rop/cst/CstArray.java b/dx/src/com/android/dx/rop/cst/CstArray.java
index cb7d54d..2766b5f 100644
--- a/dx/src/com/android/dx/rop/cst/CstArray.java
+++ b/dx/src/com/android/dx/rop/cst/CstArray.java
@@ -20,8 +20,7 @@
import com.android.dx.util.FixedSizeList;
/**
- * Constant type to represent a fixed array of other constants. The contents
- * may be of any type <i>other</i> than {@link CstUtf8}.
+ * Constant type to represent a fixed array of other constants.
*/
public final class CstArray extends Constant {
/** {@code non-null;} the actual list of contents */
@@ -154,10 +153,6 @@
* @param a {@code null-ok;} the element to set at {@code n}
*/
public void set(int n, Constant a) {
- if (a instanceof CstUtf8) {
- throw new IllegalArgumentException("bad value: " + a);
- }
-
set0(n, a);
}
}
diff --git a/dx/src/com/android/dx/rop/cst/CstFieldRef.java b/dx/src/com/android/dx/rop/cst/CstFieldRef.java
index 06f0b15..a4d7180 100644
--- a/dx/src/com/android/dx/rop/cst/CstFieldRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstFieldRef.java
@@ -72,8 +72,8 @@
}
CstFieldRef otherField = (CstFieldRef) other;
- CstUtf8 thisDescriptor = getNat().getDescriptor();
- CstUtf8 otherDescriptor = otherField.getNat().getDescriptor();
+ CstString thisDescriptor = getNat().getDescriptor();
+ CstString otherDescriptor = otherField.getNat().getDescriptor();
return thisDescriptor.compareTo(otherDescriptor);
}
}
diff --git a/dx/src/com/android/dx/rop/cst/CstMemberRef.java b/dx/src/com/android/dx/rop/cst/CstMemberRef.java
index 0791087..1775398 100644
--- a/dx/src/com/android/dx/rop/cst/CstMemberRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstMemberRef.java
@@ -79,8 +79,8 @@
return cmp;
}
- CstUtf8 thisName = nat.getName();
- CstUtf8 otherName = otherMember.nat.getName();
+ CstString thisName = nat.getName();
+ CstString otherName = otherMember.nat.getName();
return thisName.compareTo(otherName);
}
diff --git a/dx/src/com/android/dx/rop/cst/CstNat.java b/dx/src/com/android/dx/rop/cst/CstNat.java
index 8a2c591..cd067e9 100644
--- a/dx/src/com/android/dx/rop/cst/CstNat.java
+++ b/dx/src/com/android/dx/rop/cst/CstNat.java
@@ -28,14 +28,14 @@
* wrapped primitives
*/
public static final CstNat PRIMITIVE_TYPE_NAT =
- new CstNat(new CstUtf8("TYPE"),
- new CstUtf8("Ljava/lang/Class;"));
+ new CstNat(new CstString("TYPE"),
+ new CstString("Ljava/lang/Class;"));
/** {@code non-null;} the name */
- private final CstUtf8 name;
+ private final CstString name;
/** {@code non-null;} the descriptor (type) */
- private final CstUtf8 descriptor;
+ private final CstString descriptor;
/**
* Constructs an instance.
@@ -43,7 +43,7 @@
* @param name {@code non-null;} the name
* @param descriptor {@code non-null;} the descriptor
*/
- public CstNat(CstUtf8 name, CstUtf8 descriptor) {
+ public CstNat(CstString name, CstString descriptor) {
if (name == null) {
throw new NullPointerException("name == null");
}
@@ -110,7 +110,7 @@
*
* @return {@code non-null;} the name
*/
- public CstUtf8 getName() {
+ public CstString getName() {
return name;
}
@@ -119,7 +119,7 @@
*
* @return {@code non-null;} the descriptor
*/
- public CstUtf8 getDescriptor() {
+ public CstString getDescriptor() {
return descriptor;
}
diff --git a/dx/src/com/android/dx/rop/cst/CstString.java b/dx/src/com/android/dx/rop/cst/CstString.java
index 7dbfa02..a778e97 100644
--- a/dx/src/com/android/dx/rop/cst/CstString.java
+++ b/dx/src/com/android/dx/rop/cst/CstString.java
@@ -17,35 +17,187 @@
package com.android.dx.rop.cst;
import com.android.dx.rop.type.Type;
+import com.android.dx.util.ByteArray;
+import com.android.dx.util.Hex;
/**
- * Constants of type {@code CONSTANT_String_info}.
+ * Constants of type {@code CONSTANT_Utf8_info} or {@code CONSTANT_String_info}.
*/
-public final class CstString
- extends TypedConstant {
- /** {@code non-null;} the string value */
- private final CstUtf8 string;
+public final class CstString extends TypedConstant {
+ /**
+ * {@code non-null;} instance representing {@code ""}, that is, the
+ * empty string
+ */
+ public static final CstString EMPTY_STRING = new CstString("");
+
+ /** {@code non-null;} the UTF-8 value as a string */
+ private final String string;
+
+ /** {@code non-null;} the UTF-8 value as bytes */
+ private final ByteArray bytes;
/**
- * Constructs an instance.
+ * Converts a string into its MUTF-8 form. MUTF-8 differs from normal UTF-8
+ * in the handling of character '\0' and surrogate pairs.
*
- * @param string {@code non-null;} the string value
+ * @param string {@code non-null;} the string to convert
+ * @return {@code non-null;} the UTF-8 bytes for it
*/
- public CstString(CstUtf8 string) {
+ public static byte[] stringToUtf8Bytes(String string) {
+ int len = string.length();
+ byte[] bytes = new byte[len * 3]; // Avoid having to reallocate.
+ int outAt = 0;
+
+ for (int i = 0; i < len; i++) {
+ char c = string.charAt(i);
+ if ((c != 0) && (c < 0x80)) {
+ bytes[outAt] = (byte) c;
+ outAt++;
+ } else if (c < 0x800) {
+ bytes[outAt] = (byte) (((c >> 6) & 0x1f) | 0xc0);
+ bytes[outAt + 1] = (byte) ((c & 0x3f) | 0x80);
+ outAt += 2;
+ } else {
+ bytes[outAt] = (byte) (((c >> 12) & 0x0f) | 0xe0);
+ bytes[outAt + 1] = (byte) (((c >> 6) & 0x3f) | 0x80);
+ bytes[outAt + 2] = (byte) ((c & 0x3f) | 0x80);
+ outAt += 3;
+ }
+ }
+
+ byte[] result = new byte[outAt];
+ System.arraycopy(bytes, 0, result, 0, outAt);
+ return result;
+ }
+
+ /**
+ * Converts an array of UTF-8 bytes into a string.
+ *
+ * @param bytes {@code non-null;} the bytes to convert
+ * @return {@code non-null;} the converted string
+ */
+ public static String utf8BytesToString(ByteArray bytes) {
+ int length = bytes.size();
+ char[] chars = new char[length]; // This is sized to avoid a realloc.
+ int outAt = 0;
+
+ for (int at = 0; length > 0; /*at*/) {
+ int v0 = bytes.getUnsignedByte(at);
+ char out;
+ switch (v0 >> 4) {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07: {
+ // 0XXXXXXX -- single-byte encoding
+ length--;
+ if (v0 == 0) {
+ // A single zero byte is illegal.
+ return throwBadUtf8(v0, at);
+ }
+ out = (char) v0;
+ at++;
+ break;
+ }
+ case 0x0c: case 0x0d: {
+ // 110XXXXX -- two-byte encoding
+ length -= 2;
+ if (length < 0) {
+ return throwBadUtf8(v0, at);
+ }
+ int v1 = bytes.getUnsignedByte(at + 1);
+ if ((v1 & 0xc0) != 0x80) {
+ return throwBadUtf8(v1, at + 1);
+ }
+ int value = ((v0 & 0x1f) << 6) | (v1 & 0x3f);
+ if ((value != 0) && (value < 0x80)) {
+ /*
+ * This should have been represented with
+ * one-byte encoding.
+ */
+ return throwBadUtf8(v1, at + 1);
+ }
+ out = (char) value;
+ at += 2;
+ break;
+ }
+ case 0x0e: {
+ // 1110XXXX -- three-byte encoding
+ length -= 3;
+ if (length < 0) {
+ return throwBadUtf8(v0, at);
+ }
+ int v1 = bytes.getUnsignedByte(at + 1);
+ if ((v1 & 0xc0) != 0x80) {
+ return throwBadUtf8(v1, at + 1);
+ }
+ int v2 = bytes.getUnsignedByte(at + 2);
+ if ((v1 & 0xc0) != 0x80) {
+ return throwBadUtf8(v2, at + 2);
+ }
+ int value = ((v0 & 0x0f) << 12) | ((v1 & 0x3f) << 6) |
+ (v2 & 0x3f);
+ if (value < 0x800) {
+ /*
+ * This should have been represented with one- or
+ * two-byte encoding.
+ */
+ return throwBadUtf8(v2, at + 2);
+ }
+ out = (char) value;
+ at += 3;
+ break;
+ }
+ default: {
+ // 10XXXXXX, 1111XXXX -- illegal
+ return throwBadUtf8(v0, at);
+ }
+ }
+ chars[outAt] = out;
+ outAt++;
+ }
+
+ return new String(chars, 0, outAt);
+ }
+
+ /**
+ * Helper for {@link #utf8BytesToString}, which throws the right
+ * exception for a bogus utf-8 byte.
+ *
+ * @param value the byte value
+ * @param offset the file offset
+ * @return never
+ * @throws IllegalArgumentException always thrown
+ */
+ private static String throwBadUtf8(int value, int offset) {
+ throw new IllegalArgumentException("bad utf-8 byte " + Hex.u1(value) +
+ " at offset " + Hex.u4(offset));
+ }
+
+ /**
+ * Constructs an instance from a {@code String}.
+ *
+ * @param string {@code non-null;} the UTF-8 value as a string
+ */
+ public CstString(String string) {
if (string == null) {
throw new NullPointerException("string == null");
}
- this.string = string;
+ this.string = string.intern();
+ this.bytes = new ByteArray(stringToUtf8Bytes(string));
}
/**
- * Constructs an instance.
+ * Constructs an instance from some UTF-8 bytes.
*
- * @param string {@code non-null;} the string value
+ * @param bytes {@code non-null;} array of the UTF-8 bytes
*/
- public CstString(String string) {
- this(new CstUtf8(string));
+ public CstString(ByteArray bytes) {
+ if (bytes == null) {
+ throw new NullPointerException("bytes == null");
+ }
+
+ this.bytes = bytes;
+ this.string = utf8BytesToString(bytes).intern();
}
/** {@inheritDoc} */
@@ -73,18 +225,13 @@
/** {@inheritDoc} */
@Override
public String toString() {
- return "string{" + toHuman() + '}';
- }
-
- /** {@inheritDoc} */
- public Type getType() {
- return Type.STRING;
+ return "string{\"" + toHuman() + "\"}";
}
/** {@inheritDoc} */
@Override
public String typeName() {
- return "string";
+ return "utf8";
}
/** {@inheritDoc} */
@@ -95,15 +242,134 @@
/** {@inheritDoc} */
public String toHuman() {
- return string.toQuoted();
+ int len = string.length();
+ StringBuilder sb = new StringBuilder(len * 3 / 2);
+
+ for (int i = 0; i < len; i++) {
+ char c = string.charAt(i);
+ if ((c >= ' ') && (c < 0x7f)) {
+ if ((c == '\'') || (c == '\"') || (c == '\\')) {
+ sb.append('\\');
+ }
+ sb.append(c);
+ } else if (c <= 0x7f) {
+ switch (c) {
+ case '\n': sb.append("\\n"); break;
+ case '\r': sb.append("\\r"); break;
+ case '\t': sb.append("\\t"); break;
+ default: {
+ /*
+ * Represent the character as an octal escape.
+ * If the next character is a valid octal
+ * digit, disambiguate by using the
+ * three-digit form.
+ */
+ char nextChar =
+ (i < (len - 1)) ? string.charAt(i + 1) : 0;
+ boolean displayZero =
+ (nextChar >= '0') && (nextChar <= '7');
+ sb.append('\\');
+ for (int shift = 6; shift >= 0; shift -= 3) {
+ char outChar = (char) (((c >> shift) & 7) + '0');
+ if ((outChar != '0') || displayZero) {
+ sb.append(outChar);
+ displayZero = true;
+ }
+ }
+ if (! displayZero) {
+ // Ironic edge case: The original value was 0.
+ sb.append('0');
+ }
+ break;
+ }
+ }
+ } else {
+ sb.append("\\u");
+ sb.append(Character.forDigit(c >> 12, 16));
+ sb.append(Character.forDigit((c >> 8) & 0x0f, 16));
+ sb.append(Character.forDigit((c >> 4) & 0x0f, 16));
+ sb.append(Character.forDigit(c & 0x0f, 16));
+ }
+ }
+
+ return sb.toString();
}
/**
- * Gets the string value.
+ * Gets the value as a human-oriented string, surrounded by double
+ * quotes.
*
- * @return {@code non-null;} the string value
+ * @return {@code non-null;} the quoted string
*/
- public CstUtf8 getString() {
+ public String toQuoted() {
+ return '\"' + toHuman() + '\"';
+ }
+
+ /**
+ * Gets the value as a human-oriented string, surrounded by double
+ * quotes, but ellipsizes the result if it is longer than the given
+ * maximum length
+ *
+ * @param maxLength {@code >= 5;} the maximum length of the string to return
+ * @return {@code non-null;} the quoted string
+ */
+ public String toQuoted(int maxLength) {
+ String string = toHuman();
+ int length = string.length();
+ String ellipses;
+
+ if (length <= (maxLength - 2)) {
+ ellipses = "";
+ } else {
+ string = string.substring(0, maxLength - 5);
+ ellipses = "...";
+ }
+
+ return '\"' + string + ellipses + '\"';
+ }
+
+ /**
+ * Gets the UTF-8 value as a string.
+ * The returned string is always already interned.
+ *
+ * @return {@code non-null;} the UTF-8 value as a string
+ */
+ public String getString() {
return string;
}
+
+ /**
+ * Gets the UTF-8 value as UTF-8 encoded bytes.
+ *
+ * @return {@code non-null;} an array of the UTF-8 bytes
+ */
+ public ByteArray getBytes() {
+ return bytes;
+ }
+
+ /**
+ * Gets the size of this instance as UTF-8 code points. That is,
+ * get the number of bytes in the UTF-8 encoding of this instance.
+ *
+ * @return {@code >= 0;} the UTF-8 size
+ */
+ public int getUtf8Size() {
+ return bytes.size();
+ }
+
+ /**
+ * Gets the size of this instance as UTF-16 code points. That is,
+ * get the number of 16-bit chars in the UTF-16 encoding of this
+ * instance. This is the same as the {@code length} of the
+ * Java {@code String} representation of this instance.
+ *
+ * @return {@code >= 0;} the UTF-16 size
+ */
+ public int getUtf16Size() {
+ return string.length();
+ }
+
+ public Type getType() {
+ return Type.STRING;
+ }
}
diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java
index 077ad06..8624028 100644
--- a/dx/src/com/android/dx/rop/cst/CstType.java
+++ b/dx/src/com/android/dx/rop/cst/CstType.java
@@ -89,7 +89,7 @@
* {@code null-ok;} the type descriptor corresponding to this instance, if
* calculated
*/
- private CstUtf8 descriptor;
+ private CstString descriptor;
/**
* Returns an instance of this class that represents the wrapper
@@ -222,9 +222,9 @@
*
* @return {@code non-null;} the descriptor
*/
- public CstUtf8 getDescriptor() {
+ public CstString getDescriptor() {
if (descriptor == null) {
- descriptor = new CstUtf8(type.getDescriptor());
+ descriptor = new CstString(type.getDescriptor());
}
return descriptor;
diff --git a/dx/src/com/android/dx/rop/cst/CstUtf8.java b/dx/src/com/android/dx/rop/cst/CstUtf8.java
deleted file mode 100644
index 5cfc1f3..0000000
--- a/dx/src/com/android/dx/rop/cst/CstUtf8.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-package com.android.dx.rop.cst;
-
-import com.android.dx.util.ByteArray;
-import com.android.dx.util.Hex;
-
-/**
- * Constants of type {@code CONSTANT_Utf8_info}.
- */
-public final class CstUtf8 extends Constant {
- /**
- * {@code non-null;} instance representing {@code ""}, that is, the
- * empty string
- */
- public static final CstUtf8 EMPTY_STRING = new CstUtf8("");
-
- /** {@code non-null;} the UTF-8 value as a string */
- private final String string;
-
- /** {@code non-null;} the UTF-8 value as bytes */
- private final ByteArray bytes;
-
- /**
- * Converts a string into its Java-style UTF-8 form. Java-style UTF-8
- * differs from normal UTF-8 in the handling of character '\0' and
- * surrogate pairs.
- *
- * @param string {@code non-null;} the string to convert
- * @return {@code non-null;} the UTF-8 bytes for it
- */
- public static byte[] stringToUtf8Bytes(String string) {
- int len = string.length();
- byte[] bytes = new byte[len * 3]; // Avoid having to reallocate.
- int outAt = 0;
-
- for (int i = 0; i < len; i++) {
- char c = string.charAt(i);
- if ((c != 0) && (c < 0x80)) {
- bytes[outAt] = (byte) c;
- outAt++;
- } else if (c < 0x800) {
- bytes[outAt] = (byte) (((c >> 6) & 0x1f) | 0xc0);
- bytes[outAt + 1] = (byte) ((c & 0x3f) | 0x80);
- outAt += 2;
- } else {
- bytes[outAt] = (byte) (((c >> 12) & 0x0f) | 0xe0);
- bytes[outAt + 1] = (byte) (((c >> 6) & 0x3f) | 0x80);
- bytes[outAt + 2] = (byte) ((c & 0x3f) | 0x80);
- outAt += 3;
- }
- }
-
- byte[] result = new byte[outAt];
- System.arraycopy(bytes, 0, result, 0, outAt);
- return result;
- }
-
- /**
- * Converts an array of UTF-8 bytes into a string.
- *
- * @param bytes {@code non-null;} the bytes to convert
- * @return {@code non-null;} the converted string
- */
- public static String utf8BytesToString(ByteArray bytes) {
- int length = bytes.size();
- char[] chars = new char[length]; // This is sized to avoid a realloc.
- int outAt = 0;
-
- for (int at = 0; length > 0; /*at*/) {
- int v0 = bytes.getUnsignedByte(at);
- char out;
- switch (v0 >> 4) {
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07: {
- // 0XXXXXXX -- single-byte encoding
- length--;
- if (v0 == 0) {
- // A single zero byte is illegal.
- return throwBadUtf8(v0, at);
- }
- out = (char) v0;
- at++;
- break;
- }
- case 0x0c: case 0x0d: {
- // 110XXXXX -- two-byte encoding
- length -= 2;
- if (length < 0) {
- return throwBadUtf8(v0, at);
- }
- int v1 = bytes.getUnsignedByte(at + 1);
- if ((v1 & 0xc0) != 0x80) {
- return throwBadUtf8(v1, at + 1);
- }
- int value = ((v0 & 0x1f) << 6) | (v1 & 0x3f);
- if ((value != 0) && (value < 0x80)) {
- /*
- * This should have been represented with
- * one-byte encoding.
- */
- return throwBadUtf8(v1, at + 1);
- }
- out = (char) value;
- at += 2;
- break;
- }
- case 0x0e: {
- // 1110XXXX -- three-byte encoding
- length -= 3;
- if (length < 0) {
- return throwBadUtf8(v0, at);
- }
- int v1 = bytes.getUnsignedByte(at + 1);
- if ((v1 & 0xc0) != 0x80) {
- return throwBadUtf8(v1, at + 1);
- }
- int v2 = bytes.getUnsignedByte(at + 2);
- if ((v1 & 0xc0) != 0x80) {
- return throwBadUtf8(v2, at + 2);
- }
- int value = ((v0 & 0x0f) << 12) | ((v1 & 0x3f) << 6) |
- (v2 & 0x3f);
- if (value < 0x800) {
- /*
- * This should have been represented with one- or
- * two-byte encoding.
- */
- return throwBadUtf8(v2, at + 2);
- }
- out = (char) value;
- at += 3;
- break;
- }
- default: {
- // 10XXXXXX, 1111XXXX -- illegal
- return throwBadUtf8(v0, at);
- }
- }
- chars[outAt] = out;
- outAt++;
- }
-
- return new String(chars, 0, outAt);
- }
-
- /**
- * Helper for {@link #utf8BytesToString}, which throws the right
- * exception for a bogus utf-8 byte.
- *
- * @param value the byte value
- * @param offset the file offset
- * @return never
- * @throws IllegalArgumentException always thrown
- */
- private static String throwBadUtf8(int value, int offset) {
- throw new IllegalArgumentException("bad utf-8 byte " + Hex.u1(value) +
- " at offset " + Hex.u4(offset));
- }
-
- /**
- * Constructs an instance from a {@code String}.
- *
- * @param string {@code non-null;} the UTF-8 value as a string
- */
- public CstUtf8(String string) {
- if (string == null) {
- throw new NullPointerException("string == null");
- }
-
- this.string = string.intern();
- this.bytes = new ByteArray(stringToUtf8Bytes(string));
- }
-
- /**
- * Constructs an instance from some UTF-8 bytes.
- *
- * @param bytes {@code non-null;} array of the UTF-8 bytes
- */
- public CstUtf8(ByteArray bytes) {
- if (bytes == null) {
- throw new NullPointerException("bytes == null");
- }
-
- this.bytes = bytes;
- this.string = utf8BytesToString(bytes).intern();
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof CstUtf8)) {
- return false;
- }
-
- return string.equals(((CstUtf8) other).string);
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return string.hashCode();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(Constant other) {
- return string.compareTo(((CstUtf8) other).string);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return "utf8{\"" + toHuman() + "\"}";
- }
-
- /** {@inheritDoc} */
- @Override
- public String typeName() {
- return "utf8";
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isCategory2() {
- return false;
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- int len = string.length();
- StringBuilder sb = new StringBuilder(len * 3 / 2);
-
- for (int i = 0; i < len; i++) {
- char c = string.charAt(i);
- if ((c >= ' ') && (c < 0x7f)) {
- if ((c == '\'') || (c == '\"') || (c == '\\')) {
- sb.append('\\');
- }
- sb.append(c);
- } else if (c <= 0x7f) {
- switch (c) {
- case '\n': sb.append("\\n"); break;
- case '\r': sb.append("\\r"); break;
- case '\t': sb.append("\\t"); break;
- default: {
- /*
- * Represent the character as an octal escape.
- * If the next character is a valid octal
- * digit, disambiguate by using the
- * three-digit form.
- */
- char nextChar =
- (i < (len - 1)) ? string.charAt(i + 1) : 0;
- boolean displayZero =
- (nextChar >= '0') && (nextChar <= '7');
- sb.append('\\');
- for (int shift = 6; shift >= 0; shift -= 3) {
- char outChar = (char) (((c >> shift) & 7) + '0');
- if ((outChar != '0') || displayZero) {
- sb.append(outChar);
- displayZero = true;
- }
- }
- if (! displayZero) {
- // Ironic edge case: The original value was 0.
- sb.append('0');
- }
- break;
- }
- }
- } else {
- sb.append("\\u");
- sb.append(Character.forDigit(c >> 12, 16));
- sb.append(Character.forDigit((c >> 8) & 0x0f, 16));
- sb.append(Character.forDigit((c >> 4) & 0x0f, 16));
- sb.append(Character.forDigit(c & 0x0f, 16));
- }
- }
-
- return sb.toString();
- }
-
- /**
- * Gets the value as a human-oriented string, surrounded by double
- * quotes.
- *
- * @return {@code non-null;} the quoted string
- */
- public String toQuoted() {
- return '\"' + toHuman() + '\"';
- }
-
- /**
- * Gets the value as a human-oriented string, surrounded by double
- * quotes, but ellipsizes the result if it is longer than the given
- * maximum length
- *
- * @param maxLength {@code >= 5;} the maximum length of the string to return
- * @return {@code non-null;} the quoted string
- */
- public String toQuoted(int maxLength) {
- String string = toHuman();
- int length = string.length();
- String ellipses;
-
- if (length <= (maxLength - 2)) {
- ellipses = "";
- } else {
- string = string.substring(0, maxLength - 5);
- ellipses = "...";
- }
-
- return '\"' + string + ellipses + '\"';
- }
-
- /**
- * Gets the UTF-8 value as a string.
- * The returned string is always already interned.
- *
- * @return {@code non-null;} the UTF-8 value as a string
- */
- public String getString() {
- return string;
- }
-
- /**
- * Gets the UTF-8 value as UTF-8 encoded bytes.
- *
- * @return {@code non-null;} an array of the UTF-8 bytes
- */
- public ByteArray getBytes() {
- return bytes;
- }
-
- /**
- * Gets the size of this instance as UTF-8 code points. That is,
- * get the number of bytes in the UTF-8 encoding of this instance.
- *
- * @return {@code >= 0;} the UTF-8 size
- */
- public int getUtf8Size() {
- return bytes.size();
- }
-
- /**
- * Gets the size of this instance as UTF-16 code points. That is,
- * get the number of 16-bit chars in the UTF-16 encoding of this
- * instance. This is the same as the {@code length} of the
- * Java {@code String} representation of this instance.
- *
- * @return {@code >= 0;} the UTF-16 size
- */
- public int getUtf16Size() {
- return string.length();
- }
-}
diff --git a/dx/src/com/android/dx/rop/cst/TypedConstant.java b/dx/src/com/android/dx/rop/cst/TypedConstant.java
index c250c46..1c738ee 100644
--- a/dx/src/com/android/dx/rop/cst/TypedConstant.java
+++ b/dx/src/com/android/dx/rop/cst/TypedConstant.java
@@ -26,7 +26,7 @@
/**
* {@inheritDoc}
*
- * This implentation always returns {@code this}.
+ * This implementation always returns {@code this}.
*/
public final TypeBearer getFrameType() {
return this;
diff --git a/dx/src/com/android/dx/rop/type/Prototype.java b/dx/src/com/android/dx/rop/type/Prototype.java
index ec46ff9..3fc5d82 100644
--- a/dx/src/com/android/dx/rop/type/Prototype.java
+++ b/dx/src/com/android/dx/rop/type/Prototype.java
@@ -19,7 +19,7 @@
import java.util.HashMap;
/**
- * Representation of a method decriptor. Instances of this class are
+ * Representation of a method descriptor. Instances of this class are
* generally interned and may be usefully compared with each other
* using {@code ==}.
*/
diff --git a/dx/src/com/android/dx/rop/type/Type.java b/dx/src/com/android/dx/rop/type/Type.java
index eefd55b..c564fab 100644
--- a/dx/src/com/android/dx/rop/type/Type.java
+++ b/dx/src/com/android/dx/rop/type/Type.java
@@ -328,7 +328,7 @@
int length = descriptor.length();
if ((firstChar != 'L') ||
(descriptor.charAt(length - 1) != ';')) {
- throw new IllegalArgumentException("bad descriptor");
+ throw new IllegalArgumentException("bad descriptor: " + descriptor);
}
/*
@@ -349,13 +349,13 @@
case '.':
case '(':
case ')': {
- throw new IllegalArgumentException("bad descriptor");
+ throw new IllegalArgumentException("bad descriptor: " + descriptor);
}
case '/': {
if ((i == 1) ||
(i == (length - 1)) ||
(descriptor.charAt(i - 1) == '/')) {
- throw new IllegalArgumentException("bad descriptor");
+ throw new IllegalArgumentException("bad descriptor: " + descriptor);
}
break;
}
diff --git a/dx/src/com/android/dx/ssa/ConstCollector.java b/dx/src/com/android/dx/ssa/ConstCollector.java
index cf6c019..62d629f 100644
--- a/dx/src/com/android/dx/ssa/ConstCollector.java
+++ b/dx/src/com/android/dx/ssa/ConstCollector.java
@@ -31,7 +31,6 @@
import com.android.dx.rop.cst.TypedConstant;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.TypeBearer;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
diff --git a/dx/src/com/android/dx/ssa/EscapeAnalysis.java b/dx/src/com/android/dx/ssa/EscapeAnalysis.java
index d270857..b02c929 100644
--- a/dx/src/com/android/dx/ssa/EscapeAnalysis.java
+++ b/dx/src/com/android/dx/ssa/EscapeAnalysis.java
@@ -32,8 +32,8 @@
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstNat;
+import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.cst.TypedConstant;
import com.android.dx.rop.cst.Zeroes;
import com.android.dx.rop.type.StdTypeList;
@@ -754,7 +754,7 @@
SsaBasicBlock newBlock2 =
newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
SsaInsn newInsn2 = newBlock2.getInsns().get(0);
- CstNat newNat = new CstNat(new CstUtf8("<init>"), new CstUtf8("(I)V"));
+ CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
CstMethodRef newRef = new CstMethodRef(exception, newNat);
insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index),
null, RegOps.INVOKE_DIRECT, newRef);
diff --git a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
index 12bfa0d..f3976f2 100644
--- a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
+++ b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
@@ -34,7 +34,7 @@
import java.util.List;
/**
- * Upgrades insn to their literal (constant-immediate) equivilent if possible.
+ * Upgrades insn to their literal (constant-immediate) equivalent if possible.
* Also switches IF instructions that compare with a constant zero or null
* to be their IF_*Z equivalents.
*/
diff --git a/dx/tests/010-class-attrib-InnerClasses/expected.txt b/dx/tests/010-class-attrib-InnerClasses/expected.txt
index 590ed2e..f588190 100644
--- a/dx/tests/010-class-attrib-InnerClasses/expected.txt
+++ b/dx/tests/010-class-attrib-InnerClasses/expected.txt
@@ -32,7 +32,7 @@
access_flags: public
inner_class: type{Small}
outer_class: (none)
- name: utf8{"Small"}
+ name: string{"Small"}
access_flags: private
inner_class: type{Small}
outer_class: type{Zorch}
@@ -40,7 +40,7 @@
access_flags: protected
inner_class: type{Zorch}
outer_class: type{Small}
- name: utf8{"Zorch"}
+ name: string{"Zorch"}
access_flags: public|private|protected|static|final|interface|abstract|synthetic|annotation|enum|89e0
end attributes[0]
end classfile
diff --git a/dx/tests/012-class-attrib-SourceFile/expected.txt b/dx/tests/012-class-attrib-SourceFile/expected.txt
index c795cde..e607900 100644
--- a/dx/tests/012-class-attrib-SourceFile/expected.txt
+++ b/dx/tests/012-class-attrib-SourceFile/expected.txt
@@ -24,6 +24,6 @@
attributes[0]:
name: SourceFile
length: 00000002
- source: utf8{"Blort.java"}
+ source: string{"Blort.java"}
end attributes[0]
end classfile
diff --git a/dx/tests/025-class-attrib-Signature/expected.txt b/dx/tests/025-class-attrib-Signature/expected.txt
index 5ff56ed..e3f7233 100644
--- a/dx/tests/025-class-attrib-Signature/expected.txt
+++ b/dx/tests/025-class-attrib-Signature/expected.txt
@@ -24,6 +24,6 @@
attributes[0]:
name: Signature
length: 00000002
- signature: utf8{"LYo;"}
+ signature: string{"LYo;"}
end attributes[0]
end classfile
diff --git a/dx/tests/026-field-attrib-Signature/expected.txt b/dx/tests/026-field-attrib-Signature/expected.txt
index c2e840e..228989a 100644
--- a/dx/tests/026-field-attrib-Signature/expected.txt
+++ b/dx/tests/026-field-attrib-Signature/expected.txt
@@ -30,7 +30,7 @@
attributes[0]:
name: Signature
length: 00000002
- signature: utf8{"LYo;"}
+ signature: string{"LYo;"}
end attributes[0]
end fields[0]
methods_count: 0000
diff --git a/dx/tests/027-method-attrib-Signature/expected.txt b/dx/tests/027-method-attrib-Signature/expected.txt
index abc97c0..c3610e9 100644
--- a/dx/tests/027-method-attrib-Signature/expected.txt
+++ b/dx/tests/027-method-attrib-Signature/expected.txt
@@ -31,7 +31,7 @@
attributes[0]:
name: Signature
length: 00000002
- signature: utf8{"LYo;"}
+ signature: string{"LYo;"}
end attributes[0]
end methods[0]
attributes_count: 0000
diff --git a/dx/tests/108-string-annotation/expected.txt b/dx/tests/108-string-annotation/expected.txt
index 57da807..a4c4af4 100644
--- a/dx/tests/108-string-annotation/expected.txt
+++ b/dx/tests/108-string-annotation/expected.txt
@@ -1,12 +1,12 @@
elements[0]:
name
- value: string "grue"
+ value: utf8 grue
elements[0]:
names
- value: array {"gruesome"}
+ value: array {gruesome}
elements[0]:
names
- value: array {"awful", "awesome"}
+ value: array {awful, awesome}
diff --git a/dx/tests/115-merge/com/android/dx/merge/DexMergeTest.java b/dx/tests/115-merge/com/android/dx/merge/DexMergeTest.java
index b256dd2..c6ffbdc 100644
--- a/dx/tests/115-merge/com/android/dx/merge/DexMergeTest.java
+++ b/dx/tests/115-merge/com/android/dx/merge/DexMergeTest.java
@@ -17,7 +17,6 @@
package com.android.dx.merge;
import com.android.dx.io.DexBuffer;
-import dalvik.system.PathClassLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -156,14 +155,17 @@
assertTrue(maxLength + " < " + maxExpectedLength, maxLength < maxExpectedLength);
}
- public ClassLoader mergeAndLoad(String dexAResource, String dexBResource) throws IOException {
+ public ClassLoader mergeAndLoad(String dexAResource, String dexBResource) throws Exception {
DexBuffer dexA = resourceToDexBuffer(dexAResource);
DexBuffer dexB = resourceToDexBuffer(dexBResource);
DexBuffer merged = new DexMerger(dexA, dexB, CollisionPolicy.KEEP_FIRST).merge();
File mergedDex = File.createTempFile("DexMergeTest", ".classes.dex");
merged.writeTo(mergedDex);
File mergedJar = dexToJar(mergedDex);
- return new PathClassLoader(mergedJar.getPath(), getClass().getClassLoader());
+ // simplify the javac classpath by not depending directly on 'dalvik.system' classes
+ return (ClassLoader) Class.forName("dalvik.system.PathClassLoader")
+ .getConstructor(String.class, ClassLoader.class)
+ .newInstance(mergedJar.getPath(), getClass().getClassLoader());
}
private DexBuffer resourceToDexBuffer(String resource) throws IOException {
diff --git a/dx/tests/115-merge/run b/dx/tests/115-merge/run
index d3d34e8..83e5b3d 100644
--- a/dx/tests/115-merge/run
+++ b/dx/tests/115-merge/run
@@ -17,8 +17,12 @@
# Find dx.jar from dx in the android dev tree
prog=`which dx`
progdir=`dirname "${prog}"`
+dxjar=$progdir/../framework/dx.jar
-javac testdata/*.java
+javac -cp $dxjar `find . -name "*.java"`
+dx --dex --output=test.jar com/android/dx/merge/* $dxjar
+
+# Build a resource .jar containing the .dex files to merge
dx --dex --output=testdata/Annotated.dex testdata/Annotated*
dx --dex --output=testdata/Basic.dex testdata/Basic*
dx --dex --output=testdata/FillArrayData.dex testdata/FillArrayData*
@@ -26,9 +30,8 @@
dx --dex --output=testdata/TryCatchFinally.dex testdata/TryCatchFinally*
jar cfM resources.jar testdata/*.dex
-vogar --classpath resources.jar \
- --classpath $progdir/../framework/dx.jar \
- com/android/dx/merge/DexMergeTest.java > unit-out.txt
+dalvik -classpath test.jar:resources.jar \
+ junit.textui.TestRunner com.android.dx.merge.DexMergeTest > unit-out.txt
if [ "$?" = "0" ]; then
echo "Yay!"
diff --git a/dx/tests/116-leb128/run b/dx/tests/116-leb128/run
index 1e729ed..5f36cd9 100644
--- a/dx/tests/116-leb128/run
+++ b/dx/tests/116-leb128/run
@@ -17,9 +17,10 @@
# Find dx.jar from dx in the android dev tree
prog=`which dx`
progdir=`dirname "${prog}"`
+dxjar=$progdir/../framework/dx.jar
-vogar --classpath $progdir/../framework/dx.jar \
- com/android/dx/util/Leb128UtilsTest.java > unit-out.txt
+javac -cp $dxjar `find . -name "*.java"`
+java -classpath $dxjar:. junit.textui.TestRunner com.android.dx.util.Leb128UtilsTest > unit-out.txt
if [ "$?" = "0" ]; then
echo "Yay!"
diff --git a/dx/tests/117-modified-utf8/run b/dx/tests/117-modified-utf8/run
index a689991..a4c202e 100644
--- a/dx/tests/117-modified-utf8/run
+++ b/dx/tests/117-modified-utf8/run
@@ -17,9 +17,10 @@
# Find dx.jar from dx in the android dev tree
prog=`which dx`
progdir=`dirname "${prog}"`
+dxjar=$progdir/../framework/dx.jar
-vogar --classpath $progdir/../framework/dx.jar \
- com/android/dx/util/Mutf8Test.java > unit-out.txt
+javac -cp $dxjar `find . -name "*.java"`
+java -classpath $dxjar:. junit.textui.TestRunner com.android.dx.util.Mutf8Test > unit-out.txt
if [ "$?" = "0" ]; then
echo "Yay!"
diff --git a/dx/tests/119-merge-conflict/run b/dx/tests/119-merge-conflict/run
index af5087d..28c152d 100644
--- a/dx/tests/119-merge-conflict/run
+++ b/dx/tests/119-merge-conflict/run
@@ -17,19 +17,18 @@
# Find dx.jar from dx in the android dev tree
prog=`which dx`
progdir=`dirname "${prog}"`
+dxjar=$progdir/../framework/dx.jar
-# Find dx.jar from dx in the android dev tree
-prog=`which dx`
-progdir=`dirname "${prog}"`
+javac -cp $dxjar `find . -name "*.java"`
+dx --dex --output=test.jar com/android/dx/merge/* $dxjar
-javac testdata/*.java
+# Build a resource .jar containing the .dex files to merge
dx --dex --output=testdata/A.dex testdata/A.class
dx --dex --output=testdata/B.dex testdata/B.class
jar cfM resources.jar testdata/*.dex
-vogar --classpath resources.jar \
- --classpath $progdir/../framework/dx.jar \
- com/android/dx/merge/MergeConflictTest.java > unit-out.txt
+dalvik -classpath test.jar:resources.jar \
+ junit.textui.TestRunner com.android.dx.merge.MergeConflictTest > unit-out.txt
if [ "$?" = "0" ]; then
echo "Yay!"
diff --git a/libdex/Android.mk b/libdex/Android.mk
index 26f84d6..bb8d03b 100644
--- a/libdex/Android.mk
+++ b/libdex/Android.mk
@@ -15,24 +15,24 @@
LOCAL_PATH:= $(call my-dir)
dex_src_files := \
- CmdUtils.c \
- DexCatch.c \
- DexClass.c \
- DexDataMap.c \
- DexDebugInfo.c \
- DexFile.c \
- DexInlines.c \
- DexOptData.c \
- DexOpcodes.c \
- DexProto.c \
- DexSwapVerify.c \
- DexUtf.c \
- InstrUtils.c \
- Leb128.c \
- OptInvocation.c \
- sha1.c \
- SysUtil.c \
- ZipArchive.c
+ CmdUtils.cpp \
+ DexCatch.cpp \
+ DexClass.cpp \
+ DexDataMap.cpp \
+ DexDebugInfo.cpp \
+ DexFile.cpp \
+ DexInlines.cpp \
+ DexOptData.cpp \
+ DexOpcodes.cpp \
+ DexProto.cpp \
+ DexSwapVerify.cpp \
+ DexUtf.cpp \
+ InstrUtils.cpp \
+ Leb128.cpp \
+ OptInvocation.cpp \
+ sha1.cpp \
+ SysUtil.cpp \
+ ZipArchive.cpp
dex_include_files := \
dalvik \
diff --git a/libdex/CmdUtils.c b/libdex/CmdUtils.cpp
similarity index 98%
rename from libdex/CmdUtils.c
rename to libdex/CmdUtils.cpp
index ecb53e8..ff737a3 100644
--- a/libdex/CmdUtils.c
+++ b/libdex/CmdUtils.cpp
@@ -197,7 +197,7 @@
*/
sysChangeMapAccess(pMap->addr, pMap->length, true, pMap);
- if (dexSwapAndVerifyIfNecessary(pMap->addr, pMap->length)) {
+ if (dexSwapAndVerifyIfNecessary((u1*) pMap->addr, pMap->length)) {
fprintf(stderr, "ERROR: Failed structural verification of '%s'\n",
fileName);
goto bail;
@@ -213,7 +213,7 @@
/*
* Success! Close the file and return with the start/length in pMap.
*/
- result = 0;
+ result = kUTFRSuccess;
bail:
if (fd >= 0)
diff --git a/libdex/CmdUtils.h b/libdex/CmdUtils.h
index 7a85287..62ce73a 100644
--- a/libdex/CmdUtils.h
+++ b/libdex/CmdUtils.h
@@ -32,7 +32,7 @@
#define _LIBDEX_CMDUTILS
/* encode the result of unzipping to a file */
-typedef enum UnzipToFileResult {
+enum UnzipToFileResult {
kUTFRSuccess = 0,
kUTFRGenericFailure,
kUTFRBadArgs,
@@ -40,7 +40,7 @@
kUTFRNoClassesDex,
kUTFROutputFileProblem,
kUTFRBadZip,
-} UnzipToFileResult;
+};
/*
* Map the specified DEX file read-only (possibly after expanding it into a
diff --git a/libdex/DexCatch.c b/libdex/DexCatch.cpp
similarity index 100%
rename from libdex/DexCatch.c
rename to libdex/DexCatch.cpp
diff --git a/libdex/DexCatch.h b/libdex/DexCatch.h
index c0eec7c..19ea541 100644
--- a/libdex/DexCatch.h
+++ b/libdex/DexCatch.h
@@ -27,10 +27,10 @@
/*
* Catch handler entry, used while iterating over catch_handler_items.
*/
-typedef struct DexCatchHandler {
+struct DexCatchHandler {
u4 typeIdx; /* type index of the caught exception type */
u4 address; /* handler address */
-} DexCatchHandler;
+};
/* Get the first handler offset for the given DexCode.
* It's not 0 because the handlers list is prefixed with its size
@@ -44,12 +44,12 @@
* Iterator over catch handler data. This structure should be treated as
* opaque.
*/
-typedef struct DexCatchIterator {
+struct DexCatchIterator {
const u1* pEncodedData;
bool catchesAll;
u4 countRemaining;
DexCatchHandler handler;
-} DexCatchIterator;
+};
/* Initialize a DexCatchIterator to emptiness. This mostly exists to
* squelch innocuous warnings. */
diff --git a/libdex/DexClass.c b/libdex/DexClass.cpp
similarity index 97%
rename from libdex/DexClass.c
rename to libdex/DexClass.cpp
index 8a59e09..552229c 100644
--- a/libdex/DexClass.c
+++ b/libdex/DexClass.cpp
@@ -106,7 +106,7 @@
u4 lastIndex;
if (*pData == NULL) {
- DexClassData* result = malloc(sizeof(DexClassData));
+ DexClassData* result = (DexClassData*) malloc(sizeof(DexClassData));
memset(result, 0, sizeof(*result));
return result;
}
@@ -121,7 +121,7 @@
(header.directMethodsSize * sizeof(DexMethod)) +
(header.virtualMethodsSize * sizeof(DexMethod));
- DexClassData* result = malloc(resultSize);
+ DexClassData* result = (DexClassData*) malloc(resultSize);
u1* ptr = ((u1*) result) + sizeof(DexClassData);
bool okay = true;
u4 i;
diff --git a/libdex/DexClass.h b/libdex/DexClass.h
index 3d1e11b..d2d92c0 100644
--- a/libdex/DexClass.h
+++ b/libdex/DexClass.h
@@ -25,36 +25,36 @@
#include "Leb128.h"
/* expanded form of a class_data_item header */
-typedef struct DexClassDataHeader {
+struct DexClassDataHeader {
u4 staticFieldsSize;
u4 instanceFieldsSize;
u4 directMethodsSize;
u4 virtualMethodsSize;
-} DexClassDataHeader;
+};
/* expanded form of encoded_field */
-typedef struct DexField {
+struct DexField {
u4 fieldIdx; /* index to a field_id_item */
u4 accessFlags;
-} DexField;
+};
/* expanded form of encoded_method */
-typedef struct DexMethod {
+struct DexMethod {
u4 methodIdx; /* index to a method_id_item */
u4 accessFlags;
u4 codeOff; /* file offset to a code_item */
-} DexMethod;
+};
/* expanded form of class_data_item. Note: If a particular item is
* absent (e.g., no static fields), then the corresponding pointer
* is set to NULL. */
-typedef struct DexClassData {
+struct DexClassData {
DexClassDataHeader header;
DexField* staticFields;
DexField* instanceFields;
DexMethod* directMethods;
DexMethod* virtualMethods;
-} DexClassData;
+};
/* Read and verify the header of a class_data_item. This updates the
* given data pointer to point past the end of the read data and
diff --git a/libdex/DexDataMap.c b/libdex/DexDataMap.cpp
similarity index 98%
rename from libdex/DexDataMap.c
rename to libdex/DexDataMap.cpp
index a9d429e..33135ed 100644
--- a/libdex/DexDataMap.c
+++ b/libdex/DexDataMap.cpp
@@ -41,7 +41,7 @@
return NULL;
}
- map = malloc(size);
+ map = (DexDataMap*) malloc(size);
if (map == NULL) {
return NULL;
diff --git a/libdex/DexDataMap.h b/libdex/DexDataMap.h
index fa556d5..359d3ad 100644
--- a/libdex/DexDataMap.h
+++ b/libdex/DexDataMap.h
@@ -23,12 +23,12 @@
#include "DexFile.h"
-typedef struct DexDataMap {
+struct DexDataMap {
u4 count; /* number of items currently in the map */
u4 max; /* maximum number of items that may be held */
u4* offsets; /* array of item offsets */
u2* types; /* corresponding array of item types */
-} DexDataMap;
+};
/*
* Allocate and initialize a DexDataMap. Returns NULL on failure.
diff --git a/libdex/DexDebugInfo.c b/libdex/DexDebugInfo.cpp
similarity index 82%
rename from libdex/DexDebugInfo.c
rename to libdex/DexDebugInfo.cpp
index 43765f7..cbb58d4 100644
--- a/libdex/DexDebugInfo.c
+++ b/libdex/DexDebugInfo.cpp
@@ -109,13 +109,13 @@
}
}
-typedef struct LocalInfo {
+struct LocalInfo {
const char *name;
const char *descriptor;
const char *signature;
u2 startAddress;
bool live;
-} LocalInfo;
+};
static void emitLocalCbIfLive(void *cnxt, int reg, u4 endAddress,
LocalInfo *localInReg, DexDebugNewLocalCb localCb)
@@ -129,34 +129,32 @@
}
}
-// TODO optimize localCb == NULL case
-void dexDecodeDebugInfo(
+static void invalidStream(const char* classDescriptor, const DexProto* proto) {
+ IF_LOGE() {
+ char* methodDescriptor = dexProtoCopyMethodDescriptor(proto);
+ LOGE("Invalid debug info stream. class %s; proto %s",
+ classDescriptor, methodDescriptor);
+ free(methodDescriptor);
+ }
+}
+
+static void dexDecodeDebugInfo0(
const DexFile* pDexFile,
const DexCode* pCode,
const char* classDescriptor,
u4 protoIdx,
u4 accessFlags,
DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
- void* cnxt)
+ void* cnxt,
+ const u1* stream,
+ LocalInfo* localInReg)
{
- const u1 *stream = dexGetDebugInfoStream(pDexFile, pCode);
- u4 line;
- u4 parametersSize;
- u4 address = 0;
- LocalInfo localInReg[pCode->registersSize];
- u4 insnsSize = pCode->insnsSize;
DexProto proto = { pDexFile, protoIdx };
-
- memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize);
-
- if (stream == NULL) {
- goto end;
- }
-
- line = readUnsignedLeb128(&stream);
- parametersSize = readUnsignedLeb128(&stream);
-
+ u4 insnsSize = pCode->insnsSize;
+ u4 line = readUnsignedLeb128(&stream);
+ u4 parametersSize = readUnsignedLeb128(&stream);
u2 argReg = pCode->registersSize - pCode->insSize;
+ u4 address = 0;
if ((accessFlags & ACC_STATIC) == 0) {
/*
@@ -184,7 +182,8 @@
int reg;
if ((argReg >= pCode->registersSize) || (descriptor == NULL)) {
- goto invalid_stream;
+ invalidStream(classDescriptor, &proto);
+ return;
}
name = readStringIdx(pDexFile, &stream);
@@ -215,7 +214,7 @@
switch (opcode) {
case DBG_END_SEQUENCE:
- goto end;
+ return;
case DBG_ADVANCE_PC:
address += readUnsignedLeb128(&stream);
@@ -228,10 +227,13 @@
case DBG_START_LOCAL:
case DBG_START_LOCAL_EXTENDED:
reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) goto invalid_stream;
+ if (reg > pCode->registersSize) {
+ invalidStream(classDescriptor, &proto);
+ return;
+ }
// Emit what was previously there, if anything
- emitLocalCbIfLive (cnxt, reg, address,
+ emitLocalCbIfLive(cnxt, reg, address,
localInReg, localCb);
localInReg[reg].name = readStringIdx(pDexFile, &stream);
@@ -248,7 +250,10 @@
case DBG_END_LOCAL:
reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) goto invalid_stream;
+ if (reg > pCode->registersSize) {
+ invalidStream(classDescriptor, &proto);
+ return;
+ }
emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb);
localInReg[reg].live = false;
@@ -256,11 +261,15 @@
case DBG_RESTART_LOCAL:
reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) goto invalid_stream;
+ if (reg > pCode->registersSize) {
+ invalidStream(classDescriptor, &proto);
+ return;
+ }
if (localInReg[reg].name == NULL
|| localInReg[reg].descriptor == NULL) {
- goto invalid_stream;
+ invalidStream(classDescriptor, &proto);
+ return;
}
/*
@@ -290,28 +299,36 @@
if (done) {
// early exit
- goto end;
+ return;
}
}
break;
}
}
}
+}
-end:
- {
- int reg;
- for (reg = 0; reg < pCode->registersSize; reg++) {
- emitLocalCbIfLive (cnxt, reg, insnsSize, localInReg, localCb);
- }
+// TODO optimize localCb == NULL case
+void dexDecodeDebugInfo(
+ const DexFile* pDexFile,
+ const DexCode* pCode,
+ const char* classDescriptor,
+ u4 protoIdx,
+ u4 accessFlags,
+ DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
+ void* cnxt)
+{
+ const u1* stream = dexGetDebugInfoStream(pDexFile, pCode);
+ LocalInfo localInReg[pCode->registersSize];
+
+ memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize);
+
+ if (stream != NULL) {
+ dexDecodeDebugInfo0(pDexFile, pCode, classDescriptor, protoIdx, accessFlags,
+ posCb, localCb, cnxt, stream, localInReg);
}
- return;
-invalid_stream:
- IF_LOGE() {
- char* methodDescriptor = dexProtoCopyMethodDescriptor(&proto);
- LOGE("Invalid debug info stream. class %s; proto %s",
- classDescriptor, methodDescriptor);
- free(methodDescriptor);
+ for (int reg = 0; reg < pCode->registersSize; reg++) {
+ emitLocalCbIfLive(cnxt, reg, pCode->insnsSize, localInReg, localCb);
}
}
diff --git a/libdex/DexDebugInfo.h b/libdex/DexDebugInfo.h
index f23e365..9ab67f5 100644
--- a/libdex/DexDebugInfo.h
+++ b/libdex/DexDebugInfo.h
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#ifndef _LIBDEX_DEXDEBUGINFO
-#define _LIBDEX_DEXDEBUGINFO
-
/*
* Handling of method debug info in a .dex file.
*/
+#ifndef _LIBDEX_DEXDEBUGINFO
+#define _LIBDEX_DEXDEBUGINFO
+
#include "DexFile.h"
/*
diff --git a/libdex/DexFile.c b/libdex/DexFile.cpp
similarity index 100%
rename from libdex/DexFile.c
rename to libdex/DexFile.cpp
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 45f9a91..4a090e1 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -73,7 +73,7 @@
/*
* Enumeration of all the primitive types.
*/
-typedef enum PrimitiveType {
+enum PrimitiveType {
PRIM_NOT = 0, /* value is a reference type, not a primitive type */
PRIM_VOID = 1,
PRIM_BOOLEAN = 2,
@@ -84,7 +84,7 @@
PRIM_LONG = 7,
PRIM_FLOAT = 8,
PRIM_DOUBLE = 9,
-} PrimitiveType;
+};
/*
* access flags and masks; the "standard" ones are all <= 0x4000
@@ -206,7 +206,7 @@
/*
* Direct-mapped "header_item" struct.
*/
-typedef struct DexHeader {
+struct DexHeader {
u1 magic[8]; /* includes version number */
u4 checksum; /* adler32 checksum */
u1 signature[kSHA1DigestLen]; /* SHA-1 hash */
@@ -230,71 +230,71 @@
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
-} DexHeader;
+};
/*
* Direct-mapped "map_item".
*/
-typedef struct DexMapItem {
- u2 type; /* type code (see kDexType* above) */
- u2 unused;
- u4 size; /* count of items of the indicated type */
- u4 offset; /* file offset to the start of data */
-} DexMapItem;
+struct DexMapItem {
+ u2 type; /* type code (see kDexType* above) */
+ u2 unused;
+ u4 size; /* count of items of the indicated type */
+ u4 offset; /* file offset to the start of data */
+};
/*
* Direct-mapped "map_list".
*/
-typedef struct DexMapList {
+struct DexMapList {
u4 size; /* #of entries in list */
DexMapItem list[1]; /* entries */
-} DexMapList;
+};
/*
* Direct-mapped "string_id_item".
*/
-typedef struct DexStringId {
- u4 stringDataOff; /* file offset to string_data_item */
-} DexStringId;
+struct DexStringId {
+ u4 stringDataOff; /* file offset to string_data_item */
+};
/*
* Direct-mapped "type_id_item".
*/
-typedef struct DexTypeId {
+struct DexTypeId {
u4 descriptorIdx; /* index into stringIds list for type descriptor */
-} DexTypeId;
+};
/*
* Direct-mapped "field_id_item".
*/
-typedef struct DexFieldId {
+struct DexFieldId {
u2 classIdx; /* index into typeIds list for defining class */
u2 typeIdx; /* index into typeIds for field type */
u4 nameIdx; /* index into stringIds for field name */
-} DexFieldId;
+};
/*
* Direct-mapped "method_id_item".
*/
-typedef struct DexMethodId {
+struct DexMethodId {
u2 classIdx; /* index into typeIds list for defining class */
u2 protoIdx; /* index into protoIds for method prototype */
u4 nameIdx; /* index into stringIds for method name */
-} DexMethodId;
+};
/*
* Direct-mapped "proto_id_item".
*/
-typedef struct DexProtoId {
+struct DexProtoId {
u4 shortyIdx; /* index into stringIds for shorty descriptor */
u4 returnTypeIdx; /* index into typeIds list for return type */
u4 parametersOff; /* file offset to type_list for parameter types */
-} DexProtoId;
+};
/*
* Direct-mapped "class_def_item".
*/
-typedef struct DexClassDef {
+struct DexClassDef {
u4 classIdx; /* index into typeIds for this class */
u4 accessFlags;
u4 superclassIdx; /* index into typeIds for superclass */
@@ -303,22 +303,22 @@
u4 annotationsOff; /* file offset to annotations_directory_item */
u4 classDataOff; /* file offset to class_data_item */
u4 staticValuesOff; /* file offset to DexEncodedArray */
-} DexClassDef;
+};
/*
* Direct-mapped "type_item".
*/
-typedef struct DexTypeItem {
+struct DexTypeItem {
u2 typeIdx; /* index into typeIds */
-} DexTypeItem;
+};
/*
* Direct-mapped "type_list".
*/
-typedef struct DexTypeList {
+struct DexTypeList {
u4 size; /* #of entries in list */
DexTypeItem list[1]; /* entries */
-} DexTypeList;
+};
/*
* Direct-mapped "code_item".
@@ -327,7 +327,7 @@
* "debugInfo" is used when displaying an exception stack trace or
* debugging. An offset of zero indicates that there are no entries.
*/
-typedef struct DexCode {
+struct DexCode {
u2 registersSize;
u2 insSize;
u2 outsSize;
@@ -339,29 +339,29 @@
/* followed by try_item[triesSize] */
/* followed by uleb128 handlersSize */
/* followed by catch_handler_item[handlersSize] */
-} DexCode;
+};
/*
* Direct-mapped "try_item".
*/
-typedef struct DexTry {
+struct DexTry {
u4 startAddr; /* start address, in 16-bit code units */
u2 insnCount; /* instruction count, in 16-bit code units */
u2 handlerOff; /* offset in encoded handler data to handlers */
-} DexTry;
+};
/*
* Link table. Currently undefined.
*/
-typedef struct DexLink {
+struct DexLink {
u1 bleargh;
-} DexLink;
+};
/*
* Direct-mapped "annotations_directory_item".
*/
-typedef struct DexAnnotationsDirectoryItem {
+struct DexAnnotationsDirectoryItem {
u4 classAnnotationsOff; /* offset to DexAnnotationSetItem */
u4 fieldsSize; /* count of DexFieldAnnotationsItem */
u4 methodsSize; /* count of DexMethodAnnotationsItem */
@@ -369,73 +369,73 @@
/* followed by DexFieldAnnotationsItem[fieldsSize] */
/* followed by DexMethodAnnotationsItem[methodsSize] */
/* followed by DexParameterAnnotationsItem[parametersSize] */
-} DexAnnotationsDirectoryItem;
+};
/*
* Direct-mapped "field_annotations_item".
*/
-typedef struct DexFieldAnnotationsItem {
+struct DexFieldAnnotationsItem {
u4 fieldIdx;
u4 annotationsOff; /* offset to DexAnnotationSetItem */
-} DexFieldAnnotationsItem;
+};
/*
* Direct-mapped "method_annotations_item".
*/
-typedef struct DexMethodAnnotationsItem {
+struct DexMethodAnnotationsItem {
u4 methodIdx;
u4 annotationsOff; /* offset to DexAnnotationSetItem */
-} DexMethodAnnotationsItem;
+};
/*
* Direct-mapped "parameter_annotations_item".
*/
-typedef struct DexParameterAnnotationsItem {
+struct DexParameterAnnotationsItem {
u4 methodIdx;
u4 annotationsOff; /* offset to DexAnotationSetRefList */
-} DexParameterAnnotationsItem;
+};
/*
* Direct-mapped "annotation_set_ref_item".
*/
-typedef struct DexAnnotationSetRefItem {
+struct DexAnnotationSetRefItem {
u4 annotationsOff; /* offset to DexAnnotationSetItem */
-} DexAnnotationSetRefItem;
+};
/*
* Direct-mapped "annotation_set_ref_list".
*/
-typedef struct DexAnnotationSetRefList {
+struct DexAnnotationSetRefList {
u4 size;
DexAnnotationSetRefItem list[1];
-} DexAnnotationSetRefList;
+};
/*
* Direct-mapped "annotation_set_item".
*/
-typedef struct DexAnnotationSetItem {
+struct DexAnnotationSetItem {
u4 size;
u4 entries[1]; /* offset to DexAnnotationItem */
-} DexAnnotationSetItem;
+};
/*
* Direct-mapped "annotation_item".
*
* NOTE: this structure is byte-aligned.
*/
-typedef struct DexAnnotationItem {
+struct DexAnnotationItem {
u1 visibility;
u1 annotation[1]; /* data in encoded_annotation format */
-} DexAnnotationItem;
+};
/*
* Direct-mapped "encoded_array".
*
* NOTE: this structure is byte-aligned.
*/
-typedef struct DexEncodedArray {
+struct DexEncodedArray {
u1 array[1]; /* data in encoded_array format */
-} DexEncodedArray;
+};
/*
* Lookup table for classes. It provides a mapping from class name to
@@ -446,7 +446,7 @@
* a hash table with direct pointers to the items, but because it's shared
* there's less of a penalty for using a fairly sparse table.
*/
-typedef struct DexClassLookup {
+struct DexClassLookup {
int size; // total size, including "size"
int numEntries; // size of table[]; always power of 2
struct {
@@ -454,7 +454,7 @@
int classDescriptorOffset; // in bytes, from start of DEX
int classDefOffset; // in bytes, from start of DEX
} table[1];
-} DexClassLookup;
+};
/*
* Header added by DEX optimization pass. Values are always written in
@@ -464,7 +464,7 @@
*
* Try to keep this simple and fixed-size.
*/
-typedef struct DexOptHeader {
+struct DexOptHeader {
u1 magic[8]; /* includes version number */
u4 dexOffset; /* file offset of DEX header */
@@ -478,7 +478,7 @@
u4 checksum; /* adler32 checksum covering deps/opt */
/* pad for 64-bit alignment if necessary */
-} DexOptHeader;
+};
#define DEX_OPT_FLAG_BIG (1<<1) /* swapped to big-endian */
@@ -490,7 +490,7 @@
* Code should regard DexFile as opaque, using the API calls provided here
* to access specific structures.
*/
-typedef struct DexFile {
+struct DexFile {
/* directly-mapped "opt" header */
const DexOptHeader* pOptHeader;
@@ -519,7 +519,7 @@
/* additional app-specific data structures associated with the DEX */
//void* auxData;
-} DexFile;
+};
/*
* Utility function -- rounds up to the nearest power of 2.
diff --git a/libdex/DexInlines.c b/libdex/DexInlines.cpp
similarity index 100%
rename from libdex/DexInlines.c
rename to libdex/DexInlines.cpp
diff --git a/libdex/DexOpcodes.c b/libdex/DexOpcodes.cpp
similarity index 100%
rename from libdex/DexOpcodes.c
rename to libdex/DexOpcodes.cpp
diff --git a/libdex/DexOpcodes.h b/libdex/DexOpcodes.h
index 07188b2..d8dc9a7 100644
--- a/libdex/DexOpcodes.h
+++ b/libdex/DexOpcodes.h
@@ -66,7 +66,7 @@
* can find the next instruction" aren't possible. (This is
* correctable, but probably not useful.)
*/
-typedef enum Opcode {
+enum Opcode {
// BEGIN(libdex-opcode-enum); GENERATED AUTOMATICALLY BY opcode-gen
OP_NOP = 0x00,
OP_MOVE = 0x01,
@@ -581,7 +581,7 @@
OP_SPUT_OBJECT_VOLATILE_JUMBO = 0x1fe,
OP_THROW_VERIFICATION_ERROR_JUMBO = 0x1ff,
// END(libdex-opcode-enum)
-} Opcode;
+};
/*
* Macro used to generate a computed goto table for use in implementing
diff --git a/libdex/DexOptData.c b/libdex/DexOptData.cpp
similarity index 98%
rename from libdex/DexOptData.c
rename to libdex/DexOptData.cpp
index 10a4b5d..131b656 100644
--- a/libdex/DexOptData.c
+++ b/libdex/DexOptData.cpp
@@ -50,7 +50,7 @@
{
const void* pOptStart = data + pDexFile->pOptHeader->optOffset;
const void* pOptEnd = data + length;
- const u4* pOpt = pOptStart;
+ const u4* pOpt = (const u4*) pOptStart;
u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
/*
diff --git a/libdex/DexProto.c b/libdex/DexProto.cpp
similarity index 99%
rename from libdex/DexProto.c
rename to libdex/DexProto.cpp
index 25ab400..06c59b3 100644
--- a/libdex/DexProto.c
+++ b/libdex/DexProto.cpp
@@ -45,7 +45,7 @@
pCache->value = pCache->buffer;
pCache->allocatedSize = 0;
} else {
- pCache->value = malloc(length);
+ pCache->value = (char*) malloc(length);
pCache->allocatedSize = length;
}
}
diff --git a/libdex/DexProto.h b/libdex/DexProto.h
index 50d4bf3..591c274 100644
--- a/libdex/DexProto.h
+++ b/libdex/DexProto.h
@@ -30,11 +30,11 @@
* generally return a string that is valid until the next
* time the same DexStringCache is used.
*/
-typedef struct DexStringCache {
+struct DexStringCache {
char* value; /* the latest value */
size_t allocatedSize; /* size of the allocated buffer, if allocated */
char buffer[120]; /* buffer used to hold small-enough results */
-} DexStringCache;
+};
/*
* Make sure that the given cache can hold a string of the given length,
@@ -76,10 +76,10 @@
* Method prototype structure, which refers to a protoIdx in a
* particular DexFile.
*/
-typedef struct DexProto {
+struct DexProto {
const DexFile* dexFile; /* file the idx refers to */
u4 protoIdx; /* index into proto_ids table of dexFile */
-} DexProto;
+};
/*
* Set the given DexProto to refer to the prototype of the given MethodId.
@@ -199,12 +199,12 @@
* Single-thread prototype parameter iterator. This structure holds a
* pointer to a prototype and its parts, along with a cursor.
*/
-typedef struct DexParameterIterator {
+struct DexParameterIterator {
const DexProto* proto;
const DexTypeList* parameters;
int parameterCount;
int cursor;
-} DexParameterIterator;
+};
/*
* Initialize the given DexParameterIterator to be at the start of the
@@ -226,6 +226,4 @@
const char* dexParameterIteratorNextDescriptor(
DexParameterIterator* pIterator);
-
-
#endif /*_LIBDEX_DEXPROTO*/
diff --git a/libdex/DexSwapVerify.c b/libdex/DexSwapVerify.cpp
similarity index 97%
rename from libdex/DexSwapVerify.c
rename to libdex/DexSwapVerify.cpp
index 5fd3f09..ea05e0c 100644
--- a/libdex/DexSwapVerify.c
+++ b/libdex/DexSwapVerify.cpp
@@ -68,7 +68,7 @@
/*
* Some information we pass around to help verify values.
*/
-typedef struct CheckState {
+struct CheckState {
const DexHeader* pHeader;
const u1* fileStart;
const u1* fileEnd; // points to fileStart + fileLen
@@ -84,7 +84,7 @@
u4* pDefinedClassBits;
const void* previousItem; // set during section iteration
-} CheckState;
+};
/*
* Return the file offset of the given pointer.
@@ -131,8 +131,8 @@
* Assumes "const CheckState* state".
*/
#define CHECK_OFFSET_RANGE(_start, _end) { \
- const u1* _startPtr = filePointer(state, (_start)); \
- const u1* _endPtr = filePointer(state, (_end)); \
+ const u1* _startPtr = (const u1*) filePointer(state, (_start)); \
+ const u1* _endPtr = (const u1*) filePointer(state, (_end)); \
if (!checkPtrRange(state, _startPtr, _endPtr, \
#_start ".." #_end)) { \
return 0; \
@@ -332,7 +332,7 @@
return false;
}
- const DexHeader* pHeader = filePointer(state, 0);
+ const DexHeader* pHeader = (const DexHeader*) filePointer(state, 0);
*endOffset = pHeader->headerSize;
return true;
}
@@ -536,7 +536,7 @@
return false;
}
- const DexMapList* pMap = filePointer(state, sectionOffset);
+ const DexMapList* pMap = (const DexMapList*) filePointer(state, sectionOffset);
*endOffset =
sectionOffset + sizeof(u4) + (pMap->size * sizeof(DexMapItem));
@@ -545,7 +545,7 @@
/* Perform byte-swapping and intra-item verification on string_id_item. */
static void* swapStringIdItem(const CheckState* state, void* ptr) {
- DexStringId* item = ptr;
+ DexStringId* item = (DexStringId*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_OFFSET4(item->stringDataOff);
@@ -555,14 +555,14 @@
/* Perform cross-item verification of string_id_item. */
static void* crossVerifyStringIdItem(const CheckState* state, void* ptr) {
- const DexStringId* item = ptr;
+ const DexStringId* item = (const DexStringId*) ptr;
if (!dexDataMapVerify(state->pDataMap,
item->stringDataOff, kDexTypeStringDataItem)) {
return NULL;
}
- const DexStringId* item0 = state->previousItem;
+ const DexStringId* item0 = (const DexStringId*) state->previousItem;
if (item0 != NULL) {
// Check ordering.
const char* s0 = dexGetStringData(state->pDexFile, item0);
@@ -578,7 +578,7 @@
/* Perform byte-swapping and intra-item verification on type_id_item. */
static void* swapTypeIdItem(const CheckState* state, void* ptr) {
- DexTypeId* item = ptr;
+ DexTypeId* item = (DexTypeId*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_INDEX4(item->descriptorIdx, state->pHeader->stringIdsSize);
@@ -588,7 +588,7 @@
/* Perform cross-item verification of type_id_item. */
static void* crossVerifyTypeIdItem(const CheckState* state, void* ptr) {
- const DexTypeId* item = ptr;
+ const DexTypeId* item = (const DexTypeId*) ptr;
const char* descriptor =
dexStringById(state->pDexFile, item->descriptorIdx);
@@ -597,7 +597,7 @@
return NULL;
}
- const DexTypeId* item0 = state->previousItem;
+ const DexTypeId* item0 = (const DexTypeId*) state->previousItem;
if (item0 != NULL) {
// Check ordering. This relies on string_ids being in order.
if (item0->descriptorIdx >= item->descriptorIdx) {
@@ -612,7 +612,7 @@
/* Perform byte-swapping and intra-item verification on proto_id_item. */
static void* swapProtoIdItem(const CheckState* state, void* ptr) {
- DexProtoId* item = ptr;
+ DexProtoId* item = (DexProtoId*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_INDEX4(item->shortyIdx, state->pHeader->stringIdsSize);
@@ -669,7 +669,7 @@
/* Perform cross-item verification of proto_id_item. */
static void* crossVerifyProtoIdItem(const CheckState* state, void* ptr) {
- const DexProtoId* item = ptr;
+ const DexProtoId* item = (const DexProtoId*) ptr;
const char* shorty =
dexStringById(state->pDexFile, item->shortyIdx);
@@ -715,7 +715,7 @@
return NULL;
}
- const DexProtoId* item0 = state->previousItem;
+ const DexProtoId* item0 = (const DexProtoId*) state->previousItem;
if (item0 != NULL) {
// Check ordering. This relies on type_ids being in order.
if (item0->returnTypeIdx > item->returnTypeIdx) {
@@ -762,7 +762,7 @@
/* Perform byte-swapping and intra-item verification on field_id_item. */
static void* swapFieldIdItem(const CheckState* state, void* ptr) {
- DexFieldId* item = ptr;
+ DexFieldId* item = (DexFieldId*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize);
@@ -774,7 +774,7 @@
/* Perform cross-item verification of field_id_item. */
static void* crossVerifyFieldIdItem(const CheckState* state, void* ptr) {
- const DexFieldId* item = ptr;
+ const DexFieldId* item = (const DexFieldId*) ptr;
const char* s;
s = dexStringByTypeIdx(state->pDexFile, item->classIdx);
@@ -795,7 +795,7 @@
return NULL;
}
- const DexFieldId* item0 = state->previousItem;
+ const DexFieldId* item0 = (const DexFieldId*) state->previousItem;
if (item0 != NULL) {
// Check ordering. This relies on the other sections being in order.
bool done = false;
@@ -834,7 +834,7 @@
/* Perform byte-swapping and intra-item verification on method_id_item. */
static void* swapMethodIdItem(const CheckState* state, void* ptr) {
- DexMethodId* item = ptr;
+ DexMethodId* item = (DexMethodId*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize);
@@ -846,7 +846,7 @@
/* Perform cross-item verification of method_id_item. */
static void* crossVerifyMethodIdItem(const CheckState* state, void* ptr) {
- const DexMethodId* item = ptr;
+ const DexMethodId* item = (const DexMethodId*) ptr;
const char* s;
s = dexStringByTypeIdx(state->pDexFile, item->classIdx);
@@ -861,7 +861,7 @@
return NULL;
}
- const DexMethodId* item0 = state->previousItem;
+ const DexMethodId* item0 = (const DexMethodId*) state->previousItem;
if (item0 != NULL) {
// Check ordering. This relies on the other sections being in order.
bool done = false;
@@ -900,7 +900,7 @@
/* Perform byte-swapping and intra-item verification on class_def_item. */
static void* swapClassDefItem(const CheckState* state, void* ptr) {
- DexClassDef* item = ptr;
+ DexClassDef* item = (DexClassDef*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_INDEX4(item->classIdx, state->pHeader->typeIdsSize);
@@ -928,7 +928,7 @@
return true;
}
- const u1* data = filePointer(state, offset);
+ const u1* data = (const u1*) filePointer(state, offset);
DexClassData* classData = dexReadAndVerifyClassData(&data, NULL);
if (classData == NULL) {
@@ -957,7 +957,8 @@
return true;
}
- const DexAnnotationsDirectoryItem* dir = filePointer(state, offset);
+ const DexAnnotationsDirectoryItem* dir =
+ (const DexAnnotationsDirectoryItem*) filePointer(state, offset);
u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir);
return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex);
@@ -965,7 +966,7 @@
/* Perform cross-item verification of class_def_item. */
static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) {
- const DexClassDef* item = ptr;
+ const DexClassDef* item = (const DexClassDef*) ptr;
u4 classIdx = item->classIdx;
const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx);
@@ -1146,7 +1147,7 @@
/* Perform byte-swapping and intra-item verification on
* annotations_directory_item. */
static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) {
- DexAnnotationsDirectoryItem* item = ptr;
+ DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr;
CHECK_PTR_RANGE(item, item + 1);
SWAP_OFFSET4(item->classAnnotationsOff);
@@ -1276,7 +1277,7 @@
/* Perform cross-item verification of annotations_directory_item. */
static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state,
void* ptr) {
- const DexAnnotationsDirectoryItem* item = ptr;
+ const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr;
u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item);
if (!dexDataMapVerify0Ok(state->pDataMap,
@@ -1316,7 +1317,7 @@
/* Perform byte-swapping and intra-item verification on type_list. */
static void* swapTypeList(const CheckState* state, void* ptr)
{
- DexTypeList* pTypeList = ptr;
+ DexTypeList* pTypeList = (DexTypeList*) ptr;
DexTypeItem* pType;
u4 count;
@@ -1337,7 +1338,7 @@
/* Perform byte-swapping and intra-item verification on
* annotation_set_ref_list. */
static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) {
- DexAnnotationSetRefList* list = ptr;
+ DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr;
DexAnnotationSetRefItem* item;
u4 count;
@@ -1358,7 +1359,7 @@
/* Perform cross-item verification of annotation_set_ref_list. */
static void* crossVerifyAnnotationSetRefList(const CheckState* state,
void* ptr) {
- const DexAnnotationSetRefList* list = ptr;
+ const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr;
const DexAnnotationSetRefItem* item = list->list;
int count = list->size;
@@ -1376,7 +1377,7 @@
/* Perform byte-swapping and intra-item verification on
* annotation_set_item. */
static void* swapAnnotationSetItem(const CheckState* state, void* ptr) {
- DexAnnotationSetItem* set = ptr;
+ DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr;
u4* item;
u4 count;
@@ -1403,7 +1404,7 @@
/* Perform cross-item verification of annotation_set_item. */
static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) {
- const DexAnnotationSetItem* set = ptr;
+ const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr;
int count = set->size;
u4 lastIdx = 0;
bool first = true;
@@ -1545,7 +1546,7 @@
/* Perform intra-item verification on class_data_item. */
static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) {
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
if (classData == NULL) {
@@ -1598,7 +1599,7 @@
/* Perform cross-item verification of class_data_item. */
static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) {
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
u4 definingClass = findFirstClassDataDefiner(state, classData);
bool okay = true;
@@ -1798,7 +1799,7 @@
/* Perform byte-swapping and intra-item verification on code_item. */
static void* swapCodeItem(const CheckState* state, void* ptr) {
- DexCode* item = ptr;
+ DexCode* item = (DexCode*) ptr;
u2* insns;
u4 count;
@@ -1858,7 +1859,7 @@
/* Perform intra-item verification on string_data_item. */
static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) {
const u1* fileEnd = state->fileEnd;
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
bool okay = true;
u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
u4 i;
@@ -1959,7 +1960,7 @@
/* Perform intra-item verification on debug_info_item. */
static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) {
const u1* fileEnd = state->fileEnd;
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
bool okay = true;
u4 i;
@@ -2341,7 +2342,7 @@
/* Perform intra-item verification on annotation_item. */
static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) {
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
CHECK_PTR_RANGE(data, data + 1);
@@ -2362,7 +2363,7 @@
/* Perform cross-item verification on annotation_item. */
static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) {
- const u1* data = ptr;
+ const u1* data = (const u1*) ptr;
// Skip the visibility byte.
data++;
@@ -2393,10 +2394,10 @@
for (i = 0; i < count; i++) {
u4 newOffset = (offset + alignmentMask) & ~alignmentMask;
- u1* ptr = filePointer(state, newOffset);
+ u1* ptr = (u1*) filePointer(state, newOffset);
if (offset < newOffset) {
- ptr = filePointer(state, offset);
+ ptr = (u1*) filePointer(state, offset);
if (offset < newOffset) {
CHECK_OFFSET_RANGE(offset, newOffset);
while (offset < newOffset) {
@@ -2523,7 +2524,7 @@
if (lastOffset < sectionOffset) {
CHECK_OFFSET_RANGE(lastOffset, sectionOffset);
- const u1* ptr = filePointer(state, lastOffset);
+ const u1* ptr = (const u1*) filePointer(state, lastOffset);
while (lastOffset < sectionOffset) {
if (*ptr != '\0') {
LOGE("Non-zero padding 0x%02x before section start @ %x\n",
diff --git a/libdex/DexUtf.c b/libdex/DexUtf.cpp
similarity index 100%
rename from libdex/DexUtf.c
rename to libdex/DexUtf.cpp
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.cpp
similarity index 100%
rename from libdex/InstrUtils.c
rename to libdex/InstrUtils.cpp
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index f09429c..187fd5c 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -29,7 +29,7 @@
* See the file opcode-gen/README.txt for information about updating
* opcodes and instruction formats.
*/
-typedef enum {
+enum InstructionFormat {
kFmt00x = 0, // unknown format (also used for "breakpoint" opcode)
kFmt10x, // op
kFmt12x, // op vA, vB
@@ -67,13 +67,13 @@
kFmt41c, // exop vAAAA, thing@BBBBBBBB
kFmt52c, // exop vAAAA, vBBBB, thing@CCCCCCCC
kFmt5rc, // exop {vCCCC .. v(CCCC+AAAA-1)}, thing@BBBBBBBB
-} InstructionFormat;
+};
/*
* Types of indexed reference that are associated with opcodes whose
* formats include such an indexed reference (e.g., 21c and 35c).
*/
-typedef enum {
+enum InstructionIndexType {
kIndexUnknown = 0,
kIndexNone, // has no index
kIndexVaries, // "It depends." Used for throw-verification-error
@@ -84,7 +84,7 @@
kIndexInlineMethod, // inline method index (for inline linked methods)
kIndexVtableOffset, // vtable offset (for static linked methods)
kIndexFieldOffset // field offset (for static linked fields)
-} InstructionIndexType;
+};
/*
* Instruction width implied by an opcode's format; a value in the
@@ -117,12 +117,12 @@
* that works for both C and C++, but in the mean time, this will
* suffice.
*/
-typedef struct InstructionInfoTables {
+struct InstructionInfoTables {
u1* formats; /* InstructionFormat elements */
u1* indexTypes; /* InstructionIndexType elements */
OpcodeFlags* flags;
InstructionWidth* widths;
-} InstructionInfoTables;
+};
/*
* Global InstructionInfoTables struct.
@@ -132,7 +132,7 @@
/*
* Holds the contents of a decoded instruction.
*/
-typedef struct DecodedInstruction {
+struct DecodedInstruction {
u4 vA;
u4 vB;
u8 vB_wide; /* for kFmt51l */
@@ -140,7 +140,7 @@
u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
Opcode opcode;
InstructionIndexType indexType;
-} DecodedInstruction;
+};
/*
* Return the instruction width of the specified opcode, or 0 if not defined.
diff --git a/libdex/Leb128.c b/libdex/Leb128.cpp
similarity index 100%
rename from libdex/Leb128.c
rename to libdex/Leb128.cpp
diff --git a/libdex/OptInvocation.c b/libdex/OptInvocation.cpp
similarity index 100%
rename from libdex/OptInvocation.c
rename to libdex/OptInvocation.cpp
diff --git a/libdex/OptInvocation.h b/libdex/OptInvocation.h
index 0352eb4..e44ce54 100644
--- a/libdex/OptInvocation.h
+++ b/libdex/OptInvocation.h
@@ -20,10 +20,6 @@
#ifndef _LIBDEX_OPTINVOCATION
#define _LIBDEX_OPTINVOCATION
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/*
* Utility routines, used by the VM.
*/
@@ -31,8 +27,4 @@
const char* subFileName);
int dexOptCreateEmptyHeader(int fd);
-#ifdef __cplusplus
-};
-#endif
-
#endif /*_LIBDEX_OPTINVOCATION*/
diff --git a/libdex/SysUtil.c b/libdex/SysUtil.cpp
similarity index 100%
rename from libdex/SysUtil.c
rename to libdex/SysUtil.cpp
diff --git a/libdex/SysUtil.h b/libdex/SysUtil.h
index 4de0289..e297dc0 100644
--- a/libdex/SysUtil.h
+++ b/libdex/SysUtil.h
@@ -36,13 +36,13 @@
/*
* Use this to keep track of mapped segments.
*/
-typedef struct MemMapping {
+struct MemMapping {
void* addr; /* start of data */
size_t length; /* length of data */
void* baseAddr; /* page-aligned base address */
size_t baseLength; /* length of mapping */
-} MemMapping;
+};
/*
* Copy a map.
diff --git a/libdex/ZipArchive.c b/libdex/ZipArchive.cpp
similarity index 97%
rename from libdex/ZipArchive.c
rename to libdex/ZipArchive.cpp
index dd9dce4..29b665e 100644
--- a/libdex/ZipArchive.c
+++ b/libdex/ZipArchive.cpp
@@ -141,27 +141,16 @@
return result;
}
-/*
- * Find the zip Central Directory and memory-map it.
- *
- * On success, returns 0 after populating fields from the EOCD area:
- * mDirectoryOffset
- * mDirectoryMap
- * mNumEntries
- */
-static int mapCentralDirectory(int fd, const char* debugFileName,
- ZipArchive* pArchive)
+static int mapCentralDirectory0(int fd, const char* debugFileName,
+ ZipArchive* pArchive, u1* scanBuf)
{
- u1* scanBuf = NULL;
- int result = -1;
-
/*
* Get and test file length.
*/
off_t fileLength = lseek(fd, 0, SEEK_END);
if (fileLength < kEOCDLen) {
LOGV("Zip: length %ld is too small to be zip\n", (long) fileLength);
- goto bail;
+ return -1;
}
/*
@@ -184,12 +173,12 @@
scanBuf = (u1*) malloc(readAmount);
if (lseek(fd, searchStart, SEEK_SET) != searchStart) {
LOGW("Zip: seek %ld failed: %s\n", (long) searchStart, strerror(errno));
- goto bail;
+ return -1;
}
ssize_t actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, readAmount));
if (actual != (ssize_t) readAmount) {
LOGW("Zip: read %zd failed: %s\n", readAmount, strerror(errno));
- goto bail;
+ return -1;
}
/*
@@ -207,7 +196,7 @@
}
if (i < 0) {
LOGD("Zip: EOCD not found, %s is not zip\n", debugFileName);
- goto bail;
+ return -1;
}
off_t eocdOffset = searchStart + i;
@@ -226,11 +215,11 @@
if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) {
LOGW("Zip: bad offsets (dir %ld, size %u, eocd %ld)\n",
(long) dirOffset, dirSize, (long) eocdOffset);
- goto bail;
+ return -1;
}
if (numEntries == 0) {
LOGW("Zip: empty archive?\n");
- goto bail;
+ return -1;
}
LOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n",
@@ -244,15 +233,34 @@
&pArchive->mDirectoryMap) != 0)
{
LOGW("Zip: cd map failed\n");
- goto bail;
+ return -1;
}
pArchive->mNumEntries = numEntries;
pArchive->mDirectoryOffset = dirOffset;
- result = 0;
+ return 0;
+}
-bail:
+/*
+ * Find the zip Central Directory and memory-map it.
+ *
+ * On success, returns 0 after populating fields from the EOCD area:
+ * mDirectoryOffset
+ * mDirectoryMap
+ * mNumEntries
+ */
+static int mapCentralDirectory(int fd, const char* debugFileName,
+ ZipArchive* pArchive)
+{
+ u1* scanBuf = (u1*) malloc(kMaxEOCDSearch);
+
+ if (scanBuf == NULL) {
+ return -1;
+ }
+
+ int result = mapCentralDirectory0(fd, debugFileName, pArchive, scanBuf);
+
free(scanBuf);
return result;
}
diff --git a/libdex/ZipArchive.h b/libdex/ZipArchive.h
index bf4edf9..8d15cf6 100644
--- a/libdex/ZipArchive.h
+++ b/libdex/ZipArchive.h
@@ -23,7 +23,6 @@
#include "SysUtil.h"
#include "DexFile.h" // need DEX_INLINE
-
/*
* Trivial typedef to ensure that ZipEntry is not treated as a simple
* integer. We use NULL to indicate an invalid value.
@@ -33,11 +32,10 @@
/*
* One entry in the hash table.
*/
-typedef struct ZipHashEntry {
+struct ZipHashEntry {
const char* name;
unsigned short nameLen;
- //unsigned int hash;
-} ZipHashEntry;
+};
/*
* Read-only Zip archive.
@@ -58,7 +56,7 @@
* every page that the Central Directory touches. Easier to tuck a copy
* of the string length into the hash table entry.
*/
-typedef struct ZipArchive {
+struct ZipArchive {
/* open Zip archive */
int mFd;
@@ -75,7 +73,7 @@
*/
int mHashTableSize;
ZipHashEntry* mHashTable;
-} ZipArchive;
+};
/* Zip compression methods we support */
enum {
diff --git a/libdex/sha1.c b/libdex/sha1.cpp
similarity index 99%
rename from libdex/sha1.c
rename to libdex/sha1.cpp
index dc7e30a..15a81cc 100644
--- a/libdex/sha1.c
+++ b/libdex/sha1.cpp
@@ -136,10 +136,10 @@
const unsigned char buffer[64])
{
unsigned long a, b, c, d, e;
-typedef union {
+union CHAR64LONG16 {
unsigned char c[64];
unsigned long l[16];
-} CHAR64LONG16;
+};
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static unsigned char workspace[64];
diff --git a/libdex/sha1.h b/libdex/sha1.h
index 65cf667..f18a8c0 100644
--- a/libdex/sha1.h
+++ b/libdex/sha1.h
@@ -1,14 +1,14 @@
/*
- * See "sha1.c" for author info.
+ * See "sha1.cpp" for author info.
*/
#ifndef _DALVIK_SHA1
#define _DALVIK_SHA1
-typedef struct {
+struct SHA1_CTX {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
-} SHA1_CTX;
+};
#define HASHSIZE 20
diff --git a/libnativehelper/Android.mk b/libnativehelper/Android.mk
index 088de10..3b0b6dc 100644
--- a/libnativehelper/Android.mk
+++ b/libnativehelper/Android.mk
@@ -20,13 +20,13 @@
#
src_files := \
- JNIHelp.c \
- Register.c
+ JNIHelp.cpp \
+ Register.cpp
c_includes := \
$(JNI_H_INCLUDE)
-# Any shared/static libs required by libjavacore
+# Any shared/static libs required by libcore
# need to be mentioned here as well.
# TODO: fix this requirement
diff --git a/libnativehelper/JNIHelp.c b/libnativehelper/JNIHelp.c
deleted file mode 100644
index fb23a9e..0000000
--- a/libnativehelper/JNIHelp.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-/*
- * JNI helper functions.
- */
-#define LOG_TAG "JNIHelp"
-#include "JNIHelp.h"
-#include "utils/Log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/*
- * Register native JNI-callable methods.
- *
- * "className" looks like "java/lang/String".
- */
-int jniRegisterNativeMethods(JNIEnv* env, const char* className,
- const JNINativeMethod* gMethods, int numMethods)
-{
- jclass clazz;
-
- LOGV("Registering %s natives\n", className);
- clazz = (*env)->FindClass(env, className);
- if (clazz == NULL) {
- LOGE("Native registration unable to find class '%s', aborting\n",
- className);
- abort();
- }
-
- if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
- LOGE("RegisterNatives failed for '%s', aborting\n", className);
- abort();
- }
-
- (*env)->DeleteLocalRef(env, clazz);
- return 0;
-}
-
-/*
- * Get a human-readable summary of an exception object. The buffer will
- * be populated with the "binary" class name and, if present, the
- * exception message.
- */
-static void getExceptionSummary(JNIEnv* env, jthrowable exception, char* buf, size_t bufLen)
-{
- int success = 0;
-
- /* get the name of the exception's class */
- jclass exceptionClazz = (*env)->GetObjectClass(env, exception); // can't fail
- jclass classClazz = (*env)->GetObjectClass(env, exceptionClazz); // java.lang.Class, can't fail
- jmethodID classGetNameMethod = (*env)->GetMethodID(
- env, classClazz, "getName", "()Ljava/lang/String;");
- jstring classNameStr = (*env)->CallObjectMethod(env, exceptionClazz, classGetNameMethod);
- if (classNameStr != NULL) {
- /* get printable string */
- const char* classNameChars = (*env)->GetStringUTFChars(env, classNameStr, NULL);
- if (classNameChars != NULL) {
- /* if the exception has a message string, get that */
- jmethodID throwableGetMessageMethod = (*env)->GetMethodID(
- env, exceptionClazz, "getMessage", "()Ljava/lang/String;");
- jstring messageStr = (*env)->CallObjectMethod(
- env, exception, throwableGetMessageMethod);
-
- if (messageStr != NULL) {
- const char* messageChars = (*env)->GetStringUTFChars(env, messageStr, NULL);
- if (messageChars != NULL) {
- snprintf(buf, bufLen, "%s: %s", classNameChars, messageChars);
- (*env)->ReleaseStringUTFChars(env, messageStr, messageChars);
- } else {
- (*env)->ExceptionClear(env); // clear OOM
- snprintf(buf, bufLen, "%s: <error getting message>", classNameChars);
- }
- (*env)->DeleteLocalRef(env, messageStr);
- } else {
- strncpy(buf, classNameChars, bufLen);
- buf[bufLen - 1] = '\0';
- }
-
- (*env)->ReleaseStringUTFChars(env, classNameStr, classNameChars);
- success = 1;
- }
- (*env)->DeleteLocalRef(env, classNameStr);
- }
- (*env)->DeleteLocalRef(env, classClazz);
- (*env)->DeleteLocalRef(env, exceptionClazz);
-
- if (! success) {
- (*env)->ExceptionClear(env);
- snprintf(buf, bufLen, "%s", "<error getting class name>");
- }
-}
-
-/*
- * Formats an exception as a string with its stack trace.
- */
-static void printStackTrace(JNIEnv* env, jthrowable exception, char* buf, size_t bufLen)
-{
- int success = 0;
-
- jclass stringWriterClazz = (*env)->FindClass(env, "java/io/StringWriter");
- if (stringWriterClazz != NULL) {
- jmethodID stringWriterCtor = (*env)->GetMethodID(env, stringWriterClazz,
- "<init>", "()V");
- jmethodID stringWriterToStringMethod = (*env)->GetMethodID(env, stringWriterClazz,
- "toString", "()Ljava/lang/String;");
-
- jclass printWriterClazz = (*env)->FindClass(env, "java/io/PrintWriter");
- if (printWriterClazz != NULL) {
- jmethodID printWriterCtor = (*env)->GetMethodID(env, printWriterClazz,
- "<init>", "(Ljava/io/Writer;)V");
-
- jobject stringWriterObj = (*env)->NewObject(env, stringWriterClazz, stringWriterCtor);
- if (stringWriterObj != NULL) {
- jobject printWriterObj = (*env)->NewObject(env, printWriterClazz, printWriterCtor,
- stringWriterObj);
- if (printWriterObj != NULL) {
- jclass exceptionClazz = (*env)->GetObjectClass(env, exception); // can't fail
- jmethodID printStackTraceMethod = (*env)->GetMethodID(
- env, exceptionClazz, "printStackTrace", "(Ljava/io/PrintWriter;)V");
-
- (*env)->CallVoidMethod(
- env, exception, printStackTraceMethod, printWriterObj);
- if (! (*env)->ExceptionCheck(env)) {
- jstring messageStr = (*env)->CallObjectMethod(
- env, stringWriterObj, stringWriterToStringMethod);
- if (messageStr != NULL) {
- jsize messageStrLength = (*env)->GetStringLength(env, messageStr);
- if (messageStrLength >= (jsize) bufLen) {
- messageStrLength = bufLen - 1;
- }
- (*env)->GetStringUTFRegion(env, messageStr, 0, messageStrLength, buf);
- (*env)->DeleteLocalRef(env, messageStr);
- buf[messageStrLength] = '\0';
- success = 1;
- }
- }
- (*env)->DeleteLocalRef(env, exceptionClazz);
- (*env)->DeleteLocalRef(env, printWriterObj);
- }
- (*env)->DeleteLocalRef(env, stringWriterObj);
- }
- (*env)->DeleteLocalRef(env, printWriterClazz);
- }
- (*env)->DeleteLocalRef(env, stringWriterClazz);
- }
-
- if (! success) {
- (*env)->ExceptionClear(env);
- getExceptionSummary(env, exception, buf, bufLen);
- }
-}
-
-/*
- * Throw an exception with the specified class and an optional message.
- *
- * If an exception is currently pending, we log a warning message and
- * clear it.
- *
- * Returns 0 if the specified exception was successfully thrown. (Some
- * sort of exception will always be pending when this returns.)
- */
-int jniThrowException(JNIEnv* env, const char* className, const char* msg)
-{
- jclass exceptionClass;
-
- if ((*env)->ExceptionCheck(env)) {
- /* TODO: consider creating the new exception with this as "cause" */
- char buf[256];
-
- jthrowable exception = (*env)->ExceptionOccurred(env);
- (*env)->ExceptionClear(env);
-
- if (exception != NULL) {
- getExceptionSummary(env, exception, buf, sizeof(buf));
- LOGW("Discarding pending exception (%s) to throw %s\n", buf, className);
- (*env)->DeleteLocalRef(env, exception);
- }
- }
-
- exceptionClass = (*env)->FindClass(env, className);
- if (exceptionClass == NULL) {
- LOGE("Unable to find exception class %s\n", className);
- /* ClassNotFoundException now pending */
- return -1;
- }
-
- int result = 0;
- if ((*env)->ThrowNew(env, exceptionClass, msg) != JNI_OK) {
- LOGE("Failed throwing '%s' '%s'\n", className, msg);
- /* an exception, most likely OOM, will now be pending */
- result = -1;
- }
-
- (*env)->DeleteLocalRef(env, exceptionClass);
- return result;
-}
-
-int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt,
- va_list args)
-{
- char msgBuf[512];
- vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
- return jniThrowException(env, className, msgBuf);
-}
-
-/*
- * Throw a java.lang.NullPointerException, with an optional message.
- */
-int jniThrowNullPointerException(JNIEnv* env, const char* msg)
-{
- return jniThrowException(env, "java/lang/NullPointerException", msg);
-}
-
-/*
- * Throw a java.lang.RuntimeException, with an optional message.
- */
-int jniThrowRuntimeException(JNIEnv* env, const char* msg)
-{
- return jniThrowException(env, "java/lang/RuntimeException", msg);
-}
-
-/*
- * Throw a java.io.IOException, generating the message from errno.
- */
-int jniThrowIOException(JNIEnv* env, int errnum)
-{
- char buffer[80];
- const char* message = jniStrError(errnum, buffer, sizeof(buffer));
- return jniThrowException(env, "java/io/IOException", message);
-}
-
-/*
- * Log an exception.
- * If exception is NULL, logs the current exception in the JNI environment, if any.
- */
-void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception)
-{
- int currentException = 0;
- if (exception == NULL) {
- exception = (*env)->ExceptionOccurred(env);
- if (exception == NULL) {
- return;
- }
-
- (*env)->ExceptionClear(env);
- currentException = 1;
- }
-
- char buffer[1024];
- printStackTrace(env, exception, buffer, sizeof(buffer));
- __android_log_write(priority, tag, buffer);
-
- if (currentException) {
- (*env)->Throw(env, exception); // rethrow
- (*env)->DeleteLocalRef(env, exception);
- }
-}
-
-const char* jniStrError(int errnum, char* buf, size_t buflen)
-{
- // note: glibc has a nonstandard strerror_r that returns char* rather
- // than POSIX's int.
- // char *strerror_r(int errnum, char *buf, size_t n);
- char* ret = (char*) strerror_r(errnum, buf, buflen);
- if (((int)ret) == 0) {
- //POSIX strerror_r, success
- return buf;
- } else if (((int)ret) == -1) {
- //POSIX strerror_r, failure
- // (Strictly, POSIX only guarantees a value other than 0. The safest
- // way to implement this function is to use C++ and overload on the
- // type of strerror_r to accurately distinguish GNU from POSIX. But
- // realistic implementations will always return -1.)
- snprintf(buf, buflen, "errno %d", errnum);
- return buf;
- } else {
- //glibc strerror_r returning a string
- return ret;
- }
-}
-
-static struct CachedFields {
- jclass fileDescriptorClass;
- jmethodID fileDescriptorCtor;
- jfieldID descriptorField;
-} gCachedFields;
-
-int registerJniHelp(JNIEnv* env) {
- gCachedFields.fileDescriptorClass =
- (*env)->NewGlobalRef(env, (*env)->FindClass(env, "java/io/FileDescriptor"));
- if (gCachedFields.fileDescriptorClass == NULL) {
- return -1;
- }
-
- gCachedFields.fileDescriptorCtor =
- (*env)->GetMethodID(env, gCachedFields.fileDescriptorClass, "<init>", "()V");
- if (gCachedFields.fileDescriptorCtor == NULL) {
- return -1;
- }
-
- gCachedFields.descriptorField =
- (*env)->GetFieldID(env, gCachedFields.fileDescriptorClass, "descriptor", "I");
- if (gCachedFields.descriptorField == NULL) {
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Create a java.io.FileDescriptor given an integer fd
- */
-jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
- jobject fileDescriptor = (*env)->NewObject(env,
- gCachedFields.fileDescriptorClass, gCachedFields.fileDescriptorCtor);
- jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
- return fileDescriptor;
-}
-
-/*
- * Get an int file descriptor from a java.io.FileDescriptor
- */
-int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
- return (*env)->GetIntField(env, fileDescriptor, gCachedFields.descriptorField);
-}
-
-/*
- * Set the descriptor of a java.io.FileDescriptor
- */
-void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
- (*env)->SetIntField(env, fileDescriptor, gCachedFields.descriptorField, value);
-}
-
-/*
- * DO NOT USE THIS FUNCTION
- *
- * Get a pointer to the elements of a non-movable array.
- *
- * The semantics are similar to GetDirectBufferAddress. Specifically, the VM
- * guarantees that the array will not move, and the caller must ensure that
- * it does not continue to use the pointer after the object is collected.
- *
- * We currently use an illegal sequence that trips up CheckJNI when
- * the "forcecopy" mode is enabled. We pass in a magic value to work
- * around the problem.
- *
- * Returns NULL if the array is movable.
- */
-jbyte* jniGetNonMovableArrayElements(JNIEnv* env, jarray arrayObj)
-{
-#define kNoCopyMagic 0xd5aab57f /* also in CheckJni.c */
-
- /*
- * Normally the "isCopy" parameter is for a return value only, so the
- * non-CheckJNI VM will ignore whatever we pass in.
- */
- uint32_t noCopy = kNoCopyMagic;
- jbyte *addr = (*env)->GetByteArrayElements(env, arrayObj,
- (jboolean*)&noCopy);
-
- /*
- * The non-CheckJNI implementation only cares about the array object,
- * so we can replace the element pointer with the magic value.
- */
- (*env)->ReleaseByteArrayElements(env, arrayObj, (jbyte*) kNoCopyMagic, 0);
- return addr;
-}
diff --git a/libnativehelper/JNIHelp.cpp b/libnativehelper/JNIHelp.cpp
new file mode 100644
index 0000000..79a4042
--- /dev/null
+++ b/libnativehelper/JNIHelp.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#define LOG_TAG "JNIHelp"
+
+#include "JNIHelp.h"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/**
+ * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
+ */
+template<typename T>
+class scoped_local_ref {
+public:
+ scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
+ : mEnv(env), mLocalRef(localRef)
+ {
+ }
+
+ ~scoped_local_ref() {
+ reset();
+ }
+
+ void reset(T localRef = NULL) {
+ if (mLocalRef != NULL) {
+ (*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef);
+ mLocalRef = localRef;
+ }
+ }
+
+ T get() const {
+ return mLocalRef;
+ }
+
+private:
+ C_JNIEnv* mEnv;
+ T mLocalRef;
+
+ // Disallow copy and assignment.
+ scoped_local_ref(const scoped_local_ref&);
+ void operator=(const scoped_local_ref&);
+};
+
+static jclass findClass(C_JNIEnv* env, const char* className) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+ return (*env)->FindClass(e, className);
+}
+
+extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
+ const JNINativeMethod* gMethods, int numMethods)
+{
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ LOGV("Registering %s natives", className);
+
+ scoped_local_ref<jclass> c(env, findClass(env, className));
+ if (c.get() == NULL) {
+ LOGE("Native registration unable to find class '%s', aborting", className);
+ abort();
+ }
+
+ if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
+ LOGE("RegisterNatives failed for '%s', aborting", className);
+ abort();
+ }
+
+ return 0;
+}
+
+/*
+ * Returns a human-readable summary of an exception object. The buffer will
+ * be populated with the "binary" class name and, if present, the
+ * exception message.
+ */
+static char* getExceptionSummary0(C_JNIEnv* env, jthrowable exception) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ /* get the name of the exception's class */
+ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
+ scoped_local_ref<jclass> classClass(env,
+ (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail
+ jmethodID classGetNameMethod =
+ (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;");
+ scoped_local_ref<jstring> classNameStr(env,
+ (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod));
+ if (classNameStr.get() == NULL) {
+ return NULL;
+ }
+
+ /* get printable string */
+ const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL);
+ if (classNameChars == NULL) {
+ return NULL;
+ }
+
+ /* if the exception has a detail message, get that */
+ jmethodID getMessage =
+ (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;");
+ scoped_local_ref<jstring> messageStr(env,
+ (jstring) (*env)->CallObjectMethod(e, exception, getMessage));
+ if (messageStr.get() == NULL) {
+ return strdup(classNameChars);
+ }
+
+ char* result = NULL;
+ const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
+ if (messageChars != NULL) {
+ asprintf(&result, "%s: %s", classNameChars, messageChars);
+ (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars);
+ } else {
+ (*env)->ExceptionClear(e); // clear OOM
+ asprintf(&result, "%s: <error getting message>", classNameChars);
+ }
+
+ (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars);
+ return result;
+}
+
+static char* getExceptionSummary(C_JNIEnv* env, jthrowable exception) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+ char* result = getExceptionSummary0(env, exception);
+ if (result == NULL) {
+ (*env)->ExceptionClear(e);
+ result = strdup("<error getting class name>");
+ }
+ return result;
+}
+
+/*
+ * Returns an exception (with stack trace) as a string.
+ */
+static char* getStackTrace(C_JNIEnv* env, jthrowable exception) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ scoped_local_ref<jclass> stringWriterClass(env, findClass(env, "java/io/StringWriter"));
+ if (stringWriterClass.get() == NULL) {
+ return NULL;
+ }
+
+ jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "<init>", "()V");
+ jmethodID stringWriterToStringMethod =
+ (*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;");
+
+ scoped_local_ref<jclass> printWriterClass(env, findClass(env, "java/io/PrintWriter"));
+ if (printWriterClass.get() == NULL) {
+ return NULL;
+ }
+
+ jmethodID printWriterCtor =
+ (*env)->GetMethodID(e, printWriterClass.get(), "<init>", "(Ljava/io/Writer;)V");
+
+ scoped_local_ref<jobject> stringWriter(env,
+ (*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor));
+ if (stringWriter.get() == NULL) {
+ return NULL;
+ }
+
+ jobject printWriter =
+ (*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get());
+ if (printWriter == NULL) {
+ return NULL;
+ }
+
+ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
+ jmethodID printStackTraceMethod =
+ (*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V");
+ (*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter);
+
+ if ((*env)->ExceptionCheck(e)) {
+ return NULL;
+ }
+
+ scoped_local_ref<jstring> messageStr(env,
+ (jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod));
+ if (messageStr.get() == NULL) {
+ return NULL;
+ }
+
+ const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
+ if (utfChars == NULL) {
+ return NULL;
+ }
+
+ char* result = strdup(utfChars);
+ (*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars);
+ return result;
+}
+
+extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ if ((*env)->ExceptionCheck(e)) {
+ /* TODO: consider creating the new exception with this as "cause" */
+ scoped_local_ref<jthrowable> exception(env, (*env)->ExceptionOccurred(e));
+ (*env)->ExceptionClear(e);
+
+ if (exception.get() != NULL) {
+ char* text = getExceptionSummary(env, exception.get());
+ LOGW("Discarding pending exception (%s) to throw %s", text, className);
+ free(text);
+ }
+ }
+
+ scoped_local_ref<jclass> exceptionClass(env, findClass(env, className));
+ if (exceptionClass.get() == NULL) {
+ LOGE("Unable to find exception class %s", className);
+ /* ClassNotFoundException now pending */
+ return -1;
+ }
+
+ if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) {
+ LOGE("Failed throwing '%s' '%s'", className, msg);
+ /* an exception, most likely OOM, will now be pending */
+ return -1;
+ }
+
+ return 0;
+}
+
+int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) {
+ char msgBuf[512];
+ vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
+ return jniThrowException(env, className, msgBuf);
+}
+
+int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) {
+ return jniThrowException(env, "java/lang/NullPointerException", msg);
+}
+
+int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) {
+ return jniThrowException(env, "java/lang/RuntimeException", msg);
+}
+
+int jniThrowIOException(C_JNIEnv* env, int errnum) {
+ char buffer[80];
+ const char* message = jniStrError(errnum, buffer, sizeof(buffer));
+ return jniThrowException(env, "java/io/IOException", message);
+}
+
+void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ scoped_local_ref<jthrowable> currentException(env);
+ if (exception == NULL) {
+ exception = (*env)->ExceptionOccurred(e);
+ if (exception == NULL) {
+ return;
+ }
+
+ (*env)->ExceptionClear(e);
+ currentException.reset(exception);
+ }
+
+ char* buffer = getStackTrace(env, exception);
+ if (buffer == NULL) {
+ (*env)->ExceptionClear(e);
+ buffer = getExceptionSummary(env, exception);
+ }
+
+ __android_log_write(priority, tag, buffer);
+ free(buffer);
+
+ if (currentException.get() != NULL) {
+ (*env)->Throw(e, exception); // rethrow
+ }
+}
+
+const char* jniStrError(int errnum, char* buf, size_t buflen) {
+ // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
+ // char *strerror_r(int errnum, char *buf, size_t n);
+ char* ret = (char*) strerror_r(errnum, buf, buflen);
+ if (((int)ret) == 0) {
+ // POSIX strerror_r, success
+ return buf;
+ } else if (((int)ret) == -1) {
+ // POSIX strerror_r, failure
+ // (Strictly, POSIX only guarantees a value other than 0. The safest
+ // way to implement this function is to use C++ and overload on the
+ // type of strerror_r to accurately distinguish GNU from POSIX. But
+ // realistic implementations will always return -1.)
+ snprintf(buf, buflen, "errno %d", errnum);
+ return buf;
+ } else {
+ // glibc strerror_r returning a string
+ return ret;
+ }
+}
+
+static struct CachedFields {
+ jclass fileDescriptorClass;
+ jmethodID fileDescriptorCtor;
+ jfieldID descriptorField;
+} gCachedFields;
+
+int registerJniHelp(JNIEnv* env) {
+ gCachedFields.fileDescriptorClass =
+ reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/io/FileDescriptor")));
+ if (gCachedFields.fileDescriptorClass == NULL) {
+ return -1;
+ }
+
+ gCachedFields.fileDescriptorCtor =
+ env->GetMethodID(gCachedFields.fileDescriptorClass, "<init>", "()V");
+ if (gCachedFields.fileDescriptorCtor == NULL) {
+ return -1;
+ }
+
+ gCachedFields.descriptorField =
+ env->GetFieldID(gCachedFields.fileDescriptorClass, "descriptor", "I");
+ if (gCachedFields.descriptorField == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+ jobject fileDescriptor = (*env)->NewObject(e,
+ gCachedFields.fileDescriptorClass, gCachedFields.fileDescriptorCtor);
+ jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
+ return fileDescriptor;
+}
+
+int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+ return (*env)->GetIntField(e, fileDescriptor, gCachedFields.descriptorField);
+}
+
+void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+ (*env)->SetIntField(e, fileDescriptor, gCachedFields.descriptorField, value);
+}
+
+/*
+ * DO NOT USE THIS FUNCTION
+ *
+ * Get a pointer to the elements of a non-movable array.
+ *
+ * The semantics are similar to GetDirectBufferAddress. Specifically, the VM
+ * guarantees that the array will not move, and the caller must ensure that
+ * it does not continue to use the pointer after the object is collected.
+ *
+ * We currently use an illegal sequence that trips up CheckJNI when
+ * the "forcecopy" mode is enabled. We pass in a magic value to work
+ * around the problem.
+ *
+ * Returns NULL if the array is movable.
+ */
+#define kNoCopyMagic 0xd5aab57f /* also in CheckJni.c */
+extern "C" jbyte* jniGetNonMovableArrayElements(C_JNIEnv* env, jarray arrayObj) {
+ JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+
+ jbyteArray byteArray = reinterpret_cast<jbyteArray>(arrayObj);
+
+ /*
+ * Normally the "isCopy" parameter is for a return value only, so the
+ * non-CheckJNI VM will ignore whatever we pass in.
+ */
+ uint32_t noCopy = kNoCopyMagic;
+ jbyte* result = (*env)->GetByteArrayElements(e, byteArray, reinterpret_cast<jboolean*>(&noCopy));
+
+ /*
+ * The non-CheckJNI implementation only cares about the array object,
+ * so we can replace the element pointer with the magic value.
+ */
+ (*env)->ReleaseByteArrayElements(e, byteArray, reinterpret_cast<jbyte*>(kNoCopyMagic), 0);
+ return result;
+}
diff --git a/libnativehelper/Register.c b/libnativehelper/Register.cpp
similarity index 92%
rename from libnativehelper/Register.c
rename to libnativehelper/Register.cpp
index 5d7d690..b6b1b1f 100644
--- a/libnativehelper/Register.c
+++ b/libnativehelper/Register.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-/*
- * JNI helper functions.
- */
-
#include "jni.h"
extern int registerCoreLibrariesJni(JNIEnv* env);
@@ -26,8 +22,7 @@
/*
* Register all methods for system classes.
*/
-int jniRegisterSystemMethods(JNIEnv* env)
-{
+int jniRegisterSystemMethods(JNIEnv* env) {
// JniHelp depends on core library classes such as java.io.FileDescriptor.
return registerCoreLibrariesJni(env) != -1 && registerJniHelp(env) != -1;
}
diff --git a/libnativehelper/include/nativehelper/JNIHelp.h b/libnativehelper/include/nativehelper/JNIHelp.h
index 1b5ff0c..ff9cf86 100644
--- a/libnativehelper/include/nativehelper/JNIHelp.h
+++ b/libnativehelper/include/nativehelper/JNIHelp.h
@@ -37,17 +37,21 @@
/*
* Register one or more native methods with a particular class.
+ * "className" looks like "java/lang/String".
*/
-int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
- const JNINativeMethod* gMethods, int numMethods);
+int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods);
/*
* Throw an exception with the specified class and an optional message.
+ *
* The "className" argument will be passed directly to FindClass, which
* takes strings with slashes (e.g. "java/lang/Object").
*
+ * If an exception is currently pending, we log a warning message and
+ * clear it.
+ *
* Returns 0 on success, nonzero if something failed (e.g. the exception
- * class couldn't be found).
+ * class couldn't be found, so *an* exception will still be pending).
*
* Currently aborts the VM if it can't throw the exception.
*/
@@ -77,17 +81,17 @@
const char* jniStrError(int errnum, char* buf, size_t buflen);
/*
- * Create a java.io.FileDescriptor given an integer fd
+ * Returns a new java.io.FileDescriptor for the given int fd.
*/
jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd);
/*
- * Get an int file descriptor from a java.io.FileDescriptor
+ * Returns the int fd from a java.io.FileDescriptor.
*/
int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor);
/*
- * Set an int file descriptor to a java.io.FileDescriptor
+ * Sets the int fd in a java.io.FileDescriptor.
*/
void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
@@ -107,62 +111,52 @@
* inlines these, even on non-optimized builds.
*/
#if defined(__cplusplus)
-inline int jniRegisterNativeMethods(JNIEnv* env, const char* className,
- const JNINativeMethod* gMethods, int numMethods)
-{
- return jniRegisterNativeMethods(&env->functions, className, gMethods,
- numMethods);
+inline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) {
+ return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods);
}
-inline int jniThrowException(JNIEnv* env, const char* className,
- const char* msg)
-{
+
+inline int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
return jniThrowException(&env->functions, className, msg);
}
-extern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className,
- const char* fmt, va_list args);
+extern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args);
/*
* Equivalent to jniThrowException but with a printf-like format string and
* variable-length argument list. This is only available in C++.
*/
-inline int jniThrowExceptionFmt(JNIEnv* env, const char* className,
- const char* fmt, ...)
-{
+inline int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
return jniThrowExceptionFmt(&env->functions, className, fmt, args);
va_end(args);
}
-inline int jniThrowNullPointerException(JNIEnv* env, const char* msg)
-{
+inline int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
return jniThrowNullPointerException(&env->functions, msg);
}
-inline int jniThrowRuntimeException(JNIEnv* env, const char* msg)
-{
+
+inline int jniThrowRuntimeException(JNIEnv* env, const char* msg) {
return jniThrowRuntimeException(&env->functions, msg);
}
-inline int jniThrowIOException(JNIEnv* env, int errnum)
-{
+
+inline int jniThrowIOException(JNIEnv* env, int errnum) {
return jniThrowIOException(&env->functions, errnum);
}
-inline jobject jniCreateFileDescriptor(JNIEnv* env, int fd)
-{
+
+inline jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
return jniCreateFileDescriptor(&env->functions, fd);
}
-inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor)
-{
+
+inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor);
}
-inline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor,
- int value)
-{
+
+inline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value);
}
-inline void jniLogException(JNIEnv* env, int priority, const char* tag,
- jthrowable exception = NULL)
-{
+
+inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
jniLogException(&env->functions, priority, tag, exception);
}
#endif
diff --git a/opcode-gen/regen-all b/opcode-gen/regen-all
index afe6624..161cda9 100755
--- a/opcode-gen/regen-all
+++ b/opcode-gen/regen-all
@@ -38,9 +38,9 @@
${progdir}/opcode-gen dx/src/com/android/dx/dex/code/RopToDop.java
${progdir}/opcode-gen dx/src/com/android/dx/io/OpcodeInfo.java
${progdir}/opcode-gen dx/src/com/android/dx/io/Opcodes.java
-${progdir}/opcode-gen libdex/DexOpcodes.c
+${progdir}/opcode-gen libdex/DexOpcodes.cpp
${progdir}/opcode-gen libdex/DexOpcodes.h
-${progdir}/opcode-gen libdex/InstrUtils.c
+${progdir}/opcode-gen libdex/InstrUtils.cpp
# It's a minor shame that these files live in a different top-level project.
# So it goes.
diff --git a/tests/055-enum-performance/expected.txt b/tests/055-enum-performance/expected.txt
index d81c194..ceb6bc4 100644
--- a/tests/055-enum-performance/expected.txt
+++ b/tests/055-enum-performance/expected.txt
@@ -5,7 +5,7 @@
FIVE
TWELVE
SamePackagePublicEnum
-basis: performed 40000 iterations
+basis: performed 10000 iterations
test1: performed 10000 iterations
test2: performed 10000 iterations
test3: performed 10000 iterations
diff --git a/tests/055-enum-performance/src/Main.java b/tests/055-enum-performance/src/Main.java
index 64d03eb..43f45f1 100644
--- a/tests/055-enum-performance/src/Main.java
+++ b/tests/055-enum-performance/src/Main.java
@@ -19,7 +19,7 @@
long time2 = System.nanoTime();
int count3 = test3(500);
long time3 = System.nanoTime();
- int count4 = basis(2000);
+ int count4 = basis(500);
long time4 = System.nanoTime();
System.out.println("basis: performed " + count4 + " iterations");
@@ -33,7 +33,7 @@
double basisMsec = (time4 - time3) / (double) count4 / 1000000;
double avg = (msec1 + msec2 + msec3) / 3;
- if (avg < (basisMsec * 25)) {
+ if (avg < (basisMsec * 10)) {
System.out.println("Timing is acceptable.");
} else {
System.out.println("Iterations are taking too long!");
@@ -67,50 +67,46 @@
System.out.println(Enum.valueOf(c, "ZERO").getClass().getName());
}
+ static final String[] BASIS_COMPARE_ARRAY = {
+ "ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT",
+ "NINE", "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN",
+ "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"
+ };
+
static public int basis(int iters) {
- /*
- * The basis time is the time taken to call a static method
- * passing two arguments, which in turn accesses a static
- * variable, compares a string, and does a little trivial math
- * and a trivial comparison. (That is, this is a mini
- * "omnibus" performance metric.) This is clearly going to be
- * much faster than Enum.valueOf(), which is why we multiply
- * the time before testing.
- */
for (int i = iters; i > 0; i--) {
- basisCall(i, "aname");
- basisCall(i, "bname");
- basisCall(i, "cname");
- basisCall(i, "dname");
- basisCall(i, "ename");
- basisCall(i, "fname");
- basisCall(i, "gname");
- basisCall(i, "hname");
- basisCall(i, "iname");
- basisCall(i, "jname");
- basisCall(i, "kname");
- basisCall(i, "lname");
- basisCall(i, "mname");
- basisCall(i, "nname");
- basisCall(i, "oname");
- basisCall(i, "pname");
- basisCall(i, "qname");
- basisCall(i, "rname");
- basisCall(i, "sname");
- basisCall(i, "tname");
+ basisValueOf("ZERO");
+ basisValueOf("ONE");
+ basisValueOf("TWO");
+ basisValueOf("THREE");
+ basisValueOf("FOUR");
+ basisValueOf("FIVE");
+ basisValueOf("SIX");
+ basisValueOf("SEVEN");
+ basisValueOf("EIGHT");
+ basisValueOf("NINE");
+ basisValueOf("TEN");
+ basisValueOf("ELEVEN");
+ basisValueOf("TWELVE");
+ basisValueOf("THIRTEEN");
+ basisValueOf("FOURTEEN");
+ basisValueOf("FIFTEEN");
+ basisValueOf("SIXTEEN");
+ basisValueOf("SEVENTEEN");
+ basisValueOf("EIGHTEEN");
+ basisValueOf("NINETEEN");
}
return iters * 20;
}
- static public int basisCall(int i, String name) {
- int compare = name.compareTo("fuzzbot");
-
- if (i < (basisTestValue * compare)) {
- return basisTestValue;
- } else {
- return i;
+ static String basisValueOf(String key) {
+ for (String s : BASIS_COMPARE_ARRAY) {
+ if (s.equals(key)) {
+ return s;
+ }
}
+ throw new IllegalArgumentException();
}
static public int test1(int iters) {
diff --git a/vm/AllocTracker.c b/vm/AllocTracker.cpp
similarity index 96%
rename from vm/AllocTracker.c
rename to vm/AllocTracker.cpp
index 8e2c325..34e0b3f 100644
--- a/vm/AllocTracker.c
+++ b/vm/AllocTracker.cpp
@@ -73,7 +73,7 @@
* Initialize a few things. This gets called early, so keep activity to
* a minimum.
*/
-bool dvmAllocTrackerStartup(void)
+bool dvmAllocTrackerStartup()
{
/* prep locks */
dvmInitMutex(&gDvm.allocTrackerLock);
@@ -87,7 +87,7 @@
/*
* Release anything we're holding on to.
*/
-void dvmAllocTrackerShutdown(void)
+void dvmAllocTrackerShutdown()
{
free(gDvm.allocRecords);
dvmDestroyMutex(&gDvm.allocTrackerLock);
@@ -105,7 +105,7 @@
*
* Returns "true" on success.
*/
-bool dvmEnableAllocTracker(void)
+bool dvmEnableAllocTracker()
{
bool result = true;
dvmLockMutex(&gDvm.allocTrackerLock);
@@ -129,7 +129,7 @@
/*
* Disable allocation tracking. Does nothing if tracking is not enabled.
*/
-void dvmDisableAllocTracker(void)
+void dvmDisableAllocTracker()
{
dvmLockMutex(&gDvm.allocTrackerLock);
@@ -149,7 +149,7 @@
int stackDepth = 0;
void* fp;
- fp = self->curFrame;
+ fp = self->interpSave.curFrame;
while ((fp != NULL) && (stackDepth < kMaxAllocRecordStackDepth)) {
const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
@@ -184,16 +184,18 @@
/*
* Add a new allocation to the set.
*/
-void dvmDoTrackAllocation(ClassObject* clazz, int size)
+void dvmDoTrackAllocation(ClassObject* clazz, size_t size)
{
- dvmLockMutex(&gDvm.allocTrackerLock);
- if (gDvm.allocRecords == NULL)
- goto bail;
-
Thread* self = dvmThreadSelf();
if (self == NULL) {
LOGW("alloc tracker: no thread\n");
- goto bail;
+ return;
+ }
+
+ dvmLockMutex(&gDvm.allocTrackerLock);
+ if (gDvm.allocRecords == NULL) {
+ dvmUnlockMutex(&gDvm.allocTrackerLock);
+ return;
}
/* advance and clip */
@@ -210,7 +212,6 @@
if (gDvm.allocRecordCount < kNumAllocRecords)
gDvm.allocRecordCount++;
-bail:
dvmUnlockMutex(&gDvm.allocTrackerLock);
}
@@ -277,7 +278,7 @@
* We need to handle underflow in our circular buffer, so we add
* kNumAllocRecords and then mask it back down.
*/
-inline static int headIndex(void)
+inline static int headIndex()
{
return (gDvm.allocRecordHead+1 + kNumAllocRecords - gDvm.allocRecordCount)
& (kNumAllocRecords-1);
@@ -600,8 +601,10 @@
dvmEnableAllocTracker();
dvmLockMutex(&gDvm.allocTrackerLock);
- if (gDvm.allocRecords == NULL)
- goto bail;
+ if (gDvm.allocRecords == NULL) {
+ dvmUnlockMutex(&gDvm.allocTrackerLock);
+ return;
+ }
/*
* "idx" is the head of the list. We want to start at the end of the
@@ -618,8 +621,7 @@
pRec->threadId, pRec->size, pRec->clazz->descriptor);
if (true) {
- int i;
- for (i = 0; i < kMaxAllocRecordStackDepth; i++) {
+ for (int i = 0; i < kMaxAllocRecordStackDepth; i++) {
if (pRec->stackElem[i].method == NULL)
break;
@@ -642,7 +644,6 @@
idx = (idx + 1) & (kNumAllocRecords-1);
}
-bail:
dvmUnlockMutex(&gDvm.allocTrackerLock);
if (false) {
u1* data;
diff --git a/vm/AllocTracker.h b/vm/AllocTracker.h
index 84ac9b8..16d5168 100644
--- a/vm/AllocTracker.h
+++ b/vm/AllocTracker.h
@@ -24,7 +24,6 @@
void dvmAllocTrackerShutdown(void);
struct AllocRecord;
-typedef struct AllocRecord AllocRecord;
/*
* Enable allocation tracking. Does nothing if tracking is already enabled.
@@ -44,7 +43,7 @@
if (gDvm.allocRecords != NULL) \
dvmDoTrackAllocation(_clazz, _size); \
}
-void dvmDoTrackAllocation(ClassObject* clazz, int size);
+void dvmDoTrackAllocation(ClassObject* clazz, size_t size);
/*
* Generate a DDM packet with all of the tracked allocation data.
diff --git a/vm/Atomic.c b/vm/Atomic.cpp
similarity index 100%
rename from vm/Atomic.c
rename to vm/Atomic.cpp
diff --git a/vm/Atomic.h b/vm/Atomic.h
index 6c3a66f..9d43332 100644
--- a/vm/Atomic.h
+++ b/vm/Atomic.h
@@ -38,12 +38,12 @@
* Swap the 64-bit value at "addr" with "value". Returns the previous
* value.
*/
-int64_t dvmQuasiAtomicSwap64(int64_t value, volatile int64_t* addr);
+extern "C" int64_t dvmQuasiAtomicSwap64(int64_t value, volatile int64_t* addr);
/*
* Read the 64-bit value at "addr".
*/
-int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr);
+extern "C" int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr);
/*
* If the value at "addr" is equal to "oldvalue", replace it with "newvalue"
diff --git a/vm/AtomicCache.c b/vm/AtomicCache.cpp
similarity index 100%
rename from vm/AtomicCache.c
rename to vm/AtomicCache.cpp
diff --git a/vm/AtomicCache.h b/vm/AtomicCache.h
index 686eac5..29f1ebc 100644
--- a/vm/AtomicCache.h
+++ b/vm/AtomicCache.h
@@ -31,12 +31,12 @@
*
* Must be exactly 16 bytes.
*/
-typedef struct AtomicCacheEntry {
+struct AtomicCacheEntry {
u4 key1;
u4 key2;
u4 value;
volatile u4 version; /* version and lock flag */
-} AtomicCacheEntry;
+};
/*
* One cache.
@@ -45,7 +45,7 @@
* struct and "entries" separately, avoiding an indirection. (We already
* handle "numEntries" separately in ATOMIC_CACHE_LOOKUP.)
*/
-typedef struct AtomicCache {
+struct AtomicCache {
AtomicCacheEntry* entries; /* array of entries */
int numEntries; /* #of entries, must be power of 2 */
@@ -57,7 +57,7 @@
int hits; /* found entry in cache */
int misses; /* entry was for other keys */
int fills; /* entry was empty */
-} AtomicCache;
+};
/*
* Do a cache lookup. We need to be able to read and write entries
diff --git a/vm/BitVector.c b/vm/BitVector.cpp
similarity index 100%
rename from vm/BitVector.c
rename to vm/BitVector.cpp
diff --git a/vm/BitVector.h b/vm/BitVector.h
index d1a0ca3..01e2f1b 100644
--- a/vm/BitVector.h
+++ b/vm/BitVector.h
@@ -26,18 +26,18 @@
*
* All operations on a BitVector are unsynchronized.
*/
-typedef struct BitVector {
+struct BitVector {
bool expandable; /* expand bitmap if we run out? */
u4 storageSize; /* current size, in 32-bit words */
u4* storage;
-} BitVector;
+};
/* Handy iterator to walk through the bit positions set to 1 */
-typedef struct BitVectorIterator {
+struct BitVectorIterator {
BitVector *pBits;
u4 idx;
u4 bitSize;
-} BitVectorIterator;
+};
/* allocate a bit vector with enough space to hold "startBits" bits */
BitVector* dvmAllocBitVector(unsigned int startBits, bool expandable);
diff --git a/vm/CheckJni.c b/vm/CheckJni.c
deleted file mode 100644
index 17c76c8..0000000
--- a/vm/CheckJni.c
+++ /dev/null
@@ -1,2666 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/*
- * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
- *
- * We want to verify types, make sure class and field IDs are valid, and
- * ensure that JNI's semantic expectations are being met. JNI seems to
- * be relatively lax when it comes to requirements for permission checks,
- * e.g. access to private methods is generally allowed from anywhere.
- *
- * TODO: keep a counter on global Get/Release. Report a warning if some Gets
- * were not Released. Do not count explicit Add/DeleteGlobalRef calls (or
- * count them separately, so we can complain if they exceed a certain
- * threshold).
- *
- * TODO: verify that the methodID passed into the Call functions is for
- * a method in the specified class.
- */
-#include "Dalvik.h"
-#include "JniInternal.h"
-
-#include <zlib.h>
-
-#define kUnknownFuncName " -" /* can pass to showLocation() */
-
-static void showLocation(const char* func);
-static void abortMaybe(void);
-
-
-/*
- * ===========================================================================
- * JNI call bridge wrapper
- * ===========================================================================
- */
-
-/*
- * Check the result of a native method call that returns an object reference.
- *
- * The primary goal here is to verify that native code is returning the
- * correct type of object. If it's declared to return a String but actually
- * returns a byte array, things will fail in strange ways later on.
- *
- * This can be a fairly expensive operation, since we have to look up the
- * return type class by name in method->clazz' class loader. We take a
- * shortcut here and allow the call to succeed if the descriptor strings
- * match. This will allow some false-positives when a class is redefined
- * by a class loader, but that's rare enough that it doesn't seem worth
- * testing for.
- *
- * At this point, pResult->l has already been converted to an object pointer.
- */
-static void checkCallResultCommon(const u4* args, const JValue* pResult,
- const Method* method, Thread* self)
-{
- assert(pResult->l != NULL);
- const Object* resultObj = (const Object*) pResult->l;
-
- if (resultObj == kInvalidIndirectRefObject) {
- LOGW("JNI WARNING: invalid reference returned from native code\n");
- showLocation(kUnknownFuncName);
- abortMaybe();
- return;
- }
-
- ClassObject* objClazz = resultObj->clazz;
-
- /*
- * Make sure that pResult->l is an instance of the type this
- * method was expected to return.
- */
- const char* declType = dexProtoGetReturnType(&method->prototype);
- const char* objType = objClazz->descriptor;
- if (strcmp(declType, objType) == 0) {
- /* names match; ignore class loader issues and allow it */
- LOGV("Check %s.%s: %s io %s (FAST-OK)",
- method->clazz->descriptor, method->name, objType, declType);
- } else {
- /*
- * Names didn't match. We need to resolve declType in the context
- * of method->clazz->classLoader, and compare the class objects
- * for equality.
- *
- * Since we're returning an instance of declType, it's safe to
- * assume that it has been loaded and initialized (or, for the case
- * of an array, generated). However, the current class loader may
- * not be listed as an initiating loader, so we can't just look for
- * it in the loaded-classes list.
- */
- ClassObject* declClazz;
-
- declClazz = dvmFindClassNoInit(declType, method->clazz->classLoader);
- if (declClazz == NULL) {
- LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
- declType, objType);
- LOGW(" failed in %s.%s ('%s' not found)",
- method->clazz->descriptor, method->name, declType);
- abortMaybe();
- return;
- }
- if (!dvmInstanceof(objClazz, declClazz)) {
- LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
- declType, objType);
- LOGW(" failed in %s.%s",
- method->clazz->descriptor, method->name);
- abortMaybe();
- return;
- } else {
- LOGV("Check %s.%s: %s io %s (SLOW-OK)",
- method->clazz->descriptor, method->name, objType, declType);
- }
- }
-}
-
-/*
- * Determine if we need to check the return type coming out of the call.
- *
- * (We don't simply do this at the top of checkCallResultCommon() because
- * this is on the critical path for native method calls.)
- */
-static inline bool callNeedsCheck(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
- pResult->l != NULL);
-}
-
-/*
- * Check a call into native code.
- */
-void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- dvmCallJNIMethod_general(args, pResult, method, self);
- if (callNeedsCheck(args, pResult, method, self))
- checkCallResultCommon(args, pResult, method, self);
-}
-
-/*
- * Check a synchronized call into native code.
- */
-void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- dvmCallJNIMethod_synchronized(args, pResult, method, self);
- if (callNeedsCheck(args, pResult, method, self))
- checkCallResultCommon(args, pResult, method, self);
-}
-
-/*
- * Check a virtual call with no reference arguments (other than "this").
- */
-void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
- if (callNeedsCheck(args, pResult, method, self))
- checkCallResultCommon(args, pResult, method, self);
-}
-
-/*
- * Check a static call with no reference arguments (other than "clazz").
- */
-void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
- if (callNeedsCheck(args, pResult, method, self))
- checkCallResultCommon(args, pResult, method, self);
-}
-
-
-/*
- * ===========================================================================
- * JNI function helpers
- * ===========================================================================
- */
-
-#define JNI_ENTER() dvmChangeStatus(NULL, THREAD_RUNNING)
-#define JNI_EXIT() dvmChangeStatus(NULL, THREAD_NATIVE)
-
-#define BASE_ENV(_env) (((JNIEnvExt*)_env)->baseFuncTable)
-#define BASE_VM(_vm) (((JavaVMExt*)_vm)->baseFuncTable)
-
-/*
- * Flags passed into checkThread().
- */
-#define kFlag_Default 0x0000
-
-#define kFlag_CritBad 0x0000 /* calling while in critical is bad */
-#define kFlag_CritOkay 0x0001 /* ...okay */
-#define kFlag_CritGet 0x0002 /* this is a critical "get" */
-#define kFlag_CritRelease 0x0003 /* this is a critical "release" */
-#define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
-
-#define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
-#define kFlag_ExcepOkay 0x0004 /* ...okay */
-
-/*
- * Enter/exit macros for JNI env "check" functions. These do not change
- * the thread state within the VM.
- */
-#define CHECK_ENTER(_env, _flags) \
- do { \
- JNI_TRACE(true, true); \
- checkThread(_env, _flags, __FUNCTION__); \
- } while(false)
-
-#define CHECK_EXIT(_env) \
- do { JNI_TRACE(false, true); } while(false)
-
-
-/*
- * Enter/exit macros for JNI invocation interface "check" functions. These
- * do not change the thread state within the VM.
- *
- * Set "_hasmeth" to true if we have a valid thread with a method pointer.
- * We won't have one before attaching a thread, after detaching a thread, or
- * after destroying the VM.
- */
-#define CHECK_VMENTER(_vm, _hasmeth) \
- do { JNI_TRACE(true, _hasmeth); } while(false)
-#define CHECK_VMEXIT(_vm, _hasmeth) \
- do { JNI_TRACE(false, _hasmeth); } while(false)
-
-#define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic) \
- checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
-#define CHECK_STATIC_FIELD_ID(_env, _clazz, _fieldid) \
- checkStaticFieldID(_env, _clazz, _fieldid, __FUNCTION__)
-#define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
- checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
-#define CHECK_CLASS(_env, _clazz) \
- checkInstance(_env, _clazz, gDvm.classJavaLangClass, "jclass", __FUNCTION__)
-#define CHECK_STRING(_env, _str) \
- checkInstance(_env, _str, gDvm.classJavaLangString, "jstring", __FUNCTION__)
-#define CHECK_UTF_STRING(_env, _str) \
- checkUtfString(_env, _str, #_str, __FUNCTION__)
-#define CHECK_NULLABLE_UTF_STRING(_env, _str) \
- checkUtfString(_env, _str, NULL, __FUNCTION__)
-#define CHECK_CLASS_NAME(_env, _str) \
- checkClassName(_env, _str, __FUNCTION__)
-#define CHECK_OBJECT(_env, _obj) \
- checkObject(_env, _obj, __FUNCTION__)
-#define CHECK_ARRAY(_env, _array) \
- checkArray(_env, _array, __FUNCTION__)
-#define CHECK_RELEASE_MODE(_env, _mode) \
- checkReleaseMode(_env, _mode, __FUNCTION__)
-#define CHECK_LENGTH_POSITIVE(_env, _length) \
- checkLengthPositive(_env, _length, __FUNCTION__)
-#define CHECK_NON_NULL(_env, _ptr) \
- checkNonNull(_env, _ptr, __FUNCTION__)
-#define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
- checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
-#define CHECK_VIRTUAL_METHOD(_env, _obj, _methid) \
- checkVirtualMethod(_env, _obj, _methid, __FUNCTION__)
-#define CHECK_STATIC_METHOD(_env, _clazz, _methid) \
- checkStaticMethod(_env, _clazz, _methid, __FUNCTION__)
-
-/*
- * Prints trace messages when a native method calls a JNI function such as
- * NewByteArray. Enabled if both "-Xcheck:jni" and "-verbose:jni" are enabled.
- */
-#define JNI_TRACE(_entry, _hasmeth) \
- do { \
- if (gDvm.verboseJni && (_entry)) { \
- static const char* classDescriptor = "???"; \
- static const char* methodName = "???"; \
- if (_hasmeth) { \
- const Method* meth = dvmGetCurrentJNIMethod(); \
- classDescriptor = meth->clazz->descriptor; \
- methodName = meth->name; \
- } \
- /* use +6 to drop the leading "Check_" */ \
- LOGI("JNI: %s (from %s.%s)", \
- (__FUNCTION__)+6, classDescriptor, methodName); \
- } \
- } while(false)
-
-/*
- * Log the current location.
- *
- * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
- */
-static void showLocation(const char* func)
-{
- const Method* meth = dvmGetCurrentJNIMethod();
- char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGW(" in %s.%s:%s (%s)",
- meth->clazz->descriptor, meth->name, desc, func + 6);
- free(desc);
-}
-
-/*
- * Abort if we are configured to bail out on JNI warnings.
- */
-static void abortMaybe(void)
-{
- JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
- if (vm->warnError) {
- dvmDumpThread(dvmThreadSelf(), false);
- dvmAbort();
- }
-}
-
-/*
- * Verify that the current thread is (a) attached and (b) associated with
- * this particular instance of JNIEnv.
- *
- * Verify that, if this thread previously made a critical "get" call, we
- * do the corresponding "release" call before we try anything else.
- *
- * Verify that, if an exception has been raised, the native code doesn't
- * make any JNI calls other than the Exception* methods.
- *
- * TODO? if we add support for non-JNI native calls, make sure that the
- * method at the top of the interpreted stack is a JNI method call. (Or
- * set a flag in the Thread/JNIEnv when the call is made and clear it on
- * return?)
- *
- * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
- */
-static void checkThread(JNIEnv* env, int flags, const char* func)
-{
- JNIEnvExt* threadEnv;
- bool printWarn = false;
- bool printException = false;
-
- /* get the *correct* JNIEnv by going through our TLS pointer */
- threadEnv = dvmGetJNIEnvForThread();
-
- /*
- * Verify that the JNIEnv we've been handed matches what we expected
- * to receive.
- */
- if (threadEnv == NULL) {
- LOGE("JNI ERROR: non-VM thread making JNI calls");
- // don't set printWarn -- it'll try to call showLocation()
- dvmAbort();
- } else if ((JNIEnvExt*) env != threadEnv) {
- if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
- LOGE("JNI: threadEnv != thread->env?");
- dvmAbort();
- }
-
- LOGW("JNI WARNING: threadid=%d using env from threadid=%d",
- threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
- printWarn = true;
-
- /* this is a bad idea -- need to throw as we exit, or abort func */
- //dvmThrowRuntimeException("invalid use of JNI env ptr");
- } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
- /* correct JNIEnv*; make sure the "self" pointer is correct */
- LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)",
- ((JNIEnvExt*) env)->self, dvmThreadSelf());
- dvmAbort();
- }
-
- /*
- * Check for critical resource misuse.
- */
- switch (flags & kFlag_CritMask) {
- case kFlag_CritOkay: // okay to call this method
- break;
- case kFlag_CritBad: // not okay to call
- if (threadEnv->critical) {
- LOGW("JNI WARNING: threadid=%d using JNI after critical get",
- threadEnv->envThreadId);
- printWarn = true;
- }
- break;
- case kFlag_CritGet: // this is a "get" call
- /* don't check here; we allow nested gets */
- threadEnv->critical++;
- break;
- case kFlag_CritRelease: // this is a "release" call
- threadEnv->critical--;
- if (threadEnv->critical < 0) {
- LOGW("JNI WARNING: threadid=%d called too many crit releases",
- threadEnv->envThreadId);
- printWarn = true;
- }
- break;
- default:
- assert(false);
- }
-
- /*
- * Check for raised exceptions.
- */
- if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
- LOGW("JNI WARNING: JNI method called with exception raised");
- printWarn = true;
- printException = true;
- }
-
- if (printWarn)
- showLocation(func);
- if (printException) {
- LOGW("Pending exception is:");
- dvmLogExceptionStackTrace();
- }
- if (printWarn)
- abortMaybe();
-}
-
-/*
- * Get a human-oriented name for a given primitive type.
- */
-static const char* primitiveTypeToName(PrimitiveType primType) {
- switch (primType) {
- case PRIM_VOID: return "void";
- case PRIM_BOOLEAN: return "boolean";
- case PRIM_BYTE: return "byte";
- case PRIM_SHORT: return "short";
- case PRIM_CHAR: return "char";
- case PRIM_INT: return "int";
- case PRIM_LONG: return "long";
- case PRIM_FLOAT: return "float";
- case PRIM_DOUBLE: return "double";
- case PRIM_NOT: return "Object/Array";
- default: return "???";
- }
-}
-
-/*
- * Verify that the field is of the appropriate type. If the field has an
- * object type, "jobj" is the object we're trying to assign into it.
- *
- * Works for both static and instance fields.
- */
-static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
- PrimitiveType prim, bool isStatic, const char* func)
-{
- Field* field = (Field*) fieldID;
- bool printWarn = false;
-
- if (fieldID == NULL) {
- LOGW("JNI WARNING: null field ID");
- showLocation(func);
- abortMaybe();
- }
-
- if ((field->signature[0] == 'L' || field->signature[0] == '[') &&
- jobj != NULL)
- {
- JNI_ENTER();
- Object* obj = dvmDecodeIndirectRef(env, jobj);
- /*
- * If jobj is a weak global ref whose referent has been cleared,
- * obj will be NULL. Otherwise, obj should always be non-NULL
- * and valid.
- */
- if (obj != NULL && !dvmIsValidObject(obj)) {
- LOGW("JNI WARNING: field operation on invalid %s ref (%p)\n",
- dvmIndirectRefTypeName(jobj), jobj);
- printWarn = true;
- } else {
- ClassObject* fieldClass =
- dvmFindLoadedClass(field->signature);
- ClassObject* objClass = obj->clazz;
-
- assert(fieldClass != NULL);
- assert(objClass != NULL);
-
- if (!dvmInstanceof(objClass, fieldClass)) {
- LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
- field->name, field->signature, objClass->descriptor);
- printWarn = true;
- }
- }
- JNI_EXIT();
- } else if (dexGetPrimitiveTypeFromDescriptorChar(field->signature[0]) != prim) {
- LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
- field->name, field->signature, primitiveTypeToName(prim));
- printWarn = true;
- } else if (isStatic && !dvmIsStaticField(field)) {
- if (isStatic)
- LOGW("JNI WARNING: accessing non-static field %s as static",
- field->name);
- else
- LOGW("JNI WARNING: accessing static field %s as non-static",
- field->name);
- printWarn = true;
- }
-
- if (printWarn) {
- showLocation(func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that "jobj" is a valid object, and that it's an object that JNI
- * is allowed to know about. We allow NULL references.
- *
- * Switches to "running" mode before performing checks.
- */
-static void checkObject(JNIEnv* env, jobject jobj, const char* func)
-{
- bool printWarn = false;
-
- if (jobj == NULL)
- return;
-
- JNI_ENTER();
-
- if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
- LOGW("JNI WARNING: %p is not a valid JNI reference (type=%s)",
- jobj, dvmIndirectRefTypeName(jobj));
- printWarn = true;
- } else {
- Object* obj = dvmDecodeIndirectRef(env, jobj);
-
- /*
- * The decoded object will be NULL if this is a weak global ref
- * with a cleared referent.
- */
- if (obj == kInvalidIndirectRefObject ||
- (obj != NULL && !dvmIsValidObject(obj)))
- {
- LOGW("JNI WARNING: native code passing in bad object %p %p",
- jobj, obj);
- printWarn = true;
- }
- }
-
- if (printWarn) {
- showLocation(func);
- abortMaybe();
- }
- JNI_EXIT();
-}
-
-/*
- * Verify that "jobj" is a valid non-NULL object reference, and points to
- * an instance of expectedClass.
- *
- * Because we're looking at an object on the GC heap, we have to switch
- * to "running" mode before doing the checks.
- */
-static void checkInstance(JNIEnv* env, jobject jobj,
- ClassObject* expectedClass, const char* argName, const char* func)
-{
- if (jobj == NULL) {
- LOGW("JNI WARNING: received null %s", argName);
- showLocation(func);
- abortMaybe();
- return;
- }
-
- JNI_ENTER();
- bool printWarn = false;
-
- Object* obj = dvmDecodeIndirectRef(env, jobj);
-
- if (!dvmIsValidObject(obj)) {
- LOGW("JNI WARNING: %s is invalid %s ref (%p)", argName,
- dvmIndirectRefTypeName(jobj), jobj);
- printWarn = true;
- } else if (obj->clazz != expectedClass) {
- LOGW("JNI WARNING: %s arg has wrong type (expected %s, got %s)",
- argName, expectedClass->descriptor, obj->clazz->descriptor);
- printWarn = true;
- }
- JNI_EXIT();
-
- if (printWarn) {
- showLocation(func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that "bytes" points to valid "modified UTF-8" data.
- * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise,
- * "identifier" is the name to use when reporting the null pointer.
- */
-static void checkUtfString(JNIEnv* env, const char* bytes,
- const char* identifier, const char* func)
-{
- const char* origBytes = bytes;
-
- if (bytes == NULL) {
- if (identifier != NULL) {
- LOGW("JNI WARNING: %s == NULL", identifier);
- goto fail;
- }
-
- return;
- }
-
- const char* errorKind = NULL;
- u1 utf8;
- while (*bytes != '\0') {
- utf8 = *(bytes++);
- // Switch on the high four bits.
- switch (utf8 >> 4) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07: {
- // Bit pattern 0xxx. No need for any extra bytes.
- break;
- }
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0f: {
- /*
- * Bit pattern 10xx or 1111, which are illegal start bytes.
- * Note: 1111 is valid for normal UTF-8, but not the
- * modified UTF-8 used here.
- */
- errorKind = "start";
- goto fail_with_string;
- }
- case 0x0e: {
- // Bit pattern 1110, so there are two additional bytes.
- utf8 = *(bytes++);
- if ((utf8 & 0xc0) != 0x80) {
- errorKind = "continuation";
- goto fail_with_string;
- }
- // Fall through to take care of the final byte.
- }
- case 0x0c:
- case 0x0d: {
- // Bit pattern 110x, so there is one additional byte.
- utf8 = *(bytes++);
- if ((utf8 & 0xc0) != 0x80) {
- errorKind = "continuation";
- goto fail_with_string;
- }
- break;
- }
- }
- }
-
- return;
-
-fail_with_string:
- LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte 0x%x",
- errorKind, utf8);
- LOGW(" string: '%s'", origBytes);
-fail:
- showLocation(func);
- abortMaybe();
-}
-
-/*
- * In some circumstances the VM will screen class names, but it doesn't
- * for class lookup. When things get bounced through a class loader, they
- * can actually get normalized a couple of times; as a result, passing in
- * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
- * work in some circumstances.
- *
- * This is incorrect and could cause strange behavior or compatibility
- * problems, so we want to screen that out here.
- *
- * We expect "full-qualified" class names, like "java/lang/Thread" or
- * "[Ljava/lang/Object;".
- */
-static void checkClassName(JNIEnv* env, const char* className, const char* func)
-{
- if (!dexIsValidClassName(className, false)) {
- LOGW("JNI WARNING: illegal class name '%s' (%s)", className, func);
- LOGW(" (should be formed like 'dalvik/system/DexFile')");
- LOGW(" or '[Ldalvik/system/DexFile;' or '[[B')");
- abortMaybe();
- }
-}
-
-/*
- * Verify that "array" is non-NULL and points to an Array object.
- *
- * Since we're dealing with objects, switch to "running" mode.
- */
-static void checkArray(JNIEnv* env, jarray jarr, const char* func)
-{
- if (jarr == NULL) {
- LOGW("JNI WARNING: received null array");
- showLocation(func);
- abortMaybe();
- return;
- }
-
- JNI_ENTER();
- bool printWarn = false;
-
- Object* obj = dvmDecodeIndirectRef(env, jarr);
-
- if (!dvmIsValidObject(obj)) {
- LOGW("JNI WARNING: jarray is invalid %s ref (%p)",
- dvmIndirectRefTypeName(jarr), jarr);
- printWarn = true;
- } else if (obj->clazz->descriptor[0] != '[') {
- LOGW("JNI WARNING: jarray arg has wrong type (expected array, got %s)",
- obj->clazz->descriptor);
- printWarn = true;
- }
-
- JNI_EXIT();
-
- if (printWarn) {
- showLocation(func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that the "mode" argument passed to a primitive array Release
- * function is one of the valid values.
- */
-static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
-{
- if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
- LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that the length argument to array-creation calls is >= 0.
- */
-static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
-{
- if (length < 0) {
- LOGW("JNI WARNING: negative length for array allocation (%s)", func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that the pointer value is non-NULL.
- */
-static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
-{
- if (ptr == NULL) {
- LOGW("JNI WARNING: invalid null pointer (%s)", func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that the method's return type matches the type of call.
- *
- * "expectedSigByte" will be 'L' for all objects, including arrays.
- */
-static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
- bool isStatic, const char* func)
-{
- const Method* meth = (const Method*) methodID;
- bool printWarn = false;
-
- if (expectedSigByte != meth->shorty[0]) {
- LOGW("JNI WARNING: expected return type '%c'", expectedSigByte);
- printWarn = true;
- } else if (isStatic && !dvmIsStaticMethod(meth)) {
- if (isStatic)
- LOGW("JNI WARNING: calling non-static method with static call");
- else
- LOGW("JNI WARNING: calling static method with non-static call");
- printWarn = true;
- }
-
- if (printWarn) {
- char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGW(" calling %s.%s %s",
- meth->clazz->descriptor, meth->name, desc);
- free(desc);
- showLocation(func);
- abortMaybe();
- }
-}
-
-/*
- * Verify that this static field ID is valid for this class.
- *
- * Assumes "jclazz" has already been validated.
- */
-static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID,
- const char* func)
-{
- JNI_ENTER();
- ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- StaticField* base = &clazz->sfields[0];
- int fieldCount = clazz->sfieldCount;
-
- if ((StaticField*) fieldID < base ||
- (StaticField*) fieldID >= base + fieldCount)
- {
- LOGW("JNI WARNING: static fieldID %p not valid for class %s",
- fieldID, clazz->descriptor);
- LOGW(" base=%p count=%d", base, fieldCount);
- showLocation(func);
- abortMaybe();
- }
- JNI_EXIT();
-}
-
-/*
- * Verify that this instance field ID is valid for this object.
- *
- * Assumes "jobj" has already been validated.
- */
-static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
- const char* func)
-{
- JNI_ENTER();
-
- Object* obj = dvmDecodeIndirectRef(env, jobj);
- ClassObject* clazz = obj->clazz;
-
- /*
- * Check this class and all of its superclasses for a matching field.
- * Don't need to scan interfaces.
- */
- while (clazz != NULL) {
- if ((InstField*) fieldID >= clazz->ifields &&
- (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
- {
- goto bail;
- }
-
- clazz = clazz->super;
- }
-
- LOGW("JNI WARNING: inst fieldID %p not valid for class %s",
- fieldID, obj->clazz->descriptor);
- showLocation(func);
- abortMaybe();
-
-bail:
- JNI_EXIT();
-}
-
-/*
- * Verify that "methodID" is appropriate for "jobj".
- *
- * Make sure the object is an instance of the method's declaring class.
- * (Note the methodID might point to a declaration in an interface; this
- * will be handled automatically by the instanceof check.)
- */
-static void checkVirtualMethod(JNIEnv* env, jobject jobj, jmethodID methodID,
- const char* func)
-{
- JNI_ENTER();
-
- Object* obj = dvmDecodeIndirectRef(env, jobj);
- const Method* meth = (const Method*) methodID;
-
- if (!dvmInstanceof(obj->clazz, meth->clazz)) {
- LOGW("JNI WARNING: can't call %s.%s on instance of %s",
- meth->clazz->descriptor, meth->name, obj->clazz->descriptor);
- showLocation(func);
- abortMaybe();
- }
-
- JNI_EXIT();
-}
-
-/*
- * Verify that "methodID" is appropriate for "clazz".
- *
- * A mismatch isn't dangerous, because the jmethodID defines the class. In
- * fact, jclazz is unused in the implementation. It's best if we don't
- * allow bad code in the system though.
- *
- * Instances of "jclazz" must be instances of the method's declaring class.
- */
-static void checkStaticMethod(JNIEnv* env, jclass jclazz, jmethodID methodID,
- const char* func)
-{
- JNI_ENTER();
-
- ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- const Method* meth = (const Method*) methodID;
-
- if (!dvmInstanceof(clazz, meth->clazz)) {
- LOGW("JNI WARNING: can't call static %s.%s on class %s",
- meth->clazz->descriptor, meth->name, clazz->descriptor);
- showLocation(func);
- // no abort?
- }
-
- JNI_EXIT();
-}
-
-
-/*
- * ===========================================================================
- * Guarded arrays
- * ===========================================================================
- */
-
-#define kGuardLen 512 /* must be multiple of 2 */
-#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
-#define kGuardMagic 0xffd5aa96
-#define kGuardExtra sizeof(GuardExtra)
-
-/* this gets tucked in at the start of the buffer; struct size must be even */
-typedef struct GuardExtra {
- u4 magic;
- uLong adler;
- size_t originalLen;
- const void* originalPtr;
-} GuardExtra;
-
-/* find the GuardExtra given the pointer into the "live" data */
-inline static GuardExtra* getGuardExtra(const void* dataBuf)
-{
- u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
- return (GuardExtra*) fullBuf;
-}
-
-/*
- * Create an oversized buffer to hold the contents of "buf". Copy it in,
- * filling in the area around it with guard data.
- *
- * We use a 16-bit pattern to make a rogue memset less likely to elude us.
- */
-static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
-{
- GuardExtra* pExtra;
- size_t newLen = (len + kGuardLen +1) & ~0x01;
- u1* newBuf;
- u2* pat;
- int i;
-
- newBuf = (u1*)malloc(newLen);
- if (newBuf == NULL) {
- LOGE("createGuardedCopy failed on alloc of %d bytes", newLen);
- dvmAbort();
- }
-
- /* fill it in with a pattern */
- pat = (u2*) newBuf;
- for (i = 0; i < (int)newLen / 2; i++)
- *pat++ = kGuardPattern;
-
- /* copy the data in; note "len" could be zero */
- memcpy(newBuf + kGuardLen / 2, buf, len);
-
- /* if modification is not expected, grab a checksum */
- uLong adler = 0;
- if (!modOkay) {
- adler = adler32(0L, Z_NULL, 0);
- adler = adler32(adler, (const Bytef*)buf, len);
- *(uLong*)newBuf = adler;
- }
-
- pExtra = (GuardExtra*) newBuf;
- pExtra->magic = kGuardMagic;
- pExtra->adler = adler;
- pExtra->originalPtr = buf;
- pExtra->originalLen = len;
-
- return newBuf + kGuardLen / 2;
-}
-
-/*
- * Verify the guard area and, if "modOkay" is false, that the data itself
- * has not been altered.
- *
- * The caller has already checked that "dataBuf" is non-NULL.
- */
-static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
-{
- static const u4 kMagicCmp = kGuardMagic;
- const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
- const GuardExtra* pExtra = getGuardExtra(dataBuf);
- size_t len;
- const u2* pat;
- int i;
-
- /*
- * Before we do anything with "pExtra", check the magic number. We
- * do the check with memcmp rather than "==" in case the pointer is
- * unaligned. If it points to completely bogus memory we're going
- * to crash, but there's no easy way around that.
- */
- if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
- u1 buf[4];
- memcpy(buf, &pExtra->magic, 4);
- LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
- "-- incorrect data pointer %p?",
- buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
- return false;
- }
-
- len = pExtra->originalLen;
-
- /* check bottom half of guard; skip over optional checksum storage */
- pat = (u2*) fullBuf;
- for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
- {
- if (pat[i] != kGuardPattern) {
- LOGE("JNI: guard pattern(1) disturbed at %p + %d",
- fullBuf, i*2);
- return false;
- }
- }
-
- int offset = kGuardLen / 2 + len;
- if (offset & 0x01) {
- /* odd byte; expected value depends on endian-ness of host */
- const u2 patSample = kGuardPattern;
- if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
- LOGE("JNI: guard pattern disturbed in odd byte after %p "
- "(+%d) 0x%02x 0x%02x",
- fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
- return false;
- }
- offset++;
- }
-
- /* check top half of guard */
- pat = (u2*) (fullBuf + offset);
- for (i = 0; i < kGuardLen / 4; i++) {
- if (pat[i] != kGuardPattern) {
- LOGE("JNI: guard pattern(2) disturbed at %p + %d",
- fullBuf, offset + i*2);
- return false;
- }
- }
-
- /*
- * If modification is not expected, verify checksum. Strictly speaking
- * this is wrong: if we told the client that we made a copy, there's no
- * reason they can't alter the buffer.
- */
- if (!modOkay) {
- uLong adler = adler32(0L, Z_NULL, 0);
- adler = adler32(adler, (const Bytef*)dataBuf, len);
- if (pExtra->adler != adler) {
- LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p",
- pExtra->adler, adler, dataBuf);
- return false;
- }
- }
-
- return true;
-}
-
-/*
- * Free up the guard buffer, scrub it, and return the original pointer.
- */
-static void* freeGuardedCopy(void* dataBuf)
-{
- u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
- const GuardExtra* pExtra = getGuardExtra(dataBuf);
- void* originalPtr = (void*) pExtra->originalPtr;
- size_t len = pExtra->originalLen;
-
- memset(dataBuf, 0xdd, len);
- free(fullBuf);
- return originalPtr;
-}
-
-/*
- * Just pull out the original pointer.
- */
-static void* getGuardedCopyOriginalPtr(const void* dataBuf)
-{
- const GuardExtra* pExtra = getGuardExtra(dataBuf);
- return (void*) pExtra->originalPtr;
-}
-
-/*
- * Grab the data length.
- */
-static size_t getGuardedCopyOriginalLen(const void* dataBuf)
-{
- const GuardExtra* pExtra = getGuardExtra(dataBuf);
- return pExtra->originalLen;
-}
-
-/*
- * Return the width, in bytes, of a primitive type.
- */
-static int dvmPrimitiveTypeWidth(PrimitiveType primType)
-{
- switch (primType) {
- case PRIM_BOOLEAN: return 1;
- case PRIM_BYTE: return 1;
- case PRIM_SHORT: return 2;
- case PRIM_CHAR: return 2;
- case PRIM_INT: return 4;
- case PRIM_LONG: return 8;
- case PRIM_FLOAT: return 4;
- case PRIM_DOUBLE: return 8;
- case PRIM_VOID:
- default: {
- assert(false);
- return -1;
- }
- }
-}
-
-/*
- * Create a guarded copy of a primitive array. Modifications to the copied
- * data are allowed. Returns a pointer to the copied data.
- */
-static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
- jboolean* isCopy)
-{
- JNI_ENTER();
- ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
- PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
- int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
- void* result;
-
- result = createGuardedCopy(arrObj->contents, len, true);
-
- if (isCopy != NULL)
- *isCopy = JNI_TRUE;
-
- JNI_EXIT();
- return result;
-}
-
-/*
- * Perform the array "release" operation, which may or may not copy data
- * back into the VM, and may or may not release the underlying storage.
- */
-static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
- int mode)
-{
- JNI_ENTER();
- ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
- bool release, copyBack;
- u1* result = NULL;
-
- if (!checkGuardedCopy(dataBuf, true)) {
- LOGE("JNI: failed guarded copy check in releaseGuardedPACopy");
- abortMaybe();
- goto bail;
- }
-
- switch (mode) {
- case 0:
- release = copyBack = true;
- break;
- case JNI_ABORT:
- release = true;
- copyBack = false;
- break;
- case JNI_COMMIT:
- release = false;
- copyBack = true;
- break;
- default:
- LOGE("JNI: bad release mode %d", mode);
- dvmAbort();
- goto bail;
- }
-
- if (copyBack) {
- size_t len = getGuardedCopyOriginalLen(dataBuf);
- memcpy(arrObj->contents, dataBuf, len);
- }
-
- if (release) {
- result = (u1*) freeGuardedCopy(dataBuf);
- } else {
- result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
- }
-
- /* pointer is to the array contents; back up to the array object */
- result -= offsetof(ArrayObject, contents);
-
-bail:
- JNI_EXIT();
- return result;
-}
-
-
-/*
- * ===========================================================================
- * JNI functions
- * ===========================================================================
- */
-
-static jint Check_GetVersion(JNIEnv* env)
-{
- CHECK_ENTER(env, kFlag_Default);
- jint result;
- result = BASE_ENV(env)->GetVersion(env);
- CHECK_EXIT(env);
- return result;
-}
-
-static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
- const jbyte* buf, jsize bufLen)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, loader);
- CHECK_UTF_STRING(env, name);
- CHECK_CLASS_NAME(env, name);
- jclass result;
- result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
- CHECK_EXIT(env);
- return result;
-}
-
-static jclass Check_FindClass(JNIEnv* env, const char* name)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_UTF_STRING(env, name);
- CHECK_CLASS_NAME(env, name);
- jclass result;
- result = BASE_ENV(env)->FindClass(env, name);
- CHECK_EXIT(env);
- return result;
-}
-
-static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jclass result;
- result = BASE_ENV(env)->GetSuperclass(env, clazz);
- CHECK_EXIT(env);
- return result;
-}
-
-static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
- jclass clazz2)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz1);
- CHECK_CLASS(env, clazz2);
- jboolean result;
- result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
- CHECK_EXIT(env);
- return result;
-}
-
-static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, method);
- jmethodID result;
- result = BASE_ENV(env)->FromReflectedMethod(env, method);
- CHECK_EXIT(env);
- return result;
-}
-
-static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, field);
- jfieldID result;
- result = BASE_ENV(env)->FromReflectedField(env, field);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
- jmethodID methodID, jboolean isStatic)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, cls);
- jobject result;
- result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
- jboolean isStatic)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, cls);
- jobject result;
- result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_Throw(JNIEnv* env, jthrowable obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- /* TODO: verify that "obj" is an instance of Throwable */
- jint result;
- result = BASE_ENV(env)->Throw(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- CHECK_NULLABLE_UTF_STRING(env, message);
- jint result;
- result = BASE_ENV(env)->ThrowNew(env, clazz, message);
- CHECK_EXIT(env);
- return result;
-}
-
-static jthrowable Check_ExceptionOccurred(JNIEnv* env)
-{
- CHECK_ENTER(env, kFlag_ExcepOkay);
- jthrowable result;
- result = BASE_ENV(env)->ExceptionOccurred(env);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_ExceptionDescribe(JNIEnv* env)
-{
- CHECK_ENTER(env, kFlag_ExcepOkay);
- BASE_ENV(env)->ExceptionDescribe(env);
- CHECK_EXIT(env);
-}
-
-static void Check_ExceptionClear(JNIEnv* env)
-{
- CHECK_ENTER(env, kFlag_ExcepOkay);
- BASE_ENV(env)->ExceptionClear(env);
- CHECK_EXIT(env);
-}
-
-static void Check_FatalError(JNIEnv* env, const char* msg)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_NULLABLE_UTF_STRING(env, msg);
- BASE_ENV(env)->FatalError(env, msg);
- CHECK_EXIT(env);
-}
-
-static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- jint result;
- result = BASE_ENV(env)->PushLocalFrame(env, capacity);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_OBJECT(env, res);
- jobject result;
- result = BASE_ENV(env)->PopLocalFrame(env, res);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- jobject result;
- result = BASE_ENV(env)->NewGlobalRef(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_OBJECT(env, globalRef);
- if (globalRef != NULL &&
- dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
- {
- LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)",
- globalRef, dvmGetJNIRefType(env, globalRef));
- abortMaybe();
- } else
- {
- BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
- }
- CHECK_EXIT(env);
-}
-
-static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, ref);
- jobject result;
- result = BASE_ENV(env)->NewLocalRef(env, ref);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_OBJECT(env, localRef);
- if (localRef != NULL &&
- dvmGetJNIRefType(env, localRef) != JNILocalRefType)
- {
- LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)",
- localRef, dvmGetJNIRefType(env, localRef));
- abortMaybe();
- } else
- {
- BASE_ENV(env)->DeleteLocalRef(env, localRef);
- }
- CHECK_EXIT(env);
-}
-
-static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
-{
- CHECK_ENTER(env, kFlag_Default);
- jint result;
- result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
- CHECK_EXIT(env);
- return result;
-}
-
-static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, ref1);
- CHECK_OBJECT(env, ref2);
- jboolean result;
- result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jobject result;
- result = BASE_ENV(env)->AllocObject(env, clazz);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
- ...)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jobject result;
- va_list args;
-
- va_start(args, methodID);
- result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
- va_end(args);
-
- CHECK_EXIT(env);
- return result;
-}
-static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
- va_list args)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jobject result;
-
- result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
- CHECK_EXIT(env);
- return result;
-}
-static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
- jvalue* args)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jobject result;
-
- result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
- CHECK_EXIT(env);
- return result;
-}
-
-static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- jclass result;
- result = BASE_ENV(env)->GetObjectClass(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- CHECK_CLASS(env, clazz);
- jboolean result;
- result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
- CHECK_EXIT(env);
- return result;
-}
-
-static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
- const char* sig)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- CHECK_UTF_STRING(env, name);
- CHECK_UTF_STRING(env, sig);
- jmethodID result;
- result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
- CHECK_EXIT(env);
- return result;
-}
-
-static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
- const char* name, const char* sig)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- CHECK_UTF_STRING(env, name);
- CHECK_UTF_STRING(env, sig);
- jfieldID result;
- result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
- CHECK_EXIT(env);
- return result;
-}
-
-static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
- const char* name, const char* sig)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- CHECK_UTF_STRING(env, name);
- CHECK_UTF_STRING(env, sig);
- jmethodID result;
- result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
- CHECK_EXIT(env);
- return result;
-}
-
-static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
- const char* name, const char* sig)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- CHECK_UTF_STRING(env, name);
- CHECK_UTF_STRING(env, sig);
- jfieldID result;
- result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
- CHECK_EXIT(env);
- return result;
-}
-
-#define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
- static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
- jfieldID fieldID) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- _ctype result; \
- CHECK_STATIC_FIELD_ID(env, clazz, fieldID); \
- result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
- fieldID); \
- CHECK_EXIT(env); \
- return result; \
- }
-GET_STATIC_TYPE_FIELD(jobject, Object);
-GET_STATIC_TYPE_FIELD(jboolean, Boolean);
-GET_STATIC_TYPE_FIELD(jbyte, Byte);
-GET_STATIC_TYPE_FIELD(jchar, Char);
-GET_STATIC_TYPE_FIELD(jshort, Short);
-GET_STATIC_TYPE_FIELD(jint, Int);
-GET_STATIC_TYPE_FIELD(jlong, Long);
-GET_STATIC_TYPE_FIELD(jfloat, Float);
-GET_STATIC_TYPE_FIELD(jdouble, Double);
-
-#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
- static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
- jfieldID fieldID, _ctype value) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_STATIC_FIELD_ID(env, clazz, fieldID); \
- /* "value" arg only used when type == ref */ \
- CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true); \
- BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
- value); \
- CHECK_EXIT(env); \
- }
-SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
-SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
-SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
-SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
-SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
-SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
-SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
-SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
-SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
-
-#define GET_TYPE_FIELD(_ctype, _jname) \
- static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
- jfieldID fieldID) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_OBJECT(env, obj); \
- _ctype result; \
- CHECK_INST_FIELD_ID(env, obj, fieldID); \
- result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
- CHECK_EXIT(env); \
- return result; \
- }
-GET_TYPE_FIELD(jobject, Object);
-GET_TYPE_FIELD(jboolean, Boolean);
-GET_TYPE_FIELD(jbyte, Byte);
-GET_TYPE_FIELD(jchar, Char);
-GET_TYPE_FIELD(jshort, Short);
-GET_TYPE_FIELD(jint, Int);
-GET_TYPE_FIELD(jlong, Long);
-GET_TYPE_FIELD(jfloat, Float);
-GET_TYPE_FIELD(jdouble, Double);
-
-#define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
- static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
- jfieldID fieldID, _ctype value) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_OBJECT(env, obj); \
- CHECK_INST_FIELD_ID(env, obj, fieldID); \
- /* "value" arg only used when type == ref */ \
- CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
- BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
- CHECK_EXIT(env); \
- }
-SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
-SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
-SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
-SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
-SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
-SET_TYPE_FIELD(jint, Int, PRIM_INT);
-SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
-SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
-SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
-
-#define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
- static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
- jmethodID methodID, ...) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- va_list args; \
- va_start(args, methodID); \
- _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
- args); \
- va_end(args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
- jmethodID methodID, va_list args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
- args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
- jmethodID methodID, jvalue* args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
- args); \
- CHECK_EXIT(env); \
- return _retok; \
- }
-CALL_VIRTUAL(jobject, Object, Object* result, result=(Object*), result, 'L');
-CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
-CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
-CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
-CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
-CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
-CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
-CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
-CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
-CALL_VIRTUAL(void, Void, , , , 'V');
-
-#define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
- _retsig) \
- static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
- jobject obj, jclass clazz, jmethodID methodID, ...) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- va_list args; \
- va_start(args, methodID); \
- _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
- clazz, methodID, args); \
- va_end(args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
- jobject obj, jclass clazz, jmethodID methodID, va_list args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
- clazz, methodID, args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
- jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_OBJECT(env, obj); \
- CHECK_SIG(env, methodID, _retsig, false); \
- CHECK_VIRTUAL_METHOD(env, obj, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
- clazz, methodID, args); \
- CHECK_EXIT(env); \
- return _retok; \
- }
-CALL_NONVIRTUAL(jobject, Object, Object* result, result=(Object*), result, 'L');
-CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
-CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
-CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
-CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
-CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
-CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
-CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
-CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
-CALL_NONVIRTUAL(void, Void, , , , 'V');
-
-
-#define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
- static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
- jclass clazz, jmethodID methodID, ...) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_SIG(env, methodID, _retsig, true); \
- CHECK_STATIC_METHOD(env, clazz, methodID); \
- _retdecl; \
- va_list args; \
- va_start(args, methodID); \
- _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
- methodID, args); \
- va_end(args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
- jclass clazz, jmethodID methodID, va_list args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_SIG(env, methodID, _retsig, true); \
- CHECK_STATIC_METHOD(env, clazz, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
- methodID, args); \
- CHECK_EXIT(env); \
- return _retok; \
- } \
- static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
- jclass clazz, jmethodID methodID, jvalue* args) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_CLASS(env, clazz); \
- CHECK_SIG(env, methodID, _retsig, true); \
- CHECK_STATIC_METHOD(env, clazz, methodID); \
- _retdecl; \
- _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
- methodID, args); \
- CHECK_EXIT(env); \
- return _retok; \
- }
-CALL_STATIC(jobject, Object, Object* result, result=(Object*), result, 'L');
-CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
-CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
-CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
-CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
-CALL_STATIC(jint, Int, jint result, result=, result, 'I');
-CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
-CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
-CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
-CALL_STATIC(void, Void, , , , 'V');
-
-static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
- jsize len)
-{
- CHECK_ENTER(env, kFlag_Default);
- jstring result;
- result = BASE_ENV(env)->NewString(env, unicodeChars, len);
- CHECK_EXIT(env);
- return result;
-}
-
-static jsize Check_GetStringLength(JNIEnv* env, jstring string)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, string);
- jsize result;
- result = BASE_ENV(env)->GetStringLength(env, string);
- CHECK_EXIT(env);
- return result;
-}
-
-static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
- jboolean* isCopy)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, string);
- const jchar* result;
- result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
- if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
- JNI_ENTER();
- StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
- int byteCount = dvmStringLen(strObj) * 2;
- JNI_EXIT();
- result = (const jchar*) createGuardedCopy(result, byteCount, false);
- if (isCopy != NULL)
- *isCopy = JNI_TRUE;
- }
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
- const jchar* chars)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_STRING(env, string);
- CHECK_NON_NULL(env, chars);
- if (((JNIEnvExt*)env)->forceDataCopy) {
- if (!checkGuardedCopy(chars, false)) {
- LOGE("JNI: failed guarded copy check in ReleaseStringChars");
- abortMaybe();
- return;
- }
- chars = (const jchar*) freeGuardedCopy((jchar*)chars);
- }
- BASE_ENV(env)->ReleaseStringChars(env, string, chars);
- CHECK_EXIT(env);
-}
-
-static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_NULLABLE_UTF_STRING(env, bytes);
- jstring result;
- result = BASE_ENV(env)->NewStringUTF(env, bytes);
- CHECK_EXIT(env);
- return result;
-}
-
-static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, string);
- jsize result;
- result = BASE_ENV(env)->GetStringUTFLength(env, string);
- CHECK_EXIT(env);
- return result;
-}
-
-static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
- jboolean* isCopy)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, string);
- const char* result;
- result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
- if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
- result = (const char*) createGuardedCopy(result, strlen(result)+1, false);
- if (isCopy != NULL)
- *isCopy = JNI_TRUE;
- }
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
- const char* utf)
-{
- CHECK_ENTER(env, kFlag_ExcepOkay);
- CHECK_STRING(env, string);
- CHECK_NON_NULL(env, utf);
- if (((JNIEnvExt*)env)->forceDataCopy) {
- //int len = dvmStringUtf8ByteLen(string) + 1;
- if (!checkGuardedCopy(utf, false)) {
- LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars");
- abortMaybe();
- return;
- }
- utf = (const char*) freeGuardedCopy((char*)utf);
- }
- BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
- CHECK_EXIT(env);
-}
-
-static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_ARRAY(env, array);
- jsize result;
- result = BASE_ENV(env)->GetArrayLength(env, array);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
- jclass elementClass, jobject initialElement)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, elementClass);
- CHECK_OBJECT(env, initialElement);
- CHECK_LENGTH_POSITIVE(env, length);
- jobjectArray result;
- result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
- initialElement);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
- jsize index)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_ARRAY(env, array);
- jobject result;
- result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
- jsize index, jobject value)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_ARRAY(env, array);
- BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
- CHECK_EXIT(env);
-}
-
-#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
- static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_LENGTH_POSITIVE(env, length); \
- _artype result; \
- result = BASE_ENV(env)->New##_jname##Array(env, length); \
- CHECK_EXIT(env); \
- return result; \
- }
-NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
-NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
-NEW_PRIMITIVE_ARRAY(jcharArray, Char);
-NEW_PRIMITIVE_ARRAY(jshortArray, Short);
-NEW_PRIMITIVE_ARRAY(jintArray, Int);
-NEW_PRIMITIVE_ARRAY(jlongArray, Long);
-NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
-NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
-
-
-/*
- * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
- * The code deliberately uses an invalid sequence of operations, so we
- * need to pass it through unmodified. Review that code before making
- * any changes here.
- */
-#define kNoCopyMagic 0xd5aab57f
-
-#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
- static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
- _ctype##Array array, jboolean* isCopy) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_ARRAY(env, array); \
- _ctype* result; \
- u4 noCopy = 0; \
- if (((JNIEnvExt*)env)->forceDataCopy && isCopy != NULL) { \
- /* capture this before the base call tramples on it */ \
- noCopy = *(u4*) isCopy; \
- } \
- result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
- array, isCopy); \
- if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
- if (noCopy == kNoCopyMagic) { \
- LOGV("FC: not copying %p %x\n", array, noCopy); \
- } else { \
- result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
- } \
- } \
- CHECK_EXIT(env); \
- return result; \
- }
-
-#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
- static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
- _ctype##Array array, _ctype* elems, jint mode) \
- { \
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
- CHECK_ARRAY(env, array); \
- CHECK_NON_NULL(env, elems); \
- CHECK_RELEASE_MODE(env, mode); \
- if (((JNIEnvExt*)env)->forceDataCopy) { \
- if ((uintptr_t)elems == kNoCopyMagic) { \
- LOGV("FC: not freeing %p\n", array); \
- elems = NULL; /* base JNI call doesn't currently need */ \
- } else { \
- elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \
- mode); \
- } \
- } \
- BASE_ENV(env)->Release##_jname##ArrayElements(env, \
- array, elems, mode); \
- CHECK_EXIT(env); \
- }
-
-#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
- static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
- _ctype##Array array, jsize start, jsize len, _ctype* buf) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_ARRAY(env, array); \
- BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
- len, buf); \
- CHECK_EXIT(env); \
- }
-
-#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
- static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
- _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
- { \
- CHECK_ENTER(env, kFlag_Default); \
- CHECK_ARRAY(env, array); \
- BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
- len, buf); \
- CHECK_EXIT(env); \
- }
-
-#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
- GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
- RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
- GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
- SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
-
-/* TODO: verify primitive array type matches call type */
-PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
-PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
-PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
-PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
-PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
-PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
-PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
-PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
-
-static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
- const JNINativeMethod* methods, jint nMethods)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jint result;
- result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_CLASS(env, clazz);
- jint result;
- result = BASE_ENV(env)->UnregisterNatives(env, clazz);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- jint result;
- result = BASE_ENV(env)->MonitorEnter(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_MonitorExit(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_OBJECT(env, obj);
- jint result;
- result = BASE_ENV(env)->MonitorExit(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
-{
- CHECK_ENTER(env, kFlag_Default);
- jint result;
- result = BASE_ENV(env)->GetJavaVM(env, vm);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
- jsize len, jchar* buf)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, str);
- BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
- CHECK_EXIT(env);
-}
-
-static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
- jsize len, char* buf)
-{
- CHECK_ENTER(env, kFlag_CritOkay);
- CHECK_STRING(env, str);
- BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
- CHECK_EXIT(env);
-}
-
-static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
- jboolean* isCopy)
-{
- CHECK_ENTER(env, kFlag_CritGet);
- CHECK_ARRAY(env, array);
- void* result;
- result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
- if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
- result = createGuardedPACopy(env, array, isCopy);
- }
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
- void* carray, jint mode)
-{
- CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
- CHECK_ARRAY(env, array);
- CHECK_NON_NULL(env, carray);
- CHECK_RELEASE_MODE(env, mode);
- if (((JNIEnvExt*)env)->forceDataCopy) {
- carray = releaseGuardedPACopy(env, array, carray, mode);
- }
- BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
- CHECK_EXIT(env);
-}
-
-static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
- jboolean* isCopy)
-{
- CHECK_ENTER(env, kFlag_CritGet);
- CHECK_STRING(env, string);
- const jchar* result;
- result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
- if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
- JNI_ENTER();
- StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
- int byteCount = dvmStringLen(strObj) * 2;
- JNI_EXIT();
- result = (const jchar*) createGuardedCopy(result, byteCount, false);
- if (isCopy != NULL)
- *isCopy = JNI_TRUE;
- }
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
- const jchar* carray)
-{
- CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
- CHECK_STRING(env, string);
- CHECK_NON_NULL(env, carray);
- if (((JNIEnvExt*)env)->forceDataCopy) {
- if (!checkGuardedCopy(carray, false)) {
- LOGE("JNI: failed guarded copy check in ReleaseStringCritical");
- abortMaybe();
- return;
- }
- carray = (const jchar*) freeGuardedCopy((jchar*)carray);
- }
- BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
- CHECK_EXIT(env);
-}
-
-static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- jweak result;
- result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
-{
- CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
- CHECK_OBJECT(env, obj);
- BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
- CHECK_EXIT(env);
-}
-
-static jboolean Check_ExceptionCheck(JNIEnv* env)
-{
- CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
- jboolean result;
- result = BASE_ENV(env)->ExceptionCheck(env);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, obj);
- jobjectRefType result;
- result = BASE_ENV(env)->GetObjectRefType(env, obj);
- CHECK_EXIT(env);
- return result;
-}
-
-static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
- jlong capacity)
-{
- CHECK_ENTER(env, kFlag_Default);
- jobject result;
- if (address == NULL || capacity < 0) {
- LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)",
- address, (long) capacity);
- abortMaybe();
- return NULL;
- }
- result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
- CHECK_EXIT(env);
- return result;
-}
-
-static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, buf);
- void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
- CHECK_EXIT(env);
- return result;
-}
-
-static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
-{
- CHECK_ENTER(env, kFlag_Default);
- CHECK_OBJECT(env, buf);
- /* TODO: verify "buf" is an instance of java.nio.Buffer */
- jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
- CHECK_EXIT(env);
- return result;
-}
-
-
-/*
- * ===========================================================================
- * JNI invocation functions
- * ===========================================================================
- */
-
-static jint Check_DestroyJavaVM(JavaVM* vm)
-{
- CHECK_VMENTER(vm, false);
- jint result;
- result = BASE_VM(vm)->DestroyJavaVM(vm);
- CHECK_VMEXIT(vm, false);
- return result;
-}
-
-static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
- void* thr_args)
-{
- CHECK_VMENTER(vm, false);
- jint result;
- result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
- CHECK_VMEXIT(vm, true);
- return result;
-}
-
-static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
- void* thr_args)
-{
- CHECK_VMENTER(vm, false);
- jint result;
- result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
- CHECK_VMEXIT(vm, true);
- return result;
-}
-
-static jint Check_DetachCurrentThread(JavaVM* vm)
-{
- CHECK_VMENTER(vm, true);
- jint result;
- result = BASE_VM(vm)->DetachCurrentThread(vm);
- CHECK_VMEXIT(vm, false);
- return result;
-}
-
-static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
-{
- CHECK_VMENTER(vm, true);
- jint result;
- result = BASE_VM(vm)->GetEnv(vm, env, version);
- CHECK_VMEXIT(vm, true);
- return result;
-}
-
-
-/*
- * ===========================================================================
- * Function tables
- * ===========================================================================
- */
-
-static const struct JNINativeInterface gCheckNativeInterface = {
- NULL,
- NULL,
- NULL,
- NULL,
-
- Check_GetVersion,
-
- Check_DefineClass,
- Check_FindClass,
-
- Check_FromReflectedMethod,
- Check_FromReflectedField,
- Check_ToReflectedMethod,
-
- Check_GetSuperclass,
- Check_IsAssignableFrom,
-
- Check_ToReflectedField,
-
- Check_Throw,
- Check_ThrowNew,
- Check_ExceptionOccurred,
- Check_ExceptionDescribe,
- Check_ExceptionClear,
- Check_FatalError,
-
- Check_PushLocalFrame,
- Check_PopLocalFrame,
-
- Check_NewGlobalRef,
- Check_DeleteGlobalRef,
- Check_DeleteLocalRef,
- Check_IsSameObject,
- Check_NewLocalRef,
- Check_EnsureLocalCapacity,
-
- Check_AllocObject,
- Check_NewObject,
- Check_NewObjectV,
- Check_NewObjectA,
-
- Check_GetObjectClass,
- Check_IsInstanceOf,
-
- Check_GetMethodID,
-
- Check_CallObjectMethod,
- Check_CallObjectMethodV,
- Check_CallObjectMethodA,
- Check_CallBooleanMethod,
- Check_CallBooleanMethodV,
- Check_CallBooleanMethodA,
- Check_CallByteMethod,
- Check_CallByteMethodV,
- Check_CallByteMethodA,
- Check_CallCharMethod,
- Check_CallCharMethodV,
- Check_CallCharMethodA,
- Check_CallShortMethod,
- Check_CallShortMethodV,
- Check_CallShortMethodA,
- Check_CallIntMethod,
- Check_CallIntMethodV,
- Check_CallIntMethodA,
- Check_CallLongMethod,
- Check_CallLongMethodV,
- Check_CallLongMethodA,
- Check_CallFloatMethod,
- Check_CallFloatMethodV,
- Check_CallFloatMethodA,
- Check_CallDoubleMethod,
- Check_CallDoubleMethodV,
- Check_CallDoubleMethodA,
- Check_CallVoidMethod,
- Check_CallVoidMethodV,
- Check_CallVoidMethodA,
-
- Check_CallNonvirtualObjectMethod,
- Check_CallNonvirtualObjectMethodV,
- Check_CallNonvirtualObjectMethodA,
- Check_CallNonvirtualBooleanMethod,
- Check_CallNonvirtualBooleanMethodV,
- Check_CallNonvirtualBooleanMethodA,
- Check_CallNonvirtualByteMethod,
- Check_CallNonvirtualByteMethodV,
- Check_CallNonvirtualByteMethodA,
- Check_CallNonvirtualCharMethod,
- Check_CallNonvirtualCharMethodV,
- Check_CallNonvirtualCharMethodA,
- Check_CallNonvirtualShortMethod,
- Check_CallNonvirtualShortMethodV,
- Check_CallNonvirtualShortMethodA,
- Check_CallNonvirtualIntMethod,
- Check_CallNonvirtualIntMethodV,
- Check_CallNonvirtualIntMethodA,
- Check_CallNonvirtualLongMethod,
- Check_CallNonvirtualLongMethodV,
- Check_CallNonvirtualLongMethodA,
- Check_CallNonvirtualFloatMethod,
- Check_CallNonvirtualFloatMethodV,
- Check_CallNonvirtualFloatMethodA,
- Check_CallNonvirtualDoubleMethod,
- Check_CallNonvirtualDoubleMethodV,
- Check_CallNonvirtualDoubleMethodA,
- Check_CallNonvirtualVoidMethod,
- Check_CallNonvirtualVoidMethodV,
- Check_CallNonvirtualVoidMethodA,
-
- Check_GetFieldID,
-
- Check_GetObjectField,
- Check_GetBooleanField,
- Check_GetByteField,
- Check_GetCharField,
- Check_GetShortField,
- Check_GetIntField,
- Check_GetLongField,
- Check_GetFloatField,
- Check_GetDoubleField,
- Check_SetObjectField,
- Check_SetBooleanField,
- Check_SetByteField,
- Check_SetCharField,
- Check_SetShortField,
- Check_SetIntField,
- Check_SetLongField,
- Check_SetFloatField,
- Check_SetDoubleField,
-
- Check_GetStaticMethodID,
-
- Check_CallStaticObjectMethod,
- Check_CallStaticObjectMethodV,
- Check_CallStaticObjectMethodA,
- Check_CallStaticBooleanMethod,
- Check_CallStaticBooleanMethodV,
- Check_CallStaticBooleanMethodA,
- Check_CallStaticByteMethod,
- Check_CallStaticByteMethodV,
- Check_CallStaticByteMethodA,
- Check_CallStaticCharMethod,
- Check_CallStaticCharMethodV,
- Check_CallStaticCharMethodA,
- Check_CallStaticShortMethod,
- Check_CallStaticShortMethodV,
- Check_CallStaticShortMethodA,
- Check_CallStaticIntMethod,
- Check_CallStaticIntMethodV,
- Check_CallStaticIntMethodA,
- Check_CallStaticLongMethod,
- Check_CallStaticLongMethodV,
- Check_CallStaticLongMethodA,
- Check_CallStaticFloatMethod,
- Check_CallStaticFloatMethodV,
- Check_CallStaticFloatMethodA,
- Check_CallStaticDoubleMethod,
- Check_CallStaticDoubleMethodV,
- Check_CallStaticDoubleMethodA,
- Check_CallStaticVoidMethod,
- Check_CallStaticVoidMethodV,
- Check_CallStaticVoidMethodA,
-
- Check_GetStaticFieldID,
-
- Check_GetStaticObjectField,
- Check_GetStaticBooleanField,
- Check_GetStaticByteField,
- Check_GetStaticCharField,
- Check_GetStaticShortField,
- Check_GetStaticIntField,
- Check_GetStaticLongField,
- Check_GetStaticFloatField,
- Check_GetStaticDoubleField,
-
- Check_SetStaticObjectField,
- Check_SetStaticBooleanField,
- Check_SetStaticByteField,
- Check_SetStaticCharField,
- Check_SetStaticShortField,
- Check_SetStaticIntField,
- Check_SetStaticLongField,
- Check_SetStaticFloatField,
- Check_SetStaticDoubleField,
-
- Check_NewString,
-
- Check_GetStringLength,
- Check_GetStringChars,
- Check_ReleaseStringChars,
-
- Check_NewStringUTF,
- Check_GetStringUTFLength,
- Check_GetStringUTFChars,
- Check_ReleaseStringUTFChars,
-
- Check_GetArrayLength,
- Check_NewObjectArray,
- Check_GetObjectArrayElement,
- Check_SetObjectArrayElement,
-
- Check_NewBooleanArray,
- Check_NewByteArray,
- Check_NewCharArray,
- Check_NewShortArray,
- Check_NewIntArray,
- Check_NewLongArray,
- Check_NewFloatArray,
- Check_NewDoubleArray,
-
- Check_GetBooleanArrayElements,
- Check_GetByteArrayElements,
- Check_GetCharArrayElements,
- Check_GetShortArrayElements,
- Check_GetIntArrayElements,
- Check_GetLongArrayElements,
- Check_GetFloatArrayElements,
- Check_GetDoubleArrayElements,
-
- Check_ReleaseBooleanArrayElements,
- Check_ReleaseByteArrayElements,
- Check_ReleaseCharArrayElements,
- Check_ReleaseShortArrayElements,
- Check_ReleaseIntArrayElements,
- Check_ReleaseLongArrayElements,
- Check_ReleaseFloatArrayElements,
- Check_ReleaseDoubleArrayElements,
-
- Check_GetBooleanArrayRegion,
- Check_GetByteArrayRegion,
- Check_GetCharArrayRegion,
- Check_GetShortArrayRegion,
- Check_GetIntArrayRegion,
- Check_GetLongArrayRegion,
- Check_GetFloatArrayRegion,
- Check_GetDoubleArrayRegion,
- Check_SetBooleanArrayRegion,
- Check_SetByteArrayRegion,
- Check_SetCharArrayRegion,
- Check_SetShortArrayRegion,
- Check_SetIntArrayRegion,
- Check_SetLongArrayRegion,
- Check_SetFloatArrayRegion,
- Check_SetDoubleArrayRegion,
-
- Check_RegisterNatives,
- Check_UnregisterNatives,
-
- Check_MonitorEnter,
- Check_MonitorExit,
-
- Check_GetJavaVM,
-
- Check_GetStringRegion,
- Check_GetStringUTFRegion,
-
- Check_GetPrimitiveArrayCritical,
- Check_ReleasePrimitiveArrayCritical,
-
- Check_GetStringCritical,
- Check_ReleaseStringCritical,
-
- Check_NewWeakGlobalRef,
- Check_DeleteWeakGlobalRef,
-
- Check_ExceptionCheck,
-
- Check_NewDirectByteBuffer,
- Check_GetDirectBufferAddress,
- Check_GetDirectBufferCapacity,
-
- Check_GetObjectRefType
-};
-static const struct JNIInvokeInterface gCheckInvokeInterface = {
- NULL,
- NULL,
- NULL,
-
- Check_DestroyJavaVM,
- Check_AttachCurrentThread,
- Check_DetachCurrentThread,
-
- Check_GetEnv,
-
- Check_AttachCurrentThreadAsDaemon,
-};
-
-
-/*
- * Replace the normal table with the checked table.
- */
-void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
-{
- assert(pEnv->funcTable != &gCheckNativeInterface);
- pEnv->baseFuncTable = pEnv->funcTable;
- pEnv->funcTable = &gCheckNativeInterface;
-}
-
-/*
- * Replace the normal table with the checked table.
- */
-void dvmUseCheckedJniVm(JavaVMExt* pVm)
-{
- assert(pVm->funcTable != &gCheckInvokeInterface);
- pVm->baseFuncTable = pVm->funcTable;
- pVm->funcTable = &gCheckInvokeInterface;
-}
diff --git a/vm/CheckJni.cpp b/vm/CheckJni.cpp
new file mode 100644
index 0000000..a18bfd6
--- /dev/null
+++ b/vm/CheckJni.cpp
@@ -0,0 +1,2245 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
+ *
+ * We want to verify types, make sure class and field IDs are valid, and
+ * ensure that JNI's semantic expectations are being met. JNI seems to
+ * be relatively lax when it comes to requirements for permission checks,
+ * e.g. access to private methods is generally allowed from anywhere.
+ */
+
+#include "Dalvik.h"
+#include "JniInternal.h"
+
+#include <sys/mman.h>
+#include <zlib.h>
+
+/*
+ * Abort if we are configured to bail out on JNI warnings.
+ */
+static void abortMaybe() {
+ if (!gDvmJni.warnOnly) {
+ dvmDumpThread(dvmThreadSelf(), false);
+ dvmAbort();
+ }
+}
+
+/*
+ * ===========================================================================
+ * JNI call bridge wrapper
+ * ===========================================================================
+ */
+
+/*
+ * Check the result of a native method call that returns an object reference.
+ *
+ * The primary goal here is to verify that native code is returning the
+ * correct type of object. If it's declared to return a String but actually
+ * returns a byte array, things will fail in strange ways later on.
+ *
+ * This can be a fairly expensive operation, since we have to look up the
+ * return type class by name in method->clazz' class loader. We take a
+ * shortcut here and allow the call to succeed if the descriptor strings
+ * match. This will allow some false-positives when a class is redefined
+ * by a class loader, but that's rare enough that it doesn't seem worth
+ * testing for.
+ *
+ * At this point, pResult->l has already been converted to an object pointer.
+ */
+static void checkCallResultCommon(const u4* args, const JValue* pResult,
+ const Method* method, Thread* self)
+{
+ assert(pResult->l != NULL);
+ const Object* resultObj = (const Object*) pResult->l;
+
+ if (resultObj == kInvalidIndirectRefObject) {
+ LOGW("JNI WARNING: invalid reference returned from native code");
+ const Method* method = dvmGetCurrentJNIMethod();
+ char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+ LOGW(" in %s.%s:%s", method->clazz->descriptor, method->name, desc);
+ free(desc);
+ abortMaybe();
+ return;
+ }
+
+ ClassObject* objClazz = resultObj->clazz;
+
+ /*
+ * Make sure that pResult->l is an instance of the type this
+ * method was expected to return.
+ */
+ const char* declType = dexProtoGetReturnType(&method->prototype);
+ const char* objType = objClazz->descriptor;
+ if (strcmp(declType, objType) == 0) {
+ /* names match; ignore class loader issues and allow it */
+ LOGV("Check %s.%s: %s io %s (FAST-OK)",
+ method->clazz->descriptor, method->name, objType, declType);
+ } else {
+ /*
+ * Names didn't match. We need to resolve declType in the context
+ * of method->clazz->classLoader, and compare the class objects
+ * for equality.
+ *
+ * Since we're returning an instance of declType, it's safe to
+ * assume that it has been loaded and initialized (or, for the case
+ * of an array, generated). However, the current class loader may
+ * not be listed as an initiating loader, so we can't just look for
+ * it in the loaded-classes list.
+ */
+ ClassObject* declClazz = dvmFindClassNoInit(declType, method->clazz->classLoader);
+ if (declClazz == NULL) {
+ LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
+ declType, objType);
+ LOGW(" failed in %s.%s ('%s' not found)",
+ method->clazz->descriptor, method->name, declType);
+ abortMaybe();
+ return;
+ }
+ if (!dvmInstanceof(objClazz, declClazz)) {
+ LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
+ declType, objType);
+ LOGW(" failed in %s.%s",
+ method->clazz->descriptor, method->name);
+ abortMaybe();
+ return;
+ } else {
+ LOGV("Check %s.%s: %s io %s (SLOW-OK)",
+ method->clazz->descriptor, method->name, objType, declType);
+ }
+ }
+}
+
+/*
+ * Determine if we need to check the return type coming out of the call.
+ *
+ * (We don't simply do this at the top of checkCallResultCommon() because
+ * this is on the critical path for native method calls.)
+ */
+static inline bool callNeedsCheck(const u4* args, JValue* pResult,
+ const Method* method, Thread* self)
+{
+ return (method->shorty[0] == 'L' && !dvmCheckException(self) && pResult->l != NULL);
+}
+
+/*
+ * Check a call into native code.
+ */
+void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
+ const Method* method, Thread* self)
+{
+ dvmCallJNIMethod_general(args, pResult, method, self);
+ if (callNeedsCheck(args, pResult, method, self)) {
+ checkCallResultCommon(args, pResult, method, self);
+ }
+}
+
+/*
+ * Check a synchronized call into native code.
+ */
+void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+ const Method* method, Thread* self)
+{
+ dvmCallJNIMethod_synchronized(args, pResult, method, self);
+ if (callNeedsCheck(args, pResult, method, self)) {
+ checkCallResultCommon(args, pResult, method, self);
+ }
+}
+
+/*
+ * Check a virtual call with no reference arguments (other than "this").
+ */
+void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self)
+{
+ dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
+ if (callNeedsCheck(args, pResult, method, self)) {
+ checkCallResultCommon(args, pResult, method, self);
+ }
+}
+
+/*
+ * Check a static call with no reference arguments (other than "clazz").
+ */
+void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+ const Method* method, Thread* self)
+{
+ dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
+ if (callNeedsCheck(args, pResult, method, self)) {
+ checkCallResultCommon(args, pResult, method, self);
+ }
+}
+
+
+/*
+ * ===========================================================================
+ * JNI function helpers
+ * ===========================================================================
+ */
+
+static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
+ return ((JNIEnvExt*) env)->baseFuncTable;
+}
+
+static inline const JNIInvokeInterface* baseVm(JavaVM* vm) {
+ return ((JavaVMExt*) vm)->baseFuncTable;
+}
+
+/*
+ * Prints trace messages when a native method calls a JNI function such as
+ * NewByteArray. Enabled if both "-Xcheck:jni" and "-verbose:jni" are enabled.
+ */
+static inline void jniTrace(bool hasMethod, const char* functionName) {
+ static const char* classDescriptor = "???";
+ static const char* methodName = "???";
+ if (hasMethod) {
+ const Method* method = dvmGetCurrentJNIMethod();
+ classDescriptor = method->clazz->descriptor;
+ methodName = method->name;
+ }
+ /* use +6 to drop the leading "Check_" */
+ LOGI("JNI: %s (from %s.%s)", functionName + 6, classDescriptor, methodName);
+}
+
+class ScopedJniThreadState {
+public:
+ explicit ScopedJniThreadState(JNIEnv* env) {
+ dvmChangeStatus(NULL, THREAD_RUNNING);
+ }
+
+ ~ScopedJniThreadState() {
+ dvmChangeStatus(NULL, THREAD_NATIVE);
+ }
+
+private:
+ // Disallow copy and assignment.
+ ScopedJniThreadState(const ScopedJniThreadState&);
+ void operator=(const ScopedJniThreadState&);
+};
+
+class ScopedVmCheck {
+public:
+ /*
+ * Set "hasMethod" to true if we have a valid thread with a method pointer.
+ * We won't have one before attaching a thread, after detaching a thread, or
+ * after destroying the VM.
+ */
+ ScopedVmCheck(bool hasMethod, const char* functionName) {
+ if (gDvm.verboseJni) {
+ jniTrace(hasMethod, functionName);
+ }
+ }
+
+private:
+ // Disallow copy and assignment.
+ ScopedVmCheck(const ScopedVmCheck&);
+ void operator=(const ScopedVmCheck&);
+};
+
+/*
+ * Flags passed into ScopedCheck.
+ */
+#define kFlag_Default 0x0000
+
+#define kFlag_CritBad 0x0000 /* calling while in critical is bad */
+#define kFlag_CritOkay 0x0001 /* ...okay */
+#define kFlag_CritGet 0x0002 /* this is a critical "get" */
+#define kFlag_CritRelease 0x0003 /* this is a critical "release" */
+#define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
+
+#define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
+#define kFlag_ExcepOkay 0x0004 /* ...okay */
+
+class ScopedCheck {
+public:
+ explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
+ : mEnv(env), mFunctionName(functionName)
+ {
+ if (gDvm.verboseJni) {
+ jniTrace(true, mFunctionName);
+ }
+ checkThread(flags);
+ }
+
+ /*
+ * Verify that "array" is non-NULL and points to an Array object.
+ *
+ * Since we're dealing with objects, switch to "running" mode.
+ */
+ void checkArray(jarray jarr) {
+ if (jarr == NULL) {
+ LOGW("JNI WARNING: received null array");
+ showLocation();
+ abortMaybe();
+ return;
+ }
+
+ ScopedJniThreadState ts(mEnv);
+ bool printWarn = false;
+
+ Object* obj = dvmDecodeIndirectRef(mEnv, jarr);
+
+ if (!dvmIsValidObject(obj)) {
+ LOGW("JNI WARNING: jarray is invalid %s ref (%p)", dvmIndirectRefTypeName(jarr), jarr);
+ printWarn = true;
+ } else if (obj->clazz->descriptor[0] != '[') {
+ LOGW("JNI WARNING: jarray arg has wrong type (expected array, got %s)",
+ obj->clazz->descriptor);
+ printWarn = true;
+ }
+
+ if (printWarn) {
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * In some circumstances the VM will screen class names, but it doesn't
+ * for class lookup. When things get bounced through a class loader, they
+ * can actually get normalized a couple of times; as a result, passing in
+ * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
+ * work in some circumstances.
+ *
+ * This is incorrect and could cause strange behavior or compatibility
+ * problems, so we want to screen that out here.
+ *
+ * We expect "full-qualified" class names, like "java/lang/Thread" or
+ * "[Ljava/lang/Object;".
+ */
+ void checkClassName(const char* className) {
+ if (!dexIsValidClassName(className, false)) {
+ LOGW("JNI WARNING: illegal class name '%s' (%s)", className, mFunctionName);
+ LOGW(" (should be formed like 'dalvik/system/DexFile')");
+ LOGW(" or '[Ldalvik/system/DexFile;' or '[[B')");
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that the field is of the appropriate type. If the field has an
+ * object type, "jobj" is the object we're trying to assign into it.
+ *
+ * Works for both static and instance fields.
+ */
+ void checkFieldType(jobject jobj, jfieldID fieldID, PrimitiveType prim, bool isStatic) {
+ if (fieldID == NULL) {
+ LOGW("JNI WARNING: null field ID");
+ showLocation();
+ abortMaybe();
+ }
+
+ bool printWarn = false;
+ Field* field = (Field*) fieldID;
+ if ((field->signature[0] == 'L' || field->signature[0] == '[') && jobj != NULL) {
+ ScopedJniThreadState ts(mEnv);
+ Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
+ /*
+ * If jobj is a weak global ref whose referent has been cleared,
+ * obj will be NULL. Otherwise, obj should always be non-NULL
+ * and valid.
+ */
+ if (obj != NULL && !dvmIsValidObject(obj)) {
+ LOGW("JNI WARNING: field operation on invalid %s ref (%p)",
+ dvmIndirectRefTypeName(jobj), jobj);
+ printWarn = true;
+ } else {
+ ClassObject* fieldClass = dvmFindLoadedClass(field->signature);
+ ClassObject* objClass = obj->clazz;
+
+ assert(fieldClass != NULL);
+ assert(objClass != NULL);
+
+ if (!dvmInstanceof(objClass, fieldClass)) {
+ LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
+ field->name, field->signature, objClass->descriptor);
+ printWarn = true;
+ }
+ }
+ } else if (dexGetPrimitiveTypeFromDescriptorChar(field->signature[0]) != prim) {
+ LOGW("JNI WARNING: set field '%s' expected type %s, got %s",
+ field->name, field->signature, primitiveTypeToName(prim));
+ printWarn = true;
+ } else if (isStatic && !dvmIsStaticField(field)) {
+ if (isStatic) {
+ LOGW("JNI WARNING: accessing non-static field %s as static", field->name);
+ } else {
+ LOGW("JNI WARNING: accessing static field %s as non-static", field->name);
+ }
+ printWarn = true;
+ }
+
+ if (printWarn) {
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that this instance field ID is valid for this object.
+ *
+ * Assumes "jobj" has already been validated.
+ */
+ void checkInstanceFieldID(jobject jobj, jfieldID fieldID) {
+ ScopedJniThreadState ts(mEnv);
+
+ Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
+ ClassObject* clazz = obj->clazz;
+
+ /*
+ * Check this class and all of its superclasses for a matching field.
+ * Don't need to scan interfaces.
+ */
+ while (clazz != NULL) {
+ if ((InstField*) fieldID >= clazz->ifields &&
+ (InstField*) fieldID < clazz->ifields + clazz->ifieldCount) {
+ return;
+ }
+
+ clazz = clazz->super;
+ }
+
+ LOGW("JNI WARNING: inst fieldID %p not valid for class %s",
+ fieldID, obj->clazz->descriptor);
+ showLocation();
+ abortMaybe();
+ }
+
+ /*
+ * Verify that the length argument to array-creation calls is >= 0.
+ */
+ void checkLengthPositive(jsize length) {
+ if (length < 0) {
+ LOGW("JNI WARNING: negative length for array allocation (%s)", mFunctionName);
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that the pointer value is non-NULL.
+ */
+ void checkNonNull(const void* ptr) {
+ if (ptr == NULL) {
+ LOGW("JNI WARNING: invalid null pointer (%s)", mFunctionName);
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that "jobj" is a valid object, and that it's an object that JNI
+ * is allowed to know about. We allow NULL references.
+ *
+ * Switches to "running" mode before performing checks.
+ */
+ void checkObject(jobject jobj) {
+ if (jobj == NULL) {
+ return;
+ }
+
+ ScopedJniThreadState ts(mEnv);
+
+ bool printWarn = false;
+ if (dvmGetJNIRefType(mEnv, jobj) == JNIInvalidRefType) {
+ LOGW("JNI WARNING: %p is not a valid JNI reference (type=%s)",
+ jobj, dvmIndirectRefTypeName(jobj));
+ printWarn = true;
+ } else {
+ Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
+
+ /*
+ * The decoded object will be NULL if this is a weak global ref
+ * with a cleared referent.
+ */
+ if (obj == kInvalidIndirectRefObject || (obj != NULL && !dvmIsValidObject(obj))) {
+ LOGW("JNI WARNING: native code passing in bad object %p %p", jobj, obj);
+ printWarn = true;
+ }
+ }
+
+ if (printWarn) {
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that the "mode" argument passed to a primitive array Release
+ * function is one of the valid values.
+ */
+ void checkReleaseMode(jint mode) {
+ if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
+ LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, mFunctionName);
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that the method's return type matches the type of call.
+ *
+ * "expectedSigByte" will be 'L' for all objects, including arrays.
+ */
+ void checkSig(jmethodID methodID, char expectedSigByte, bool isStatic) {
+ const Method* method = (const Method*) methodID;
+ bool printWarn = false;
+
+ if (expectedSigByte != method->shorty[0]) {
+ LOGW("JNI WARNING: expected return type '%c'", expectedSigByte);
+ printWarn = true;
+ } else if (isStatic && !dvmIsStaticMethod(method)) {
+ if (isStatic) {
+ LOGW("JNI WARNING: calling non-static method with static call");
+ } else {
+ LOGW("JNI WARNING: calling static method with non-static call");
+ }
+ printWarn = true;
+ }
+
+ if (printWarn) {
+ char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+ LOGW(" calling %s.%s %s", method->clazz->descriptor, method->name, desc);
+ free(desc);
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that this static field ID is valid for this class.
+ *
+ * Assumes "jclazz" has already been validated.
+ */
+ void checkStaticFieldID(jclass jclazz, jfieldID fieldID) {
+ ScopedJniThreadState ts(mEnv);
+ ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz);
+ StaticField* base = &clazz->sfields[0];
+ int fieldCount = clazz->sfieldCount;
+ if ((StaticField*) fieldID < base || (StaticField*) fieldID >= base + fieldCount) {
+ LOGW("JNI WARNING: static fieldID %p not valid for class %s",
+ fieldID, clazz->descriptor);
+ LOGW(" base=%p count=%d", base, fieldCount);
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that "methodID" is appropriate for "clazz".
+ *
+ * A mismatch isn't dangerous, because the jmethodID defines the class. In
+ * fact, jclazz is unused in the implementation. It's best if we don't
+ * allow bad code in the system though.
+ *
+ * Instances of "jclazz" must be instances of the method's declaring class.
+ */
+ void checkStaticMethod(jclass jclazz, jmethodID methodID) {
+ ScopedJniThreadState ts(mEnv);
+
+ ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz);
+ const Method* method = (const Method*) methodID;
+
+ if (!dvmInstanceof(clazz, method->clazz)) {
+ LOGW("JNI WARNING: can't call static %s.%s on class %s",
+ method->clazz->descriptor, method->name, clazz->descriptor);
+ showLocation();
+ // no abort?
+ }
+ }
+
+ void checkString(jstring s) {
+ checkInstance(s, gDvm.classJavaLangString, "jstring");
+ }
+
+ void checkClass(jclass c) {
+ checkInstance(c, gDvm.classJavaLangClass, "jclass");
+ }
+
+ /*
+ * Verify that "bytes" points to valid "modified UTF-8" data.
+ * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise,
+ * "identifier" is the name to use when reporting the null pointer.
+ */
+ void checkUtfString(const char* bytes, const char* identifier) {
+ if (bytes == NULL) {
+ if (identifier != NULL) {
+ LOGW("JNI WARNING: %s == NULL", identifier);
+ showLocation();
+ abortMaybe();
+ }
+ return;
+ }
+
+ const char* errorKind = NULL;
+ u1 utf8 = checkUtfBytes(bytes, &errorKind);
+ if (errorKind != NULL) {
+ LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte 0x%x", errorKind, utf8);
+ LOGW(" string: '%s'", bytes);
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that "methodID" is appropriate for "jobj".
+ *
+ * Make sure the object is an instance of the method's declaring class.
+ * (Note the methodID might point to a declaration in an interface; this
+ * will be handled automatically by the instanceof check.)
+ */
+ void checkVirtualMethod(jobject jobj, jmethodID methodID) {
+ ScopedJniThreadState ts(mEnv);
+
+ Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
+ const Method* method = (const Method*) methodID;
+
+ if (!dvmInstanceof(obj->clazz, method->clazz)) {
+ LOGW("JNI WARNING: can't call %s.%s on instance of %s",
+ method->clazz->descriptor, method->name, obj->clazz->descriptor);
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+private:
+ JNIEnv* mEnv;
+ const char* mFunctionName;
+
+ void checkThread(int flags) {
+ // Get the *correct* JNIEnv by going through our TLS pointer.
+ JNIEnvExt* threadEnv = dvmGetJNIEnvForThread();
+
+ /*
+ * Verify that the current thread is (a) attached and (b) associated with
+ * this particular instance of JNIEnv.
+ */
+ bool printWarn = false;
+ if (threadEnv == NULL) {
+ LOGE("JNI ERROR: non-VM thread making JNI calls");
+ // don't set printWarn -- it'll try to call showLocation()
+ dvmAbort();
+ } else if ((JNIEnvExt*) mEnv != threadEnv) {
+ if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
+ LOGE("JNI: threadEnv != thread->env?");
+ dvmAbort();
+ }
+
+ LOGW("JNI WARNING: threadid=%d using env from threadid=%d",
+ threadEnv->envThreadId, ((JNIEnvExt*) mEnv)->envThreadId);
+ printWarn = true;
+
+ /* this is a bad idea -- need to throw as we exit, or abort func */
+ //dvmThrowRuntimeException("invalid use of JNI env ptr");
+ } else if (((JNIEnvExt*) mEnv)->self != dvmThreadSelf()) {
+ /* correct JNIEnv*; make sure the "self" pointer is correct */
+ LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)",
+ ((JNIEnvExt*) mEnv)->self, dvmThreadSelf());
+ dvmAbort();
+ }
+
+ /*
+ * Verify that, if this thread previously made a critical "get" call, we
+ * do the corresponding "release" call before we try anything else.
+ */
+ switch (flags & kFlag_CritMask) {
+ case kFlag_CritOkay: // okay to call this method
+ break;
+ case kFlag_CritBad: // not okay to call
+ if (threadEnv->critical) {
+ LOGW("JNI WARNING: threadid=%d using JNI after critical get",
+ threadEnv->envThreadId);
+ printWarn = true;
+ }
+ break;
+ case kFlag_CritGet: // this is a "get" call
+ /* don't check here; we allow nested gets */
+ threadEnv->critical++;
+ break;
+ case kFlag_CritRelease: // this is a "release" call
+ threadEnv->critical--;
+ if (threadEnv->critical < 0) {
+ LOGW("JNI WARNING: threadid=%d called too many crit releases",
+ threadEnv->envThreadId);
+ printWarn = true;
+ }
+ break;
+ default:
+ assert(false);
+ }
+
+ /*
+ * Verify that, if an exception has been raised, the native code doesn't
+ * make any JNI calls other than the Exception* methods.
+ */
+ bool printException = false;
+ if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
+ LOGW("JNI WARNING: JNI method called with exception raised");
+ printWarn = true;
+ printException = true;
+ }
+
+ if (printWarn) {
+ showLocation();
+ }
+ if (printException) {
+ LOGW("Pending exception is:");
+ dvmLogExceptionStackTrace();
+ }
+ if (printWarn) {
+ abortMaybe();
+ }
+ }
+
+ /*
+ * Verify that "jobj" is a valid non-NULL object reference, and points to
+ * an instance of expectedClass.
+ *
+ * Because we're looking at an object on the GC heap, we have to switch
+ * to "running" mode before doing the checks.
+ */
+ void checkInstance(jobject jobj, ClassObject* expectedClass, const char* argName) {
+ if (jobj == NULL) {
+ LOGW("JNI WARNING: received null %s", argName);
+ showLocation();
+ abortMaybe();
+ return;
+ }
+
+ ScopedJniThreadState ts(mEnv);
+ bool printWarn = false;
+
+ Object* obj = dvmDecodeIndirectRef(mEnv, jobj);
+
+ if (!dvmIsValidObject(obj)) {
+ LOGW("JNI WARNING: %s is invalid %s ref (%p)",
+ argName, dvmIndirectRefTypeName(jobj), jobj);
+ printWarn = true;
+ } else if (obj->clazz != expectedClass) {
+ LOGW("JNI WARNING: %s arg has wrong type (expected %s, got %s)",
+ argName, expectedClass->descriptor, obj->clazz->descriptor);
+ printWarn = true;
+ }
+
+ if (printWarn) {
+ showLocation();
+ abortMaybe();
+ }
+ }
+
+ static u1 checkUtfBytes(const char* bytes, const char** errorKind) {
+ while (*bytes != '\0') {
+ u1 utf8 = *(bytes++);
+ // Switch on the high four bits.
+ switch (utf8 >> 4) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ // Bit pattern 0xxx. No need for any extra bytes.
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0f:
+ /*
+ * Bit pattern 10xx or 1111, which are illegal start bytes.
+ * Note: 1111 is valid for normal UTF-8, but not the
+ * modified UTF-8 used here.
+ */
+ *errorKind = "start";
+ return utf8;
+ case 0x0e:
+ // Bit pattern 1110, so there are two additional bytes.
+ utf8 = *(bytes++);
+ if ((utf8 & 0xc0) != 0x80) {
+ *errorKind = "continuation";
+ return utf8;
+ }
+ // Fall through to take care of the final byte.
+ case 0x0c:
+ case 0x0d:
+ // Bit pattern 110x, so there is one additional byte.
+ utf8 = *(bytes++);
+ if ((utf8 & 0xc0) != 0x80) {
+ *errorKind = "continuation";
+ return utf8;
+ }
+ break;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Returns a human-readable name for the given primitive type.
+ */
+ static const char* primitiveTypeToName(PrimitiveType primType) {
+ switch (primType) {
+ case PRIM_VOID: return "void";
+ case PRIM_BOOLEAN: return "boolean";
+ case PRIM_BYTE: return "byte";
+ case PRIM_SHORT: return "short";
+ case PRIM_CHAR: return "char";
+ case PRIM_INT: return "int";
+ case PRIM_LONG: return "long";
+ case PRIM_FLOAT: return "float";
+ case PRIM_DOUBLE: return "double";
+ case PRIM_NOT: return "Object/array";
+ default: return "???";
+ }
+ }
+
+ void showLocation() {
+ // mFunctionName looks like "Check_DeleteLocalRef"; we drop the "Check_".
+ const char* name = mFunctionName + 6;
+ const Method* method = dvmGetCurrentJNIMethod();
+ char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+ LOGW(" in %s.%s:%s (%s)", method->clazz->descriptor, method->name, desc, name);
+ free(desc);
+ }
+
+ // Disallow copy and assignment.
+ ScopedCheck(const ScopedCheck&);
+ void operator=(const ScopedCheck&);
+};
+
+/*
+ * ===========================================================================
+ * Guarded arrays
+ * ===========================================================================
+ */
+
+#define kGuardLen 512 /* must be multiple of 2 */
+#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
+#define kGuardMagic 0xffd5aa96
+
+/* this gets tucked in at the start of the buffer; struct size must be even */
+struct GuardedCopy {
+ u4 magic;
+ uLong adler;
+ size_t originalLen;
+ const void* originalPtr;
+
+ /* find the GuardedCopy given the pointer into the "live" data */
+ static inline const GuardedCopy* fromData(const void* dataBuf) {
+ return reinterpret_cast<const GuardedCopy*>(actualBuffer(dataBuf));
+ }
+
+ /*
+ * Create an over-sized buffer to hold the contents of "buf". Copy it in,
+ * filling in the area around it with guard data.
+ *
+ * We use a 16-bit pattern to make a rogue memset less likely to elude us.
+ */
+ static void* create(const void* buf, size_t len, bool modOkay) {
+ size_t newLen = actualLength(len);
+ u1* newBuf = debugAlloc(newLen);
+
+ /* fill it in with a pattern */
+ u2* pat = (u2*) newBuf;
+ for (size_t i = 0; i < newLen / 2; i++) {
+ *pat++ = kGuardPattern;
+ }
+
+ /* copy the data in; note "len" could be zero */
+ memcpy(newBuf + kGuardLen / 2, buf, len);
+
+ /* if modification is not expected, grab a checksum */
+ uLong adler = 0;
+ if (!modOkay) {
+ adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (const Bytef*)buf, len);
+ *(uLong*)newBuf = adler;
+ }
+
+ GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
+ pExtra->magic = kGuardMagic;
+ pExtra->adler = adler;
+ pExtra->originalPtr = buf;
+ pExtra->originalLen = len;
+
+ return newBuf + kGuardLen / 2;
+ }
+
+ /*
+ * Free up the guard buffer, scrub it, and return the original pointer.
+ */
+ static void* destroy(void* dataBuf) {
+ const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
+ void* originalPtr = (void*) pExtra->originalPtr;
+ size_t len = pExtra->originalLen;
+ debugFree(dataBuf, len);
+ return originalPtr;
+ }
+
+ /*
+ * Verify the guard area and, if "modOkay" is false, that the data itself
+ * has not been altered.
+ *
+ * The caller has already checked that "dataBuf" is non-NULL.
+ */
+ static bool check(const void* dataBuf, bool modOkay) {
+ static const u4 kMagicCmp = kGuardMagic;
+ const u1* fullBuf = actualBuffer(dataBuf);
+ const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf);
+
+ /*
+ * Before we do anything with "pExtra", check the magic number. We
+ * do the check with memcmp rather than "==" in case the pointer is
+ * unaligned. If it points to completely bogus memory we're going
+ * to crash, but there's no easy way around that.
+ */
+ if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
+ u1 buf[4];
+ memcpy(buf, &pExtra->magic, 4);
+ LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
+ buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
+ return false;
+ }
+
+ size_t len = pExtra->originalLen;
+
+ /* check bottom half of guard; skip over optional checksum storage */
+ const u2* pat = (u2*) fullBuf;
+ for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
+ if (pat[i] != kGuardPattern) {
+ LOGE("JNI: guard pattern(1) disturbed at %p + %d", fullBuf, i*2);
+ return false;
+ }
+ }
+
+ int offset = kGuardLen / 2 + len;
+ if (offset & 0x01) {
+ /* odd byte; expected value depends on endian-ness of host */
+ const u2 patSample = kGuardPattern;
+ if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
+ LOGE("JNI: guard pattern disturbed in odd byte after %p (+%d) 0x%02x 0x%02x",
+ fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
+ return false;
+ }
+ offset++;
+ }
+
+ /* check top half of guard */
+ pat = (u2*) (fullBuf + offset);
+ for (size_t i = 0; i < kGuardLen / 4; i++) {
+ if (pat[i] != kGuardPattern) {
+ LOGE("JNI: guard pattern(2) disturbed at %p + %d", fullBuf, offset + i*2);
+ return false;
+ }
+ }
+
+ /*
+ * If modification is not expected, verify checksum. Strictly speaking
+ * this is wrong: if we told the client that we made a copy, there's no
+ * reason they can't alter the buffer.
+ */
+ if (!modOkay) {
+ uLong adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (const Bytef*)dataBuf, len);
+ if (pExtra->adler != adler) {
+ LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p",
+ pExtra->adler, adler, dataBuf);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+private:
+ static u1* debugAlloc(size_t len) {
+ void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (result == MAP_FAILED) {
+ LOGE("GuardedCopy::create mmap(%d) failed: %s", len, strerror(errno));
+ dvmAbort();
+ }
+ return reinterpret_cast<u1*>(result);
+ }
+
+ static void debugFree(void* dataBuf, size_t len) {
+ u1* fullBuf = actualBuffer(dataBuf);
+ size_t totalByteCount = actualLength(len);
+ // TODO: we could mprotect instead, and keep the allocation around for a while.
+ // This would be even more expensive, but it might catch more errors.
+ // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
+ // LOGW("mprotect(PROT_NONE) failed: %s\n", strerror(errno));
+ // }
+ if (munmap(fullBuf, totalByteCount) != 0) {
+ LOGW("munmap failed: %s\n", strerror(errno));
+ dvmAbort();
+ }
+ }
+
+ static const u1* actualBuffer(const void* dataBuf) {
+ return reinterpret_cast<const u1*>(dataBuf) - kGuardLen / 2;
+ }
+
+ static u1* actualBuffer(void* dataBuf) {
+ return reinterpret_cast<u1*>(dataBuf) - kGuardLen / 2;
+ }
+
+ // Underlying length of a user allocation of 'length' bytes.
+ static size_t actualLength(size_t length) {
+ return (length + kGuardLen + 1) & ~0x01;
+ }
+};
+
+/*
+ * Return the width, in bytes, of a primitive type.
+ */
+static int dvmPrimitiveTypeWidth(PrimitiveType primType) {
+ switch (primType) {
+ case PRIM_BOOLEAN: return 1;
+ case PRIM_BYTE: return 1;
+ case PRIM_SHORT: return 2;
+ case PRIM_CHAR: return 2;
+ case PRIM_INT: return 4;
+ case PRIM_LONG: return 8;
+ case PRIM_FLOAT: return 4;
+ case PRIM_DOUBLE: return 8;
+ case PRIM_VOID:
+ default: {
+ assert(false);
+ return -1;
+ }
+ }
+}
+
+/*
+ * Create a guarded copy of a primitive array. Modifications to the copied
+ * data are allowed. Returns a pointer to the copied data.
+ */
+static void* createGuardedPACopy(JNIEnv* env, const jarray jarr, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
+
+ ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+ PrimitiveType primType = arrObj->clazz->elementClass->primitiveType;
+ int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
+ void* result = GuardedCopy::create(arrObj->contents, len, true);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ return result;
+}
+
+/*
+ * Perform the array "release" operation, which may or may not copy data
+ * back into the VM, and may or may not release the underlying storage.
+ */
+static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf, int mode) {
+ ScopedJniThreadState ts(env);
+ ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+
+ if (!GuardedCopy::check(dataBuf, true)) {
+ LOGE("JNI: failed guarded copy check in releaseGuardedPACopy");
+ abortMaybe();
+ return NULL;
+ }
+
+ if (mode != JNI_ABORT) {
+ size_t len = GuardedCopy::fromData(dataBuf)->originalLen;
+ memcpy(arrObj->contents, dataBuf, len);
+ }
+
+ u1* result = NULL;
+ if (mode != JNI_COMMIT) {
+ result = (u1*) GuardedCopy::destroy(dataBuf);
+ } else {
+ result = (u1*) (void*) GuardedCopy::fromData(dataBuf)->originalPtr;
+ }
+
+ /* pointer is to the array contents; back up to the array object */
+ result -= OFFSETOF_MEMBER(ArrayObject, contents);
+ return result;
+}
+
+
+/*
+ * ===========================================================================
+ * JNI functions
+ * ===========================================================================
+ */
+
+static jint Check_GetVersion(JNIEnv* env) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ return baseEnv(env)->GetVersion(env);
+}
+
+static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
+ const jbyte* buf, jsize bufLen)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(loader);
+ sc.checkUtfString(name, "name");
+ sc.checkClassName(name);
+ return baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
+}
+
+static jclass Check_FindClass(JNIEnv* env, const char* name) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkUtfString(name, "name");
+ sc.checkClassName(name);
+ return baseEnv(env)->FindClass(env, name);
+}
+
+static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->GetSuperclass(env, clazz);
+}
+
+static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz1);
+ sc.checkClass(clazz2);
+ return baseEnv(env)->IsAssignableFrom(env, clazz1, clazz2);
+}
+
+static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(method);
+ return baseEnv(env)->FromReflectedMethod(env, method);
+}
+
+static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(field);
+ return baseEnv(env)->FromReflectedField(env, field);
+}
+
+static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
+ jmethodID methodID, jboolean isStatic)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(cls);
+ return baseEnv(env)->ToReflectedMethod(env, cls, methodID, isStatic);
+}
+
+static jobject Check_ToReflectedField(JNIEnv* env, jclass cls,
+ jfieldID fieldID, jboolean isStatic)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(cls);
+ return baseEnv(env)->ToReflectedField(env, cls, fieldID, isStatic);
+}
+
+static jint Check_Throw(JNIEnv* env, jthrowable obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ /* TODO: verify that "obj" is an instance of Throwable */
+ return baseEnv(env)->Throw(env, obj);
+}
+
+static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ sc.checkUtfString(message, NULL);
+ return baseEnv(env)->ThrowNew(env, clazz, message);
+}
+
+static jthrowable Check_ExceptionOccurred(JNIEnv* env) {
+ ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
+ return baseEnv(env)->ExceptionOccurred(env);
+}
+
+static void Check_ExceptionDescribe(JNIEnv* env) {
+ ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
+ baseEnv(env)->ExceptionDescribe(env);
+}
+
+static void Check_ExceptionClear(JNIEnv* env) {
+ ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
+ baseEnv(env)->ExceptionClear(env);
+}
+
+static void Check_FatalError(JNIEnv* env, const char* msg) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkUtfString(msg, NULL);
+ baseEnv(env)->FatalError(env, msg);
+}
+
+static jint Check_PushLocalFrame(JNIEnv* env, jint capacity) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ return baseEnv(env)->PushLocalFrame(env, capacity);
+}
+
+static jobject Check_PopLocalFrame(JNIEnv* env, jobject res) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkObject(res);
+ return baseEnv(env)->PopLocalFrame(env, res);
+}
+
+static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->NewGlobalRef(env, obj);
+}
+
+static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkObject(globalRef);
+ if (globalRef != NULL && dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType) {
+ LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)",
+ globalRef, dvmGetJNIRefType(env, globalRef));
+ abortMaybe();
+ } else {
+ baseEnv(env)->DeleteGlobalRef(env, globalRef);
+ }
+}
+
+static jobject Check_NewLocalRef(JNIEnv* env, jobject ref) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(ref);
+ return baseEnv(env)->NewLocalRef(env, ref);
+}
+
+static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkObject(localRef);
+ if (localRef != NULL && dvmGetJNIRefType(env, localRef) != JNILocalRefType) {
+ LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)",
+ localRef, dvmGetJNIRefType(env, localRef));
+ abortMaybe();
+ } else {
+ baseEnv(env)->DeleteLocalRef(env, localRef);
+ }
+}
+
+static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ return baseEnv(env)->EnsureLocalCapacity(env, capacity);
+}
+
+static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(ref1);
+ sc.checkObject(ref2);
+ return baseEnv(env)->IsSameObject(env, ref1, ref2);
+}
+
+static jobject Check_AllocObject(JNIEnv* env, jclass clazz) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->AllocObject(env, clazz);
+}
+
+static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ va_list args;
+
+ va_start(args, methodID);
+ jobject result = baseEnv(env)->NewObjectV(env, clazz, methodID, args);
+ va_end(args);
+
+ return result;
+}
+
+static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->NewObjectV(env, clazz, methodID, args);
+}
+
+static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue* args) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->NewObjectA(env, clazz, methodID, args);
+}
+
+static jclass Check_GetObjectClass(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->GetObjectClass(env, obj);
+}
+
+static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ sc.checkClass(clazz);
+ return baseEnv(env)->IsInstanceOf(env, obj, clazz);
+}
+
+static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ sc.checkUtfString(name, "name");
+ sc.checkUtfString(sig, "sig");
+ return baseEnv(env)->GetMethodID(env, clazz, name, sig);
+}
+
+static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ sc.checkUtfString(name, "name");
+ sc.checkUtfString(sig, "sig");
+ return baseEnv(env)->GetFieldID(env, clazz, name, sig);
+}
+
+static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
+ const char* name, const char* sig)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ sc.checkUtfString(name, "name");
+ sc.checkUtfString(sig, "sig");
+ return baseEnv(env)->GetStaticMethodID(env, clazz, name, sig);
+}
+
+static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
+ const char* name, const char* sig)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ sc.checkUtfString(name, "name");
+ sc.checkUtfString(sig, "sig");
+ return baseEnv(env)->GetStaticFieldID(env, clazz, name, sig);
+}
+
+#define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
+ static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, jfieldID fieldID) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkStaticFieldID(clazz, fieldID); \
+ return baseEnv(env)->GetStatic##_jname##Field(env, clazz, fieldID); \
+ }
+GET_STATIC_TYPE_FIELD(jobject, Object);
+GET_STATIC_TYPE_FIELD(jboolean, Boolean);
+GET_STATIC_TYPE_FIELD(jbyte, Byte);
+GET_STATIC_TYPE_FIELD(jchar, Char);
+GET_STATIC_TYPE_FIELD(jshort, Short);
+GET_STATIC_TYPE_FIELD(jint, Int);
+GET_STATIC_TYPE_FIELD(jlong, Long);
+GET_STATIC_TYPE_FIELD(jfloat, Float);
+GET_STATIC_TYPE_FIELD(jdouble, Double);
+
+#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
+ static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
+ jfieldID fieldID, _ctype value) { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkStaticFieldID(clazz, fieldID); \
+ /* "value" arg only used when type == ref */ \
+ sc.checkFieldType((jobject)(u4)value, fieldID, _ftype, true); \
+ baseEnv(env)->SetStatic##_jname##Field(env, clazz, fieldID, value); \
+ }
+SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
+SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
+SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
+SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
+SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
+SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
+SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
+SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
+SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
+
+#define GET_TYPE_FIELD(_ctype, _jname) \
+ static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID) { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkObject(obj); \
+ sc.checkInstanceFieldID(obj, fieldID); \
+ return baseEnv(env)->Get##_jname##Field(env, obj, fieldID); \
+ }
+GET_TYPE_FIELD(jobject, Object);
+GET_TYPE_FIELD(jboolean, Boolean);
+GET_TYPE_FIELD(jbyte, Byte);
+GET_TYPE_FIELD(jchar, Char);
+GET_TYPE_FIELD(jshort, Short);
+GET_TYPE_FIELD(jint, Int);
+GET_TYPE_FIELD(jlong, Long);
+GET_TYPE_FIELD(jfloat, Float);
+GET_TYPE_FIELD(jdouble, Double);
+
+#define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
+ static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID, _ctype value) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkObject(obj); \
+ sc.checkInstanceFieldID(obj, fieldID); \
+ /* "value" arg only used when type == ref */ \
+ sc.checkFieldType((jobject)(u4) value, fieldID, _ftype, false); \
+ baseEnv(env)->Set##_jname##Field(env, obj, fieldID, value); \
+ }
+SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
+SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
+SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
+SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
+SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
+SET_TYPE_FIELD(jint, Int, PRIM_INT);
+SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
+SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
+SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
+
+#define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
+ static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
+ jmethodID methodID, ...) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ va_list args; \
+ va_start(args, methodID); \
+ _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID, \
+ args); \
+ va_end(args); \
+ return _retok; \
+ } \
+ static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
+ jmethodID methodID, va_list args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID, \
+ args); \
+ return _retok; \
+ } \
+ static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
+ jmethodID methodID, jvalue* args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->Call##_jname##MethodA(env, obj, methodID, \
+ args); \
+ return _retok; \
+ }
+CALL_VIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
+CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
+CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
+CALL_VIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C');
+CALL_VIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S');
+CALL_VIRTUAL(jint, Int, jint result, result=, (jint) result, 'I');
+CALL_VIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J');
+CALL_VIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
+CALL_VIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
+CALL_VIRTUAL(void, Void, , , , 'V');
+
+#define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
+ _retsig) \
+ static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
+ jobject obj, jclass clazz, jmethodID methodID, ...) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ va_list args; \
+ va_start(args, methodID); \
+ _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, \
+ clazz, methodID, args); \
+ va_end(args); \
+ return _retok; \
+ } \
+ static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
+ jobject obj, jclass clazz, jmethodID methodID, va_list args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, \
+ clazz, methodID, args); \
+ return _retok; \
+ } \
+ static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
+ jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkObject(obj); \
+ sc.checkSig(methodID, _retsig, false); \
+ sc.checkVirtualMethod(obj, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, \
+ clazz, methodID, args); \
+ return _retok; \
+ }
+CALL_NONVIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
+CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
+CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
+CALL_NONVIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C');
+CALL_NONVIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S');
+CALL_NONVIRTUAL(jint, Int, jint result, result=, (jint) result, 'I');
+CALL_NONVIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J');
+CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
+CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
+CALL_NONVIRTUAL(void, Void, , , , 'V');
+
+
+#define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
+ static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
+ jclass clazz, jmethodID methodID, ...) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkSig(methodID, _retsig, true); \
+ sc.checkStaticMethod(clazz, methodID); \
+ _retdecl; \
+ va_list args; \
+ va_start(args, methodID); \
+ _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, \
+ methodID, args); \
+ va_end(args); \
+ return _retok; \
+ } \
+ static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
+ jclass clazz, jmethodID methodID, va_list args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkSig(methodID, _retsig, true); \
+ sc.checkStaticMethod(clazz, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, \
+ methodID, args); \
+ return _retok; \
+ } \
+ static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
+ jclass clazz, jmethodID methodID, jvalue* args) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkClass(clazz); \
+ sc.checkSig(methodID, _retsig, true); \
+ sc.checkStaticMethod(clazz, methodID); \
+ _retdecl; \
+ _retasgn baseEnv(env)->CallStatic##_jname##MethodA(env, clazz, \
+ methodID, args); \
+ return _retok; \
+ }
+CALL_STATIC(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L');
+CALL_STATIC(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z');
+CALL_STATIC(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B');
+CALL_STATIC(jchar, Char, jchar result, result=, (jchar) result, 'C');
+CALL_STATIC(jshort, Short, jshort result, result=, (jshort) result, 'S');
+CALL_STATIC(jint, Int, jint result, result=, (jint) result, 'I');
+CALL_STATIC(jlong, Long, jlong result, result=, (jlong) result, 'J');
+CALL_STATIC(jfloat, Float, jfloat result, result=, (jfloat) result, 'F');
+CALL_STATIC(jdouble, Double, jdouble result, result=, (jdouble) result, 'D');
+CALL_STATIC(void, Void, , , , 'V');
+
+static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ return baseEnv(env)->NewString(env, unicodeChars, len);
+}
+
+static jsize Check_GetStringLength(JNIEnv* env, jstring string) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(string);
+ return baseEnv(env)->GetStringLength(env, string);
+}
+
+static const jchar* Check_GetStringChars(JNIEnv* env, jstring string, jboolean* isCopy) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(string);
+ const jchar* result = baseEnv(env)->GetStringChars(env, string, isCopy);
+ if (gDvmJni.forceCopy && result != NULL) {
+ ScopedJniThreadState ts(env);
+ StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
+ int byteCount = dvmStringLen(strObj) * 2;
+ result = (const jchar*) GuardedCopy::create(result, byteCount, false);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ }
+ return result;
+}
+
+static void Check_ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkString(string);
+ sc.checkNonNull(chars);
+ if (gDvmJni.forceCopy) {
+ if (!GuardedCopy::check(chars, false)) {
+ LOGE("JNI: failed guarded copy check in ReleaseStringChars");
+ abortMaybe();
+ return;
+ }
+ chars = (const jchar*) GuardedCopy::destroy((jchar*)chars);
+ }
+ baseEnv(env)->ReleaseStringChars(env, string, chars);
+}
+
+static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkUtfString(bytes, NULL);
+ return baseEnv(env)->NewStringUTF(env, bytes);
+}
+
+static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(string);
+ return baseEnv(env)->GetStringUTFLength(env, string);
+}
+
+static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(string);
+ const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
+ if (gDvmJni.forceCopy && result != NULL) {
+ result = (const char*) GuardedCopy::create(result, strlen(result) + 1, false);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ }
+ return result;
+}
+
+static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
+ ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkString(string);
+ sc.checkNonNull(utf);
+ if (gDvmJni.forceCopy) {
+ if (!GuardedCopy::check(utf, false)) {
+ LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars");
+ abortMaybe();
+ return;
+ }
+ utf = (const char*) GuardedCopy::destroy((char*)utf);
+ }
+ baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
+}
+
+static jsize Check_GetArrayLength(JNIEnv* env, jarray array) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkArray(array);
+ return baseEnv(env)->GetArrayLength(env, array);
+}
+
+static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
+ jclass elementClass, jobject initialElement)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(elementClass);
+ sc.checkObject(initialElement);
+ sc.checkLengthPositive(length);
+ return baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement);
+}
+
+static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkArray(array);
+ return baseEnv(env)->GetObjectArrayElement(env, array, index);
+}
+
+static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkArray(array);
+ baseEnv(env)->SetObjectArrayElement(env, array, index, value);
+}
+
+#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
+ static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkLengthPositive(length); \
+ return baseEnv(env)->New##_jname##Array(env, length); \
+ }
+NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
+NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
+NEW_PRIMITIVE_ARRAY(jcharArray, Char);
+NEW_PRIMITIVE_ARRAY(jshortArray, Short);
+NEW_PRIMITIVE_ARRAY(jintArray, Int);
+NEW_PRIMITIVE_ARRAY(jlongArray, Long);
+NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
+NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
+
+
+/*
+ * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
+ * The code deliberately uses an invalid sequence of operations, so we
+ * need to pass it through unmodified. Review that code before making
+ * any changes here.
+ */
+#define kNoCopyMagic 0xd5aab57f
+
+#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
+ static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
+ _ctype##Array array, jboolean* isCopy) \
+ { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkArray(array); \
+ u4 noCopy = 0; \
+ if (gDvmJni.forceCopy && isCopy != NULL) { \
+ /* capture this before the base call tramples on it */ \
+ noCopy = *(u4*) isCopy; \
+ } \
+ _ctype* result = baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy); \
+ if (gDvmJni.forceCopy && result != NULL) { \
+ if (noCopy == kNoCopyMagic) { \
+ LOGV("FC: not copying %p %x", array, noCopy); \
+ } else { \
+ result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
+ } \
+ } \
+ return result; \
+ }
+
+#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
+ static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
+ _ctype##Array array, _ctype* elems, jint mode) \
+ { \
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); \
+ sc.checkArray(array); \
+ sc.checkNonNull(elems); \
+ sc.checkReleaseMode(mode); \
+ if (gDvmJni.forceCopy) { \
+ if ((uintptr_t)elems == kNoCopyMagic) { \
+ LOGV("FC: not freeing %p", array); \
+ elems = NULL; /* base JNI call doesn't currently need */ \
+ } else { \
+ elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \
+ mode); \
+ } \
+ } \
+ baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
+ }
+
+#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
+ static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
+ _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkArray(array); \
+ baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
+ }
+
+#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
+ static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
+ _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \
+ sc.checkArray(array); \
+ baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
+ }
+
+#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
+ GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
+ RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
+ GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
+ SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
+
+/* TODO: verify primitive array type matches call type */
+PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
+PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
+PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
+PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
+PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
+PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
+PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
+PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
+
+static jint Check_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods,
+ jint nMethods)
+{
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->RegisterNatives(env, clazz, methods, nMethods);
+}
+
+static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkClass(clazz);
+ return baseEnv(env)->UnregisterNatives(env, clazz);
+}
+
+static jint Check_MonitorEnter(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->MonitorEnter(env, obj);
+}
+
+static jint Check_MonitorExit(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->MonitorExit(env, obj);
+}
+
+static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ return baseEnv(env)->GetJavaVM(env, vm);
+}
+
+static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(str);
+ baseEnv(env)->GetStringRegion(env, str, start, len, buf);
+}
+
+static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
+ ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__);
+ sc.checkString(str);
+ baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
+}
+
+static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
+ ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__);
+ sc.checkArray(array);
+ void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
+ if (gDvmJni.forceCopy && result != NULL) {
+ result = createGuardedPACopy(env, array, isCopy);
+ }
+ return result;
+}
+
+static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode)
+{
+ ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkArray(array);
+ sc.checkNonNull(carray);
+ sc.checkReleaseMode(mode);
+ if (gDvmJni.forceCopy) {
+ carray = releaseGuardedPACopy(env, array, carray, mode);
+ }
+ baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
+}
+
+static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string, jboolean* isCopy) {
+ ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__);
+ sc.checkString(string);
+ const jchar* result = baseEnv(env)->GetStringCritical(env, string, isCopy);
+ if (gDvmJni.forceCopy && result != NULL) {
+ ScopedJniThreadState ts(env);
+ StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string);
+ int byteCount = dvmStringLen(strObj) * 2;
+ result = (const jchar*) GuardedCopy::create(result, byteCount, false);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ }
+ return result;
+}
+
+static void Check_ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
+ ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkString(string);
+ sc.checkNonNull(carray);
+ if (gDvmJni.forceCopy) {
+ if (!GuardedCopy::check(carray, false)) {
+ LOGE("JNI: failed guarded copy check in ReleaseStringCritical");
+ abortMaybe();
+ return;
+ }
+ carray = (const jchar*) GuardedCopy::destroy((jchar*)carray);
+ }
+ baseEnv(env)->ReleaseStringCritical(env, string, carray);
+}
+
+static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->NewWeakGlobalRef(env, obj);
+}
+
+static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
+ ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__);
+ sc.checkObject(obj);
+ baseEnv(env)->DeleteWeakGlobalRef(env, obj);
+}
+
+static jboolean Check_ExceptionCheck(JNIEnv* env) {
+ ScopedCheck sc(env, kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
+ return baseEnv(env)->ExceptionCheck(env);
+}
+
+static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(obj);
+ return baseEnv(env)->GetObjectRefType(env, obj);
+}
+
+static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ if (address == NULL || capacity < 0) {
+ LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)",
+ address, (long) capacity);
+ abortMaybe();
+ return NULL;
+ }
+ return baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
+}
+
+static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(buf);
+ return baseEnv(env)->GetDirectBufferAddress(env, buf);
+}
+
+static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
+ ScopedCheck sc(env, kFlag_Default, __FUNCTION__);
+ sc.checkObject(buf);
+ /* TODO: verify "buf" is an instance of java.nio.Buffer */
+ return baseEnv(env)->GetDirectBufferCapacity(env, buf);
+}
+
+
+/*
+ * ===========================================================================
+ * JNI invocation functions
+ * ===========================================================================
+ */
+
+static jint Check_DestroyJavaVM(JavaVM* vm) {
+ ScopedVmCheck svc(false, __FUNCTION__);
+ return baseVm(vm)->DestroyJavaVM(vm);
+}
+
+static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
+ ScopedVmCheck svc(false, __FUNCTION__);
+ return baseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
+}
+
+static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
+ ScopedVmCheck svc(false, __FUNCTION__);
+ return baseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
+}
+
+static jint Check_DetachCurrentThread(JavaVM* vm) {
+ ScopedVmCheck svc(true, __FUNCTION__);
+ return baseVm(vm)->DetachCurrentThread(vm);
+}
+
+static jint Check_GetEnv(JavaVM* vm, void** env, jint version) {
+ ScopedVmCheck svc(true, __FUNCTION__);
+ return baseVm(vm)->GetEnv(vm, env, version);
+}
+
+
+/*
+ * ===========================================================================
+ * Function tables
+ * ===========================================================================
+ */
+
+static const struct JNINativeInterface gCheckNativeInterface = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ Check_GetVersion,
+
+ Check_DefineClass,
+ Check_FindClass,
+
+ Check_FromReflectedMethod,
+ Check_FromReflectedField,
+ Check_ToReflectedMethod,
+
+ Check_GetSuperclass,
+ Check_IsAssignableFrom,
+
+ Check_ToReflectedField,
+
+ Check_Throw,
+ Check_ThrowNew,
+ Check_ExceptionOccurred,
+ Check_ExceptionDescribe,
+ Check_ExceptionClear,
+ Check_FatalError,
+
+ Check_PushLocalFrame,
+ Check_PopLocalFrame,
+
+ Check_NewGlobalRef,
+ Check_DeleteGlobalRef,
+ Check_DeleteLocalRef,
+ Check_IsSameObject,
+ Check_NewLocalRef,
+ Check_EnsureLocalCapacity,
+
+ Check_AllocObject,
+ Check_NewObject,
+ Check_NewObjectV,
+ Check_NewObjectA,
+
+ Check_GetObjectClass,
+ Check_IsInstanceOf,
+
+ Check_GetMethodID,
+
+ Check_CallObjectMethod,
+ Check_CallObjectMethodV,
+ Check_CallObjectMethodA,
+ Check_CallBooleanMethod,
+ Check_CallBooleanMethodV,
+ Check_CallBooleanMethodA,
+ Check_CallByteMethod,
+ Check_CallByteMethodV,
+ Check_CallByteMethodA,
+ Check_CallCharMethod,
+ Check_CallCharMethodV,
+ Check_CallCharMethodA,
+ Check_CallShortMethod,
+ Check_CallShortMethodV,
+ Check_CallShortMethodA,
+ Check_CallIntMethod,
+ Check_CallIntMethodV,
+ Check_CallIntMethodA,
+ Check_CallLongMethod,
+ Check_CallLongMethodV,
+ Check_CallLongMethodA,
+ Check_CallFloatMethod,
+ Check_CallFloatMethodV,
+ Check_CallFloatMethodA,
+ Check_CallDoubleMethod,
+ Check_CallDoubleMethodV,
+ Check_CallDoubleMethodA,
+ Check_CallVoidMethod,
+ Check_CallVoidMethodV,
+ Check_CallVoidMethodA,
+
+ Check_CallNonvirtualObjectMethod,
+ Check_CallNonvirtualObjectMethodV,
+ Check_CallNonvirtualObjectMethodA,
+ Check_CallNonvirtualBooleanMethod,
+ Check_CallNonvirtualBooleanMethodV,
+ Check_CallNonvirtualBooleanMethodA,
+ Check_CallNonvirtualByteMethod,
+ Check_CallNonvirtualByteMethodV,
+ Check_CallNonvirtualByteMethodA,
+ Check_CallNonvirtualCharMethod,
+ Check_CallNonvirtualCharMethodV,
+ Check_CallNonvirtualCharMethodA,
+ Check_CallNonvirtualShortMethod,
+ Check_CallNonvirtualShortMethodV,
+ Check_CallNonvirtualShortMethodA,
+ Check_CallNonvirtualIntMethod,
+ Check_CallNonvirtualIntMethodV,
+ Check_CallNonvirtualIntMethodA,
+ Check_CallNonvirtualLongMethod,
+ Check_CallNonvirtualLongMethodV,
+ Check_CallNonvirtualLongMethodA,
+ Check_CallNonvirtualFloatMethod,
+ Check_CallNonvirtualFloatMethodV,
+ Check_CallNonvirtualFloatMethodA,
+ Check_CallNonvirtualDoubleMethod,
+ Check_CallNonvirtualDoubleMethodV,
+ Check_CallNonvirtualDoubleMethodA,
+ Check_CallNonvirtualVoidMethod,
+ Check_CallNonvirtualVoidMethodV,
+ Check_CallNonvirtualVoidMethodA,
+
+ Check_GetFieldID,
+
+ Check_GetObjectField,
+ Check_GetBooleanField,
+ Check_GetByteField,
+ Check_GetCharField,
+ Check_GetShortField,
+ Check_GetIntField,
+ Check_GetLongField,
+ Check_GetFloatField,
+ Check_GetDoubleField,
+ Check_SetObjectField,
+ Check_SetBooleanField,
+ Check_SetByteField,
+ Check_SetCharField,
+ Check_SetShortField,
+ Check_SetIntField,
+ Check_SetLongField,
+ Check_SetFloatField,
+ Check_SetDoubleField,
+
+ Check_GetStaticMethodID,
+
+ Check_CallStaticObjectMethod,
+ Check_CallStaticObjectMethodV,
+ Check_CallStaticObjectMethodA,
+ Check_CallStaticBooleanMethod,
+ Check_CallStaticBooleanMethodV,
+ Check_CallStaticBooleanMethodA,
+ Check_CallStaticByteMethod,
+ Check_CallStaticByteMethodV,
+ Check_CallStaticByteMethodA,
+ Check_CallStaticCharMethod,
+ Check_CallStaticCharMethodV,
+ Check_CallStaticCharMethodA,
+ Check_CallStaticShortMethod,
+ Check_CallStaticShortMethodV,
+ Check_CallStaticShortMethodA,
+ Check_CallStaticIntMethod,
+ Check_CallStaticIntMethodV,
+ Check_CallStaticIntMethodA,
+ Check_CallStaticLongMethod,
+ Check_CallStaticLongMethodV,
+ Check_CallStaticLongMethodA,
+ Check_CallStaticFloatMethod,
+ Check_CallStaticFloatMethodV,
+ Check_CallStaticFloatMethodA,
+ Check_CallStaticDoubleMethod,
+ Check_CallStaticDoubleMethodV,
+ Check_CallStaticDoubleMethodA,
+ Check_CallStaticVoidMethod,
+ Check_CallStaticVoidMethodV,
+ Check_CallStaticVoidMethodA,
+
+ Check_GetStaticFieldID,
+
+ Check_GetStaticObjectField,
+ Check_GetStaticBooleanField,
+ Check_GetStaticByteField,
+ Check_GetStaticCharField,
+ Check_GetStaticShortField,
+ Check_GetStaticIntField,
+ Check_GetStaticLongField,
+ Check_GetStaticFloatField,
+ Check_GetStaticDoubleField,
+
+ Check_SetStaticObjectField,
+ Check_SetStaticBooleanField,
+ Check_SetStaticByteField,
+ Check_SetStaticCharField,
+ Check_SetStaticShortField,
+ Check_SetStaticIntField,
+ Check_SetStaticLongField,
+ Check_SetStaticFloatField,
+ Check_SetStaticDoubleField,
+
+ Check_NewString,
+
+ Check_GetStringLength,
+ Check_GetStringChars,
+ Check_ReleaseStringChars,
+
+ Check_NewStringUTF,
+ Check_GetStringUTFLength,
+ Check_GetStringUTFChars,
+ Check_ReleaseStringUTFChars,
+
+ Check_GetArrayLength,
+ Check_NewObjectArray,
+ Check_GetObjectArrayElement,
+ Check_SetObjectArrayElement,
+
+ Check_NewBooleanArray,
+ Check_NewByteArray,
+ Check_NewCharArray,
+ Check_NewShortArray,
+ Check_NewIntArray,
+ Check_NewLongArray,
+ Check_NewFloatArray,
+ Check_NewDoubleArray,
+
+ Check_GetBooleanArrayElements,
+ Check_GetByteArrayElements,
+ Check_GetCharArrayElements,
+ Check_GetShortArrayElements,
+ Check_GetIntArrayElements,
+ Check_GetLongArrayElements,
+ Check_GetFloatArrayElements,
+ Check_GetDoubleArrayElements,
+
+ Check_ReleaseBooleanArrayElements,
+ Check_ReleaseByteArrayElements,
+ Check_ReleaseCharArrayElements,
+ Check_ReleaseShortArrayElements,
+ Check_ReleaseIntArrayElements,
+ Check_ReleaseLongArrayElements,
+ Check_ReleaseFloatArrayElements,
+ Check_ReleaseDoubleArrayElements,
+
+ Check_GetBooleanArrayRegion,
+ Check_GetByteArrayRegion,
+ Check_GetCharArrayRegion,
+ Check_GetShortArrayRegion,
+ Check_GetIntArrayRegion,
+ Check_GetLongArrayRegion,
+ Check_GetFloatArrayRegion,
+ Check_GetDoubleArrayRegion,
+ Check_SetBooleanArrayRegion,
+ Check_SetByteArrayRegion,
+ Check_SetCharArrayRegion,
+ Check_SetShortArrayRegion,
+ Check_SetIntArrayRegion,
+ Check_SetLongArrayRegion,
+ Check_SetFloatArrayRegion,
+ Check_SetDoubleArrayRegion,
+
+ Check_RegisterNatives,
+ Check_UnregisterNatives,
+
+ Check_MonitorEnter,
+ Check_MonitorExit,
+
+ Check_GetJavaVM,
+
+ Check_GetStringRegion,
+ Check_GetStringUTFRegion,
+
+ Check_GetPrimitiveArrayCritical,
+ Check_ReleasePrimitiveArrayCritical,
+
+ Check_GetStringCritical,
+ Check_ReleaseStringCritical,
+
+ Check_NewWeakGlobalRef,
+ Check_DeleteWeakGlobalRef,
+
+ Check_ExceptionCheck,
+
+ Check_NewDirectByteBuffer,
+ Check_GetDirectBufferAddress,
+ Check_GetDirectBufferCapacity,
+
+ Check_GetObjectRefType
+};
+
+static const struct JNIInvokeInterface gCheckInvokeInterface = {
+ NULL,
+ NULL,
+ NULL,
+
+ Check_DestroyJavaVM,
+ Check_AttachCurrentThread,
+ Check_DetachCurrentThread,
+
+ Check_GetEnv,
+
+ Check_AttachCurrentThreadAsDaemon,
+};
+
+/*
+ * Replace the normal table with the checked table.
+ */
+void dvmUseCheckedJniEnv(JNIEnvExt* pEnv) {
+ assert(pEnv->funcTable != &gCheckNativeInterface);
+ pEnv->baseFuncTable = pEnv->funcTable;
+ pEnv->funcTable = &gCheckNativeInterface;
+}
+
+/*
+ * Replace the normal table with the checked table.
+ */
+void dvmUseCheckedJniVm(JavaVMExt* pVm) {
+ assert(pVm->funcTable != &gCheckInvokeInterface);
+ pVm->baseFuncTable = pVm->funcTable;
+ pVm->funcTable = &gCheckInvokeInterface;
+}
diff --git a/vm/Common.h b/vm/Common.h
index 7d8424e..8e73cd0 100644
--- a/vm/Common.h
+++ b/vm/Common.h
@@ -24,8 +24,12 @@
# define LOG_TAG "dalvikvm"
#endif
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <assert.h>
+#include <endian.h>
+#include "utils/Log.h"
#if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
# undef assert
@@ -67,8 +71,6 @@
/*
* These match the definitions in the VM specification.
*/
-#ifdef HAVE_STDINT_H
-# include <stdint.h> /* C99 */
typedef uint8_t u1;
typedef uint16_t u2;
typedef uint32_t u4;
@@ -77,16 +79,6 @@
typedef int16_t s2;
typedef int32_t s4;
typedef int64_t s8;
-#else
-typedef unsigned char u1;
-typedef unsigned short u2;
-typedef unsigned int u4;
-typedef unsigned long long u8;
-typedef signed char s1;
-typedef signed short s2;
-typedef signed int s4;
-typedef signed long long s8;
-#endif
/*
* Storage for primitive types and object references.
@@ -96,7 +88,9 @@
* yield the same result. This seems to be guaranteed by gcc on big- and
* little-endian systems.
*/
-typedef union JValue {
+struct Object;
+
+union JValue {
u1 z;
s1 b;
u2 c;
@@ -105,58 +99,14 @@
s8 j;
float f;
double d;
- void* l;
-} JValue;
+ Object* l;
+};
-/*
- * The <stdbool.h> definition uses _Bool, a type known to the compiler.
- */
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h> /* C99 */
-#else
-# ifndef __bool_true_false_are_defined
-typedef enum { false=0, true=!false } bool;
-# define __bool_true_false_are_defined 1
-# endif
-#endif
+#define OFFSETOF_MEMBER(t, f) \
+ (reinterpret_cast<char*>( \
+ &reinterpret_cast<t*>(16)->f) - \
+ reinterpret_cast<char*>(16))
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
-
-#if defined(HAVE_ENDIAN_H)
-# include <endian.h>
-#else /*not HAVE_ENDIAN_H*/
-# define __BIG_ENDIAN 4321
-# define __LITTLE_ENDIAN 1234
-# if defined(HAVE_LITTLE_ENDIAN)
-# define __BYTE_ORDER __LITTLE_ENDIAN
-# else
-# define __BYTE_ORDER __BIG_ENDIAN
-# endif
-#endif /*not HAVE_ENDIAN_H*/
-
-
-#if 0
-/*
- * Pretend we have the Android logging macros. These are replaced by the
- * Android logging implementation.
- */
-#define ANDROID_LOG_DEBUG 3
-#define LOGV(...) LOG_PRI(2, 0, __VA_ARGS__)
-#define LOGD(...) LOG_PRI(3, 0, __VA_ARGS__)
-#define LOGI(...) LOG_PRI(4, 0, __VA_ARGS__)
-#define LOGW(...) LOG_PRI(5, 0, __VA_ARGS__)
-#define LOGE(...) LOG_PRI(6, 0, __VA_ARGS__)
-#define MIN_LOG_LEVEL 2
-
-#define LOG_PRI(priority, tag, ...) do { \
- if (priority >= MIN_LOG_LEVEL) { \
- dvmFprintf(stdout, "%s:%-4d ", __FILE__, __LINE__); \
- dvmFprintf(stdout, __VA_ARGS__); \
- } \
- } while(0)
-#else
-# include "utils/Log.h"
-#endif
-
#endif /*_DALVIK_COMMON*/
diff --git a/vm/Dalvik.h b/vm/Dalvik.h
index 534ea2d..a47388a 100644
--- a/vm/Dalvik.h
+++ b/vm/Dalvik.h
@@ -20,8 +20,6 @@
#ifndef _DALVIK_DALVIK
#define _DALVIK_DALVIK
-#include <pthread.h>
-
#include "Common.h"
#include "Inlines.h"
#include "Misc.h"
diff --git a/vm/Ddm.c b/vm/Ddm.cpp
similarity index 97%
rename from vm/Ddm.c
rename to vm/Ddm.cpp
index 1251fe2..4bb2bb1 100644
--- a/vm/Ddm.c
+++ b/vm/Ddm.cpp
@@ -192,7 +192,7 @@
*
* We can do some initialization here too.
*/
-void dvmDdmConnected(void)
+void dvmDdmConnected()
{
// TODO: any init
@@ -205,7 +205,7 @@
*
* Do some cleanup.
*/
-void dvmDdmDisconnected(void)
+void dvmDdmDisconnected()
{
LOGV("Broadcasting DDM disconnect\n");
broadcast(DISCONNECTED);
@@ -284,7 +284,7 @@
set4BE(&buf[0x04], stringLen);
/* copy the UTF-16 string, transforming to big-endian */
- outChars = (u2*) &buf[0x08];
+ outChars = (u2*)(void*)&buf[0x08];
while (stringLen--)
set2BE((u1*) (outChars++), *chars++);
} else {
@@ -320,7 +320,7 @@
set4BE(&buf[0x00], threadId);
set4BE(&buf[0x04], stringLen);
- u2* outChars = (u2*) &buf[0x08];
+ u2* outChars = (u2*)(void*)&buf[0x08];
while (stringLen--)
set2BE((u1*) (outChars++), *chars++);
@@ -351,7 +351,7 @@
* Returns a new byte[] with the data inside, or NULL on failure. The
* caller must call dvmReleaseTrackedAlloc() on the array.
*/
-ArrayObject* dvmDdmGenerateThreadStats(void)
+ArrayObject* dvmDdmGenerateThreadStats()
{
const int kHeaderLen = 4;
const int kBytesPerEntry = 18;
@@ -462,7 +462,7 @@
*
* Returns NULL on failure with an exception raised.
*/
-ArrayObject* dvmDdmGetRecentAllocations(void)
+ArrayObject* dvmDdmGetRecentAllocations()
{
u1* data;
size_t len;
diff --git a/vm/Debugger.c b/vm/Debugger.cpp
similarity index 96%
rename from vm/Debugger.c
rename to vm/Debugger.cpp
index f7e35d9..fe1bedb 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.cpp
@@ -95,7 +95,7 @@
* System init. We don't allocate the registry until first use.
* Make sure we do this before initializing JDWP.
*/
-bool dvmDebuggerStartup(void)
+bool dvmDebuggerStartup()
{
if (!dvmBreakpointStartup())
return false;
@@ -107,7 +107,7 @@
/*
* Free registry storage.
*/
-void dvmDebuggerShutdown(void)
+void dvmDebuggerShutdown()
{
dvmHashTableFree(gDvm.dbgRegistry);
gDvm.dbgRegistry = NULL;
@@ -153,9 +153,9 @@
/* keep track of type, in case we need to distinguish them someday */
-typedef enum RegistryType {
+enum RegistryType {
kObjectId = 0xc1, kRefTypeId
-} RegistryType;
+};
/*
* Hash function for object IDs. Since objects are at least 8 bytes, and
@@ -229,7 +229,7 @@
goto bail;
}
- (void) dvmHashTableLookup(gDvm.dbgRegistry, registryHash((u4) id),
+ dvmHashTableLookup(gDvm.dbgRegistry, registryHash((u4) id),
(void*)(u4) id, registryCompare, true);
bail:
@@ -364,7 +364,7 @@
/*
* Get the invocation request state.
*/
-DebugInvokeReq* dvmDbgGetInvokeReq(void)
+DebugInvokeReq* dvmDbgGetInvokeReq()
{
return &dvmThreadSelf()->invokeReq;
}
@@ -374,7 +374,7 @@
*
* Only called from the JDWP handler thread.
*/
-void dvmDbgConnected(void)
+void dvmDbgConnected()
{
assert(!gDvm.debuggerConnected);
@@ -390,7 +390,7 @@
*
* Only called from the JDWP handler thread.
*/
-void dvmDbgActive(void)
+void dvmDbgActive()
{
if (gDvm.debuggerActive)
return;
@@ -398,7 +398,7 @@
LOGI("Debugger is active\n");
dvmInitBreakpoints();
gDvm.debuggerActive = true;
- dvmUpdateAllInterpBreak(kInterpDebugBreak, kSubModeDebuggerActive, true);
+ dvmEnableAllSubMode(kSubModeDebuggerActive);
#if defined(WITH_JIT)
dvmCompilerUpdateGlobalState();
#endif
@@ -412,12 +412,12 @@
*
* Only called from the JDWP handler thread.
*/
-void dvmDbgDisconnected(void)
+void dvmDbgDisconnected()
{
assert(gDvm.debuggerConnected);
gDvm.debuggerActive = false;
- dvmUpdateAllInterpBreak(kInterpDebugBreak, kSubModeDebuggerActive, false);
+ dvmDisableAllSubMode(kSubModeDebuggerActive);
#if defined(WITH_JIT)
dvmCompilerUpdateGlobalState();
#endif
@@ -440,7 +440,7 @@
*
* Does not return "true" if it's just a DDM server.
*/
-bool dvmDbgIsDebuggerConnected(void)
+bool dvmDbgIsDebuggerConnected()
{
return gDvm.debuggerActive;
}
@@ -449,7 +449,7 @@
* Get time since last debugger activity. Used when figuring out if the
* debugger has finished configuring us.
*/
-s8 dvmDbgLastDebuggerActivity(void)
+s8 dvmDbgLastDebuggerActivity()
{
return dvmJdwpLastDebuggerActivity(gDvm.jdwpState);
}
@@ -457,17 +457,19 @@
/*
* JDWP thread is running, don't allow GC.
*/
-int dvmDbgThreadRunning(void)
+int dvmDbgThreadRunning()
{
- return dvmChangeStatus(NULL, THREAD_RUNNING);
+ ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_RUNNING);
+ return static_cast<int>(oldStatus);
}
/*
* JDWP thread is idle, allow GC.
*/
-int dvmDbgThreadWaiting(void)
+int dvmDbgThreadWaiting()
{
- return dvmChangeStatus(NULL, THREAD_VMWAIT);
+ ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
+ return static_cast<int>(oldStatus);
}
/*
@@ -475,7 +477,9 @@
*/
int dvmDbgThreadContinuing(int status)
{
- return dvmChangeStatus(NULL, status);
+ ThreadStatus newStatus = static_cast<ThreadStatus>(status);
+ ThreadStatus oldStatus = dvmChangeStatus(NULL, newStatus);
+ return static_cast<int>(oldStatus);
}
/*
@@ -490,10 +494,6 @@
dvmDumpAtomicCacheStats(gDvm.instanceofCache);
dvmDumpBootClassPath();
}
-#ifdef PROFILE_FIELD_ACCESS
- dvmDumpFieldAccessCounts();
-#endif
-
exit(status);
}
@@ -810,7 +810,7 @@
if (clazz == gDvm.classJavaLangString) {
return JT_STRING;
- } else if (clazz == gDvm.classJavaLangClass) {
+ } else if (dvmIsTheClassClass(clazz)) {
return JT_CLASS_OBJECT;
} else if (dvmInstanceof(clazz, gDvm.classJavaLangThread)) {
return JT_THREAD;
@@ -913,7 +913,7 @@
{
ArrayObject* arrayObj = (ArrayObject*) objectIdToObject(arrayId);
- ClassObject* arrayClass = arrayObj->obj.clazz;
+ ClassObject* arrayClass = arrayObj->clazz;
u1 tag = basicTagFromDescriptor(arrayClass->descriptor + 1);
if (!isTagPrimitive(tag)) {
/* try to refine it */
@@ -1001,7 +1001,7 @@
return false;
}
- tag = basicTagFromDescriptor(arrayObj->obj.clazz->descriptor + 1);
+ tag = basicTagFromDescriptor(arrayObj->clazz->descriptor + 1);
if (isTagPrimitive(tag)) {
int width = dvmDbgGetTagWidth(tag);
@@ -1052,7 +1052,7 @@
return false;
}
- tag = basicTagFromDescriptor(arrayObj->obj.clazz->descriptor + 1);
+ tag = basicTagFromDescriptor(arrayObj->clazz->descriptor + 1);
if (isTagPrimitive(tag)) {
int width = dvmDbgGetTagWidth(tag);
@@ -1173,36 +1173,32 @@
void dvmDbgOutputAllFields(RefTypeId refTypeId, bool withGeneric,
ExpandBuf* pReply)
{
- static const u1 genericSignature[1] = "";
- ClassObject* clazz;
- Field* field;
- u4 declared;
- int i;
-
- clazz = refTypeIdToClassObject(refTypeId);
+ ClassObject* clazz = refTypeIdToClassObject(refTypeId);
assert(clazz != NULL);
- declared = clazz->sfieldCount + clazz->ifieldCount;
+ u4 declared = clazz->sfieldCount + clazz->ifieldCount;
expandBufAdd4BE(pReply, declared);
- for (i = 0; i < clazz->sfieldCount; i++) {
- field = (Field*) &clazz->sfields[i];
-
+ for (int i = 0; i < clazz->sfieldCount; i++) {
+ Field* field = &clazz->sfields[i].field;
expandBufAddFieldId(pReply, fieldToFieldId(field));
expandBufAddUtf8String(pReply, (const u1*) field->name);
expandBufAddUtf8String(pReply, (const u1*) field->signature);
- if (withGeneric)
+ if (withGeneric) {
+ static const u1 genericSignature[1] = "";
expandBufAddUtf8String(pReply, genericSignature);
+ }
expandBufAdd4BE(pReply, augmentedAccessFlags(field->accessFlags));
}
- for (i = 0; i < clazz->ifieldCount; i++) {
- field = (Field*) &clazz->ifields[i];
-
+ for (int i = 0; i < clazz->ifieldCount; i++) {
+ Field* field = (Field*)&clazz->ifields[i].field;
expandBufAddFieldId(pReply, fieldToFieldId(field));
expandBufAddUtf8String(pReply, (const u1*) field->name);
expandBufAddUtf8String(pReply, (const u1*) field->signature);
- if (withGeneric)
+ if (withGeneric) {
+ static const u1 genericSignature[1] = "";
expandBufAddUtf8String(pReply, genericSignature);
+ }
expandBufAdd4BE(pReply, augmentedAccessFlags(field->accessFlags));
}
}
@@ -1286,12 +1282,12 @@
}
}
-typedef struct DebugCallbackContext {
+struct DebugCallbackContext {
int numItems;
ExpandBuf* pReply;
// used by locals table
bool withGeneric;
-} DebugCallbackContext;
+};
static int lineTablePositionsCb(void *cnxt, u4 address, u4 lineNum)
{
@@ -1792,7 +1788,7 @@
if (thread == NULL)
goto bail;
- result = thread->interpBreak.ctl.suspendCount;
+ result = thread->suspendCount;
bail:
dvmUnlockThreadList();
@@ -1857,7 +1853,7 @@
/*
* Return the ObjectId for the "system" thread group.
*/
-ObjectId dvmDbgGetSystemThreadGroupId(void)
+ObjectId dvmDbgGetSystemThreadGroupId()
{
Object* groupObj = dvmGetSystemThreadGroup();
return objectToObjectId(groupObj);
@@ -1866,7 +1862,7 @@
/*
* Return the ObjectId for the "main" thread group.
*/
-ObjectId dvmDbgGetMainThreadGroupId(void)
+ObjectId dvmDbgGetMainThreadGroupId()
{
Object* groupObj = dvmGetMainThreadGroup();
return objectToObjectId(groupObj);
@@ -2073,7 +2069,7 @@
dvmLockThreadList(NULL);
thread = threadObjToThread(threadObj);
if (thread != NULL) {
- count = dvmComputeExactFrameDepth(thread->curFrame);
+ count = dvmComputeExactFrameDepth(thread->interpSave.curFrame);
}
dvmUnlockThreadList();
@@ -2099,7 +2095,7 @@
if (thread == NULL)
goto bail;
- framePtr = thread->curFrame;
+ framePtr = thread->interpSave.curFrame;
count = 0;
while (framePtr != NULL) {
const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr);
@@ -2136,7 +2132,7 @@
/*
* Get the ThreadId for the current thread.
*/
-ObjectId dvmDbgGetThreadSelfId(void)
+ObjectId dvmDbgGetThreadSelfId()
{
Thread* self = dvmThreadSelf();
return objectToObjectId(self->threadObj);
@@ -2202,7 +2198,7 @@
/*
* Suspend ourselves after sending an event to the debugger.
*/
-void dvmDbgSuspendSelf(void)
+void dvmDbgSuspendSelf()
{
dvmSuspendSelf(true);
}
@@ -2574,8 +2570,8 @@
* The JDWP event mechanism has registered a single-step event. Tell
* the interpreter about it.
*/
-bool dvmDbgConfigureStep(ObjectId threadId, enum JdwpStepSize size,
- enum JdwpStepDepth depth)
+bool dvmDbgConfigureStep(ObjectId threadId, JdwpStepSize size,
+ JdwpStepDepth depth)
{
Object* threadObj;
Thread* thread;
@@ -2635,21 +2631,17 @@
u4 options, u1* pResultTag, u8* pResultValue, ObjectId* pExceptObj)
{
Object* threadObj = objectIdToObject(threadId);
- Thread* targetThread;
- JdwpError err = ERR_NONE;
dvmLockThreadList(NULL);
- targetThread = threadObjToThread(threadObj);
+ Thread* targetThread = threadObjToThread(threadObj);
if (targetThread == NULL) {
- err = ERR_INVALID_THREAD; /* thread does not exist */
dvmUnlockThreadList();
- goto bail;
+ return ERR_INVALID_THREAD; /* thread does not exist */
}
if (!targetThread->invokeReq.ready) {
- err = ERR_INVALID_THREAD; /* thread not stopped by event */
dvmUnlockThreadList();
- goto bail;
+ return ERR_INVALID_THREAD; /* thread not stopped by event */
}
/*
@@ -2666,14 +2658,13 @@
* by rejecting the method invocation request. Without this, we will
* be stuck waiting on a suspended thread.
*/
- if (targetThread->interpBreak.ctl.suspendCount > 1) {
+ if (targetThread->suspendCount > 1) {
LOGW("threadid=%d: suspend count on threadid=%d is %d, too deep "
"for method exec\n",
dvmThreadSelf()->threadId, targetThread->threadId,
- targetThread->interpBreak.ctl.suspendCount);
- err = ERR_THREAD_SUSPENDED; /* probably not expected here */
+ targetThread->suspendCount);
dvmUnlockThreadList();
- goto bail;
+ return ERR_THREAD_SUSPENDED; /* probably not expected here */
}
/*
@@ -2704,7 +2695,7 @@
* the invokeReq mutex, although that should never be held for long.
*/
Thread* self = dvmThreadSelf();
- int oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
+ ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
LOGV(" Transferring control to event thread\n");
dvmLockMutex(&targetThread->invokeReq.lock);
@@ -2760,10 +2751,7 @@
*pResultValue = objectToObjectId(tmpObj);
}
*pExceptObj = targetThread->invokeReq.exceptObj;
- err = targetThread->invokeReq.err;
-
-bail:
- return err;
+ return targetThread->invokeReq.err;
}
/*
@@ -2786,7 +2774,7 @@
Thread* self = dvmThreadSelf();
const Method* meth;
Object* oldExcept;
- int oldStatus;
+ ThreadStatus oldStatus;
/*
* We can be called while an exception is pending in the VM. We need
@@ -2855,7 +2843,7 @@
* We can't use the "tracked allocation" mechanism here because
* the object is going to be handed off to a different thread.
*/
- (void) objectToObjectId((Object*)pReq->resultValue.l);
+ objectToObjectId((Object*)pReq->resultValue.l);
}
if (oldExcept != NULL) {
@@ -2866,12 +2854,12 @@
}
// for dvmAddressSetForLine
-typedef struct AddressSetContext {
+struct AddressSetContext {
bool lastAddressValid;
u4 lastAddress;
u4 lineNum;
AddressSet *pSet;
-} AddressSetContext;
+};
// for dvmAddressSetForLine
static int addressSetCb (void *cnxt, u4 address, u4 lineNum)
@@ -2953,7 +2941,7 @@
/*
* First DDM packet has arrived over JDWP. Notify the press.
*/
-void dvmDbgDdmConnected(void)
+void dvmDbgDdmConnected()
{
dvmDdmConnected();
}
@@ -2961,7 +2949,7 @@
/*
* JDWP connection has dropped.
*/
-void dvmDbgDdmDisconnected(void)
+void dvmDbgDdmDisconnected()
{
dvmDdmDisconnected();
}
diff --git a/vm/Debugger.h b/vm/Debugger.h
index 9a45b39..aaef02d 100644
--- a/vm/Debugger.h
+++ b/vm/Debugger.h
@@ -21,10 +21,10 @@
#ifndef _DALVIK_DEBUGGER
#define _DALVIK_DEBUGGER
+#include <pthread.h>
#include "Common.h"
#include "Misc.h"
#include "jdwp/Jdwp.h"
-#include <pthread.h>
/* fwd decl */
struct Object;
@@ -36,10 +36,10 @@
* Used by StepControl to track a set of addresses associated with
* a single line.
*/
-typedef struct AddressSet {
+struct AddressSet {
u4 setSize;
u1 set[1];
-} AddressSet;
+};
INLINE void dvmAddressSetSet(AddressSet *pSet, u4 toSet)
{
@@ -60,24 +60,24 @@
/*
* Single-step management.
*/
-typedef struct StepControl {
+struct StepControl {
/* request */
- enum JdwpStepSize size;
- enum JdwpStepDepth depth;
- struct Thread* thread; /* don't deref; for comparison only */
+ JdwpStepSize size;
+ JdwpStepDepth depth;
+ Thread* thread; /* don't deref; for comparison only */
/* current state */
- bool active;
- const struct Method* method;
- int line; /* line #; could be -1 */
- const AddressSet* pAddressSet; /* if non-null, address set for line */
- int frameDepth;
-} StepControl;
+ bool active;
+ const Method* method;
+ int line; /* line #; could be -1 */
+ const AddressSet* pAddressSet; /* if non-null, address set for line */
+ int frameDepth;
+};
/*
* Invoke-during-breakpoint support.
*/
-typedef struct DebugInvokeReq {
+struct DebugInvokeReq {
/* boolean; only set when we're in the tail end of an event handler */
bool ready;
@@ -85,24 +85,24 @@
bool invokeNeeded;
/* request */
- struct Object* obj; /* not used for ClassType.InvokeMethod */
- struct Object* thread;
- struct ClassObject* clazz;
- struct Method* method;
- u4 numArgs;
- u8* argArray; /* will be NULL if numArgs==0 */
- u4 options;
+ Object* obj; /* not used for ClassType.InvokeMethod */
+ Object* thread;
+ ClassObject* clazz;
+ Method* method;
+ u4 numArgs;
+ u8* argArray; /* will be NULL if numArgs==0 */
+ u4 options;
/* result */
- JdwpError err;
- u1 resultTag;
- JValue resultValue;
- ObjectId exceptObj;
+ JdwpError err;
+ u1 resultTag;
+ JValue resultValue;
+ ObjectId exceptObj;
/* condition variable to wait on while the method executes */
- pthread_mutex_t lock;
- pthread_cond_t cv;
-} DebugInvokeReq;
+ pthread_mutex_t lock;
+ pthread_cond_t cv;
+};
/* system init/shutdown */
bool dvmDebuggerStartup(void);
@@ -260,14 +260,13 @@
/*
* Debugger notification
*/
-void dvmDbgPostLocationEvent(const struct Method* method, int pcOffset,
- struct Object* thisPtr, int eventFlags);
+void dvmDbgPostLocationEvent(const Method* method, int pcOffset,
+ Object* thisPtr, int eventFlags);
void dvmDbgPostException(void* throwFp, int throwRelPc, void* catchFp,
- int catchRelPc, struct Object* exception);
-void dvmDbgPostThreadStart(struct Thread* thread);
-void dvmDbgPostThreadDeath(struct Thread* thread);
-void dvmDbgPostClassPrepare(struct ClassObject* clazz);
-// FieldAccess, FieldModification
+ int catchRelPc, Object* exception);
+void dvmDbgPostThreadStart(Thread* thread);
+void dvmDbgPostThreadDeath(Thread* thread);
+void dvmDbgPostClassPrepare(ClassObject* clazz);
/* for "eventFlags" */
enum {
@@ -279,8 +278,8 @@
bool dvmDbgWatchLocation(const JdwpLocation* pLoc);
void dvmDbgUnwatchLocation(const JdwpLocation* pLoc);
-bool dvmDbgConfigureStep(ObjectId threadId, enum JdwpStepSize size,
- enum JdwpStepDepth depth);
+bool dvmDbgConfigureStep(ObjectId threadId, JdwpStepSize size,
+ JdwpStepDepth depth);
void dvmDbgUnconfigureStep(ObjectId threadId);
JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId,
@@ -289,7 +288,7 @@
void dvmDbgExecuteMethod(DebugInvokeReq* pReq);
/* Make an AddressSet for a line, for single stepping */
-const AddressSet *dvmAddressSetForLine(const struct Method* method, int line);
+const AddressSet *dvmAddressSetForLine(const Method* method, int line);
/* perform "late registration" of an object ID */
void dvmDbgRegisterObjectId(ObjectId id);
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index d655a3a..feb53a8 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -25,7 +25,7 @@
# Compiler defines.
#
LOCAL_CFLAGS += -fstrict-aliasing -Wstrict-aliasing=2 -fno-align-jumps
-LOCAL_CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wc++-compat
+LOCAL_CFLAGS += -Wall -Wextra -Wno-unused-parameter
LOCAL_CFLAGS += -DARCH_VARIANT=\"$(dvm_arch_variant)\"
#
@@ -59,7 +59,6 @@
LOCAL_CFLAGS += -DWITH_TRACKREF_CHECKS
LOCAL_CFLAGS += -DWITH_EXTRA_GC_CHECKS=1
#LOCAL_CFLAGS += -DCHECK_MUTEX
- #LOCAL_CFLAGS += -DPROFILE_FIELD_ACCESS
LOCAL_CFLAGS += -DDVM_SHOW_EXCEPTION=3
# add some extra stuff to make it easier to examine with GDB
LOCAL_CFLAGS += -DEASY_GDB
@@ -85,121 +84,121 @@
#LOCAL_CFLAGS += -DWITH_JNI_STACK_CHECK
LOCAL_SRC_FILES := \
- AllocTracker.c \
- Atomic.c.arm \
- AtomicCache.c \
- BitVector.c.arm \
- CheckJni.c \
- Ddm.c \
- Debugger.c \
- DvmDex.c \
- Exception.c \
- Hash.c \
- IndirectRefTable.c.arm \
- Init.c \
- InitRefs.c \
- InlineNative.c.arm \
- Inlines.c \
- Intern.c \
- Jni.c \
- JarFile.c \
- LinearAlloc.c \
- Misc.c \
- Native.c \
- PointerSet.c \
- Profile.c \
- Properties.c \
- RawDexFile.c \
- ReferenceTable.c \
- SignalCatcher.c \
- StdioConverter.c \
- Sync.c \
- Thread.c \
- UtfString.c \
- alloc/Alloc.c \
- alloc/CardTable.c \
- alloc/HeapBitmap.c.arm \
- alloc/HeapDebug.c \
- alloc/Heap.c.arm \
- alloc/DdmHeap.c \
- alloc/Verify.c \
- alloc/Visit.c \
- analysis/CodeVerify.c \
- analysis/DexPrepare.c \
- analysis/DexVerify.c \
- analysis/Liveness.c \
- analysis/Optimize.c \
- analysis/RegisterMap.c \
- analysis/VerifySubs.c \
- analysis/VfyBasicBlock.c \
- hprof/Hprof.c \
- hprof/HprofClass.c \
- hprof/HprofHeap.c \
- hprof/HprofOutput.c \
- hprof/HprofString.c \
- interp/Interp.c.arm \
- interp/Stack.c \
- jdwp/ExpandBuf.c \
- jdwp/JdwpAdb.c \
- jdwp/JdwpConstants.c \
- jdwp/JdwpEvent.c \
- jdwp/JdwpHandler.c \
- jdwp/JdwpMain.c \
- jdwp/JdwpSocket.c \
- mterp/Mterp.c.arm \
- mterp/out/InterpC-portable.c.arm \
- native/InternalNative.c \
- native/dalvik_bytecode_OpcodeInfo.c \
- native/dalvik_system_DexFile.c \
- native/dalvik_system_VMDebug.c \
- native/dalvik_system_VMRuntime.c \
- native/dalvik_system_VMStack.c \
- native/dalvik_system_Zygote.c \
- native/java_lang_Class.c \
- native/java_lang_Double.c \
- native/java_lang_Float.c \
- native/java_lang_Math.c \
- native/java_lang_Object.c \
- native/java_lang_Runtime.c \
- native/java_lang_String.c \
- native/java_lang_System.c \
- native/java_lang_Throwable.c \
- native/java_lang_VMClassLoader.c \
- native/java_lang_VMThread.c \
- native/java_lang_reflect_AccessibleObject.c \
- native/java_lang_reflect_Array.c \
- native/java_lang_reflect_Constructor.c \
- native/java_lang_reflect_Field.c \
- native/java_lang_reflect_Method.c \
- native/java_lang_reflect_Proxy.c \
- native/java_util_concurrent_atomic_AtomicLong.c \
- native/org_apache_harmony_dalvik_NativeTestTarget.c \
- native/org_apache_harmony_dalvik_ddmc_DdmServer.c \
- native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.c \
- native/sun_misc_Unsafe.c \
- oo/AccessCheck.c \
- oo/Array.c \
- oo/Class.c \
- oo/Object.c \
- oo/Resolve.c \
- oo/TypeCheck.c \
- reflect/Annotation.c \
- reflect/Proxy.c \
- reflect/Reflect.c \
- test/AtomicTest.c.arm \
- test/TestHash.c \
- test/TestIndirectRefTable.c
+ AllocTracker.cpp \
+ Atomic.cpp.arm \
+ AtomicCache.cpp \
+ BitVector.cpp.arm \
+ CheckJni.cpp \
+ Ddm.cpp \
+ Debugger.cpp \
+ DvmDex.cpp \
+ Exception.cpp \
+ Hash.cpp \
+ IndirectRefTable.cpp.arm \
+ Init.cpp \
+ InitRefs.cpp \
+ InlineNative.cpp.arm \
+ Inlines.cpp \
+ Intern.cpp \
+ Jni.cpp \
+ JarFile.cpp \
+ LinearAlloc.cpp \
+ Misc.cpp \
+ Native.cpp \
+ PointerSet.cpp \
+ Profile.cpp \
+ Properties.cpp \
+ RawDexFile.cpp \
+ ReferenceTable.cpp \
+ SignalCatcher.cpp \
+ StdioConverter.cpp \
+ Sync.cpp \
+ Thread.cpp \
+ UtfString.cpp \
+ alloc/Alloc.cpp \
+ alloc/CardTable.cpp \
+ alloc/HeapBitmap.cpp.arm \
+ alloc/HeapDebug.cpp \
+ alloc/Heap.cpp.arm \
+ alloc/DdmHeap.cpp \
+ alloc/Verify.cpp \
+ alloc/Visit.cpp \
+ analysis/CodeVerify.cpp \
+ analysis/DexPrepare.cpp \
+ analysis/DexVerify.cpp \
+ analysis/Liveness.cpp \
+ analysis/Optimize.cpp \
+ analysis/RegisterMap.cpp \
+ analysis/VerifySubs.cpp \
+ analysis/VfyBasicBlock.cpp \
+ hprof/Hprof.cpp \
+ hprof/HprofClass.cpp \
+ hprof/HprofHeap.cpp \
+ hprof/HprofOutput.cpp \
+ hprof/HprofString.cpp \
+ interp/Interp.cpp.arm \
+ interp/Stack.cpp \
+ jdwp/ExpandBuf.cpp \
+ jdwp/JdwpAdb.cpp \
+ jdwp/JdwpConstants.cpp \
+ jdwp/JdwpEvent.cpp \
+ jdwp/JdwpHandler.cpp \
+ jdwp/JdwpMain.cpp \
+ jdwp/JdwpSocket.cpp \
+ mterp/Mterp.cpp.arm \
+ mterp/out/InterpC-portable.cpp.arm \
+ native/InternalNative.cpp \
+ native/dalvik_bytecode_OpcodeInfo.cpp \
+ native/dalvik_system_DexFile.cpp \
+ native/dalvik_system_VMDebug.cpp \
+ native/dalvik_system_VMRuntime.cpp \
+ native/dalvik_system_VMStack.cpp \
+ native/dalvik_system_Zygote.cpp \
+ native/java_lang_Class.cpp \
+ native/java_lang_Double.cpp \
+ native/java_lang_Float.cpp \
+ native/java_lang_Math.cpp \
+ native/java_lang_Object.cpp \
+ native/java_lang_Runtime.cpp \
+ native/java_lang_String.cpp \
+ native/java_lang_System.cpp \
+ native/java_lang_Throwable.cpp \
+ native/java_lang_VMClassLoader.cpp \
+ native/java_lang_VMThread.cpp \
+ native/java_lang_reflect_AccessibleObject.cpp \
+ native/java_lang_reflect_Array.cpp \
+ native/java_lang_reflect_Constructor.cpp \
+ native/java_lang_reflect_Field.cpp \
+ native/java_lang_reflect_Method.cpp \
+ native/java_lang_reflect_Proxy.cpp \
+ native/java_util_concurrent_atomic_AtomicLong.cpp \
+ native/org_apache_harmony_dalvik_NativeTestTarget.cpp \
+ native/org_apache_harmony_dalvik_ddmc_DdmServer.cpp \
+ native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cpp \
+ native/sun_misc_Unsafe.cpp \
+ oo/AccessCheck.cpp \
+ oo/Array.cpp \
+ oo/Class.cpp \
+ oo/Object.cpp \
+ oo/Resolve.cpp \
+ oo/TypeCheck.cpp \
+ reflect/Annotation.cpp \
+ reflect/Proxy.cpp \
+ reflect/Reflect.cpp \
+ test/AtomicTest.cpp.arm \
+ test/TestHash.cpp \
+ test/TestIndirectRefTable.cpp
WITH_COPYING_GC := $(strip $(WITH_COPYING_GC))
ifeq ($(WITH_COPYING_GC),true)
LOCAL_CFLAGS += -DWITH_COPYING_GC
LOCAL_SRC_FILES += \
- alloc/Copying.c.arm
+ alloc/Copying.cpp.arm
else
LOCAL_SRC_FILES += \
- alloc/HeapSource.c \
- alloc/MarkSweep.c.arm
+ alloc/HeapSource.cpp \
+ alloc/MarkSweep.cpp.arm
endif
WITH_JIT := $(strip $(WITH_JIT))
@@ -207,16 +206,16 @@
ifeq ($(WITH_JIT),true)
LOCAL_CFLAGS += -DWITH_JIT
LOCAL_SRC_FILES += \
- compiler/Compiler.c \
- compiler/Frontend.c \
- compiler/Utility.c \
- compiler/InlineTransformation.c \
- compiler/IntermediateRep.c \
- compiler/Dataflow.c \
- compiler/SSATransformation.c \
- compiler/Loop.c \
- compiler/Ralloc.c \
- interp/Jit.c
+ compiler/Compiler.cpp \
+ compiler/Frontend.cpp \
+ compiler/Utility.cpp \
+ compiler/InlineTransformation.cpp \
+ compiler/IntermediateRep.cpp \
+ compiler/Dataflow.cpp \
+ compiler/SSATransformation.cpp \
+ compiler/Loop.cpp \
+ compiler/Ralloc.cpp \
+ interp/Jit.cpp
endif
LOCAL_C_INCLUDES += \
@@ -224,9 +223,9 @@
dalvik \
dalvik/vm \
external/zlib \
+ libcore/include \
$(KERNEL_HEADERS)
-
ifeq ($(dvm_simulator),true)
LOCAL_LDLIBS += -lpthread -ldl
ifeq ($(HOST_OS),linux)
@@ -246,20 +245,20 @@
LOCAL_SRC_FILES += \
arch/arm/CallOldABI.S \
arch/arm/CallEABI.S \
- arch/arm/HintsEABI.c \
- mterp/out/InterpC-$(dvm_arch_variant).c.arm \
+ arch/arm/HintsEABI.cpp \
+ mterp/out/InterpC-$(dvm_arch_variant).cpp.arm \
mterp/out/InterpAsm-$(dvm_arch_variant).S
ifeq ($(WITH_JIT),true)
LOCAL_SRC_FILES += \
- compiler/codegen/RallocUtil.c \
- compiler/codegen/arm/$(dvm_arch_variant)/Codegen.c \
+ compiler/codegen/RallocUtil.cpp \
+ compiler/codegen/arm/$(dvm_arch_variant)/Codegen.cpp \
compiler/codegen/arm/$(dvm_arch_variant)/CallingConvention.S \
- compiler/codegen/arm/Assemble.c \
- compiler/codegen/arm/ArchUtility.c \
- compiler/codegen/arm/LocalOptimizations.c \
- compiler/codegen/arm/GlobalOptimizations.c \
- compiler/codegen/arm/ArmRallocUtil.c \
+ compiler/codegen/arm/Assemble.cpp \
+ compiler/codegen/arm/ArchUtility.cpp \
+ compiler/codegen/arm/LocalOptimizations.cpp \
+ compiler/codegen/arm/GlobalOptimizations.cpp \
+ compiler/codegen/arm/ArmRallocUtil.cpp \
compiler/template/out/CompilerTemplateAsm-$(dvm_arch_variant).S
endif
endif
@@ -270,14 +269,14 @@
LOCAL_CFLAGS += -DDVM_JMP_TABLE_MTERP=1
LOCAL_SRC_FILES += \
arch/$(dvm_arch_variant)/Call386ABI.S \
- arch/$(dvm_arch_variant)/Hints386ABI.c \
- mterp/out/InterpC-$(dvm_arch_variant).c \
+ arch/$(dvm_arch_variant)/Hints386ABI.cpp \
+ mterp/out/InterpC-$(dvm_arch_variant).cpp \
mterp/out/InterpAsm-$(dvm_arch_variant).S
ifeq ($(WITH_JIT),true)
LOCAL_SRC_FILES += \
- compiler/codegen/x86/Assemble.c \
- compiler/codegen/x86/ArchUtility.c \
- compiler/codegen/x86/ia32/Codegen.c \
+ compiler/codegen/x86/Assemble.cpp \
+ compiler/codegen/x86/ArchUtility.cpp \
+ compiler/codegen/x86/ia32/Codegen.cpp \
compiler/codegen/x86/ia32/CallingConvention.S \
compiler/template/out/CompilerTemplateAsm-ia32.S
endif
@@ -288,8 +287,8 @@
MTERP_ARCH_KNOWN := true
LOCAL_SRC_FILES += \
arch/sh/CallSH4ABI.S \
- arch/generic/Hints.c \
- mterp/out/InterpC-allstubs.c \
+ arch/generic/Hints.cpp \
+ mterp/out/InterpC-allstubs.cpp \
mterp/out/InterpAsm-allstubs.S
endif
@@ -305,9 +304,9 @@
endif
LOCAL_SRC_FILES += \
- arch/generic/Call.c \
- arch/generic/Hints.c \
- mterp/out/InterpC-allstubs.c
+ arch/generic/Call.cpp \
+ arch/generic/Hints.cpp \
+ mterp/out/InterpC-allstubs.cpp
# The following symbols are usually defined in the asm file, but
# since we don't have an asm file in this case, we instead just
diff --git a/vm/DvmDex.c b/vm/DvmDex.cpp
similarity index 100%
rename from vm/DvmDex.c
rename to vm/DvmDex.cpp
diff --git a/vm/DvmDex.h b/vm/DvmDex.h
index ad82e54..df14760 100644
--- a/vm/DvmDex.h
+++ b/vm/DvmDex.h
@@ -34,7 +34,7 @@
/*
* Some additional VM data structures that are associated with the DEX file.
*/
-typedef struct DvmDex {
+struct DvmDex {
/* pointer to the DexFile we're associated with */
DexFile* pDexFile;
@@ -63,7 +63,7 @@
/* lock ensuring mutual exclusion during updates */
pthread_mutex_t modLock;
-} DvmDex;
+};
/*
diff --git a/vm/Exception.c b/vm/Exception.cpp
similarity index 97%
rename from vm/Exception.c
rename to vm/Exception.cpp
index 740f5a6..30796c2 100644
--- a/vm/Exception.c
+++ b/vm/Exception.cpp
@@ -561,7 +561,7 @@
* Exceptions thrown during the course of printing the stack trace are
* ignored.
*/
-void dvmPrintExceptionStackTrace(void)
+void dvmPrintExceptionStackTrace()
{
Thread* self = dvmThreadSelf();
Object* exception;
@@ -609,7 +609,7 @@
LOGVV("findCatchInMethod %s.%s excep=%s depth=%d\n",
method->clazz->descriptor, method->name, excepClass->descriptor,
- dvmComputeExactFrameDepth(self->curFrame));
+ dvmComputeExactFrameDepth(self->interpSave.curFrame));
DvmDex* pDvmDex = method->clazz->pDvmDex;
const DexCode* pCode = dvmGetMethodCode(method);
@@ -710,12 +710,12 @@
* before calling here and restore it after.
*
* Sets *newFrame to the frame pointer of the frame with the catch block.
- * If "scanOnly" is false, self->curFrame is also set to this value.
+ * If "scanOnly" is false, self->interpSave.curFrame is also set to this value.
*/
int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
bool scanOnly, void** newFrame)
{
- void* fp = self->curFrame;
+ u4* fp = self->interpSave.curFrame;
int catchAddr = -1;
assert(!dvmCheckException(self));
@@ -789,7 +789,7 @@
}
if (!scanOnly)
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* The class resolution in findCatchInMethod() could cause an exception.
@@ -831,7 +831,7 @@
if (pCount != NULL)
*pCount = 0;
- fp = thread->curFrame;
+ fp = thread->interpSave.curFrame;
assert(thread == dvmThreadSelf() || dvmIsSuspended(thread));
@@ -888,7 +888,7 @@
assert(dvmCheckException(dvmThreadSelf()));
goto bail;
}
- intPtr = (int*) stackData->contents;
+ intPtr = (int*)(void*)stackData->contents;
} else {
/* array of ints; first entry is stack depth */
assert(sizeof(Method*) == sizeof(int));
@@ -950,7 +950,7 @@
{
const ArrayObject* stackData = (const ArrayObject*) ostackData;
size_t stackSize = stackData->length / 2;
- const int* intVals = (const int*) stackData->contents;
+ const int* intVals = (const int*)(void*)stackData->contents;
return dvmGetStackTraceRaw(intVals, stackSize);
}
@@ -964,19 +964,14 @@
*/
ArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth)
{
- ArrayObject* steArray = NULL;
-
/* allocate a StackTraceElement array */
- steArray = dvmAllocArray(gDvm.classJavaLangStackTraceElementArray,
- stackDepth, kObjectArrayRefWidth, ALLOC_DEFAULT);
- if (steArray == NULL)
- goto bail;
-
- dvmFillStackTraceElements(intVals, stackDepth, steArray);
-
-bail:
- dvmReleaseTrackedAlloc((Object*) steArray, NULL);
- return steArray;
+ ClassObject* klass = gDvm.classJavaLangStackTraceElementArray;
+ ArrayObject* array = dvmAllocArrayByClass(klass, stackDepth, ALLOC_DEFAULT);
+ if (array != NULL){
+ dvmFillStackTraceElements(intVals, stackDepth, array);
+ dvmReleaseTrackedAlloc((Object*) array, NULL);
+ }
+ return array;
}
/*
@@ -1189,7 +1184,7 @@
}
stackSize = stackData->length / 2;
- intVals = (const int*) stackData->contents;
+ intVals = (const int*)(void*)stackData->contents;
dvmLogRawStackTrace(intVals, stackSize);
}
@@ -1200,7 +1195,7 @@
* the stored stack trace and process it internally instead of calling
* interpreted code.
*/
-void dvmLogExceptionStackTrace(void)
+void dvmLogExceptionStackTrace()
{
Object* exception = dvmThreadSelf()->exception;
Object* cause;
@@ -1317,7 +1312,7 @@
dvmThrowChainedException(gDvm.exClassNotFoundException, name, cause);
}
-void dvmThrowExceptionInInitializerError(void)
+void dvmThrowExceptionInInitializerError()
{
/*
* TODO: Do we want to wrap it if the original is an Error rather than
diff --git a/vm/Exception.h b/vm/Exception.h
index 509d3b2..81a0e76 100644
--- a/vm/Exception.h
+++ b/vm/Exception.h
@@ -168,12 +168,12 @@
* "*newFrame" gets a copy of the new frame pointer.
*
* If "doUnroll" is set, we unroll "thread"s stack as we go (and update
- * self->curFrame with the same value as in *newFrame).
+ * self->interpSave.curFrame with the same value as in *newFrame).
*
* Returns the offset to the catch code on success, or -1 if we couldn't
* find a catcher.
*/
-int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
+extern "C" int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
bool doUnroll, void** newFrame);
/*
@@ -212,21 +212,20 @@
* Throw an ArithmeticException in the current thread, with the given detail
* message.
*/
-void dvmThrowArithmeticException(const char* msg);
+extern "C" void dvmThrowArithmeticException(const char* msg);
/*
* Throw an ArrayIndexOutOfBoundsException in the current thread,
* using the given array length and index in the detail message.
*/
-void dvmThrowArrayIndexOutOfBoundsException(int length, int index);
+extern "C" void dvmThrowArrayIndexOutOfBoundsException(int length, int index);
/*
* Throw an ArrayStoreException in the current thread, using the given classes'
* names in the detail message, indicating that an object of the given type
* can't be stored into an array of the given type.
*/
-void dvmThrowArrayStoreExceptionIncompatibleElement(ClassObject* objectType,
- ClassObject* arrayType);
+extern "C" void dvmThrowArrayStoreExceptionIncompatibleElement(ClassObject* objectType, ClassObject* arrayType);
/*
* Throw an ArrayStoreException in the current thread, using the given
@@ -255,7 +254,7 @@
* Throw a ClassCastException in the current thread, using the given classes'
* names in the detail message.
*/
-void dvmThrowClassCastException(ClassObject* actual, ClassObject* desired);
+extern "C" void dvmThrowClassCastException(ClassObject* actual, ClassObject* desired);
/**
* Throw a ClassCircularityError in the current thread, with the
@@ -361,7 +360,7 @@
* Throw an InternalError in the current thread, with the given
* detail message.
*/
-void dvmThrowInternalError(const char* msg);
+extern "C" void dvmThrowInternalError(const char* msg);
/**
* Throw an InterruptedException in the current thread, with the given
@@ -379,13 +378,13 @@
* Throw a NegativeArraySizeException in the current thread, with the
* given number as the detail message.
*/
-void dvmThrowNegativeArraySizeException(s4 size);
+extern "C" void dvmThrowNegativeArraySizeException(s4 size);
/**
* Throw a NoClassDefFoundError in the current thread, with the
* human-readable form of the given descriptor as the detail message.
*/
-void dvmThrowNoClassDefFoundError(const char* descriptor);
+extern "C" void dvmThrowNoClassDefFoundError(const char* descriptor);
/**
* Throw a NoClassDefFoundError in the current thread, with the given
@@ -399,7 +398,7 @@
* Throw a NoSuchFieldError in the current thread, with the given
* detail message.
*/
-void dvmThrowNoSuchFieldError(const char* msg);
+extern "C" void dvmThrowNoSuchFieldError(const char* msg);
/**
* Throw a NoSuchFieldException in the current thread, with the given
@@ -411,13 +410,13 @@
* Throw a NoSuchMethodError in the current thread, with the given
* detail message.
*/
-void dvmThrowNoSuchMethodError(const char* msg);
+extern "C" void dvmThrowNoSuchMethodError(const char* msg);
/**
* Throw a NullPointerException in the current thread, with the given
* detail message.
*/
-void dvmThrowNullPointerException(const char* msg);
+extern "C" void dvmThrowNullPointerException(const char* msg);
/**
* Throw an OutOfMemoryError in the current thread, with the given
diff --git a/vm/Globals.h b/vm/Globals.h
index faafcc6..db552c6 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -33,22 +33,20 @@
#include <stdarg.h>
#include <pthread.h>
-#define MAX_BREAKPOINTS 20 /* used for a debugger optimization */
-
/* private structures */
-typedef struct GcHeap GcHeap;
-typedef struct BreakpointSet BreakpointSet;
-typedef struct InlineSub InlineSub;
+struct GcHeap;
+struct BreakpointSet;
+struct InlineSub;
/*
* One of these for each -ea/-da/-esa/-dsa on the command line.
*/
-typedef struct AssertionControl {
+struct AssertionControl {
char* pkgOrClass; /* package/class string, or NULL for esa/dsa */
int pkgOrClassLen; /* string length, for quick compare */
bool enable; /* enable or disable */
bool isPackage; /* string ended with "..."? */
-} AssertionControl;
+};
/*
* Register map generation mode. Only applicable when generateRegisterMaps
@@ -60,11 +58,11 @@
* maps, but allows type-precise GC. "LivePrecise" is even slower and
* requires additional heap during processing, but allows live-precise GC.
*/
-typedef enum {
+enum RegisterMapMode {
kRegisterMapModeUnknown = 0,
kRegisterMapModeTypePrecise,
kRegisterMapModeLivePrecise
-} RegisterMapMode;
+};
/*
* All fields are initialized to zero.
@@ -91,7 +89,7 @@
bool jdwpAllowed; // debugging allowed for this process?
bool jdwpConfigured; // has debugging info been provided?
- int jdwpTransport;
+ JdwpTransportType jdwpTransport;
bool jdwpServer;
char* jdwpHost;
int jdwpPort;
@@ -452,7 +450,7 @@
pthread_mutex_t _threadSuspendLock;
/*
- * Guards Thread->interpBreak.ctl.suspendCount for all threads, and
+ * Guards Thread->suspendCount for all threads, and
* provides the lock for the condition variable that all suspended threads
* sleep on (threadSuspendCountCond).
*
@@ -566,12 +564,6 @@
pthread_key_t pthreadKeySelf; /* Thread*, for dvmThreadSelf */
/*
- * JNI allows you to have multiple VMs, but we limit ourselves to 1,
- * so "vmList" is really just a pointer to the one and only VM.
- */
- JavaVM* vmList;
-
- /*
* Cache results of "A instanceof B".
*/
AtomicCache* instanceofCache;
@@ -727,25 +719,25 @@
#if defined(WITH_JIT)
/* Trace profiling modes. Ordering matters - off states before on states */
-typedef enum TraceProfilingModes {
+enum TraceProfilingModes {
kTraceProfilingDisabled = 0, // Not profiling
kTraceProfilingPeriodicOff = 1, // Periodic profiling, off phase
kTraceProfilingContinuous = 2, // Always profiling
kTraceProfilingPeriodicOn = 3 // Periodic profiling, on phase
-} TraceProfilingModes;
+};
/*
* Exiting the compiled code w/o chaining will incur overhead to look up the
* target in the code cache which is extra work only when JIT is enabled. So
* we want to monitor it closely to make sure we don't have performance bugs.
*/
-typedef enum NoChainExits {
+enum NoChainExits {
kInlineCacheMiss = 0,
kCallsiteInterpreted,
kSwitchOverflow,
kHeavyweightMonitor,
kNoChainExitLast,
-} NoChainExits;
+};
/*
* JIT-specific global state
@@ -959,4 +951,17 @@
#endif
+struct DvmJniGlobals {
+ bool useCheckJni;
+ bool warnOnly;
+ bool forceCopy;
+
+ /**
+ * The JNI JavaVM object. Dalvik only supports a single VM per process.
+ */
+ JavaVM* jniVm;
+};
+
+extern struct DvmJniGlobals gDvmJni;
+
#endif /*_DALVIK_GLOBALS*/
diff --git a/vm/Hash.c b/vm/Hash.cpp
similarity index 100%
rename from vm/Hash.c
rename to vm/Hash.cpp
diff --git a/vm/Hash.h b/vm/Hash.h
index cfd7544..12af8a7 100644
--- a/vm/Hash.h
+++ b/vm/Hash.h
@@ -58,10 +58,10 @@
*
* When an entry is released, we will call (HashFreeFunc)(entry->data).
*/
-typedef struct HashEntry {
+struct HashEntry {
u4 hashValue;
void* data;
-} HashEntry;
+};
#define HASH_TOMBSTONE ((void*) 0xcbcacccd) // invalid ptr value
@@ -70,14 +70,14 @@
*
* This structure should be considered opaque.
*/
-typedef struct HashTable {
+struct HashTable {
int tableSize; /* must be power of 2 */
int numEntries; /* current #of "live" entries */
int numDeadEntries; /* current #of tombstone entries */
HashEntry* pEntries; /* array on heap */
HashFreeFunc freeFunc;
pthread_mutex_t lock;
-} HashTable;
+};
/*
* Create and initialize a HashTable structure, using "initialSize" as
@@ -179,11 +179,11 @@
* MyData* data = (MyData*)dvmHashIterData(&iter);
* }
*/
-typedef struct HashIter {
+struct HashIter {
void* data;
HashTable* pHashTable;
int idx;
-} HashIter;
+};
INLINE void dvmHashIterNext(HashIter* pIter) {
int i = pIter->idx +1;
int lim = pIter->pHashTable->tableSize;
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.cpp
similarity index 100%
rename from vm/IndirectRefTable.c
rename to vm/IndirectRefTable.cpp
diff --git a/vm/IndirectRefTable.h b/vm/IndirectRefTable.h
index 7248a7b..165bfb1 100644
--- a/vm/IndirectRefTable.h
+++ b/vm/IndirectRefTable.h
@@ -16,6 +16,7 @@
#ifndef _DALVIK_INDIRECTREFTABLE
#define _DALVIK_INDIRECTREFTABLE
+
/*
* Maintain a table of indirect references. Used for local/global JNI
* references.
@@ -90,22 +91,22 @@
*
* For convenience these match up with enum jobjectRefType from jni.h.
*/
-typedef enum IndirectRefKind {
+enum IndirectRefKind {
kIndirectKindInvalid = 0,
kIndirectKindLocal = 1,
kIndirectKindGlobal = 2,
kIndirectKindWeakGlobal = 3
-} IndirectRefKind;
+};
/*
* Extended debugging structure. We keep a parallel array of these, one
* per slot in the table.
*/
#define kIRTPrevCount 4
-typedef struct IndirectRefSlot {
+struct IndirectRefSlot {
u4 serial; /* slot serial */
Object* previous[kIRTPrevCount];
-} IndirectRefSlot;
+};
/*
* Table definition.
@@ -174,14 +175,14 @@
* add a "synchronized lookup" call that takes the mutex as an argument,
* and either locks or doesn't lock based on internal details.
*/
-typedef union IRTSegmentState {
+union IRTSegmentState {
u4 all;
struct {
u4 topIndex:16; /* index of first unused entry */
u4 numHoles:16; /* #of holes in entire table */
} parts;
-} IRTSegmentState;
-typedef struct IndirectRefTable {
+};
+struct IndirectRefTable {
/* semi-public - read/write by interpreter in native call handler */
IRTSegmentState segmentState;
@@ -196,7 +197,7 @@
// TODO: want hole-filling stats (#of holes filled, total entries scanned)
// for performance evaluation.
-} IndirectRefTable;
+};
/* use as initial value for "cookie", and when table has only one segment */
#define IRT_FIRST_SEGMENT 0
diff --git a/vm/Init.c b/vm/Init.cpp
similarity index 98%
rename from vm/Init.c
rename to vm/Init.cpp
index a8cf258..c87aea9 100644
--- a/vm/Init.c
+++ b/vm/Init.cpp
@@ -17,11 +17,7 @@
/*
* Dalvik initialization, shutdown, and command-line argument processing.
*/
-#include "Dalvik.h"
-#include "test/Test.h"
-#include "mterp/Mterp.h"
-#include "Hash.h"
-
+#define __STDC_LIMIT_MACROS
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
@@ -30,6 +26,11 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "Dalvik.h"
+#include "test/Test.h"
+#include "mterp/Mterp.h"
+#include "Hash.h"
+
#define kMinHeapStartSize (1*1024*1024)
#define kMinHeapSize (2*1024*1024)
#define kMaxHeapSize (1*1024*1024*1024)
@@ -41,12 +42,13 @@
/* fwd */
static bool registerSystemNatives(JNIEnv* pEnv);
-static bool initJdwp(void);
-static bool initZygote(void);
+static bool initJdwp();
+static bool initZygote();
/* global state */
struct DvmGlobals gDvm;
+struct DvmJniGlobals gDvmJni;
/* JIT-specific global state */
#if defined(WITH_JIT)
@@ -167,9 +169,6 @@
#ifdef CHECK_MUTEX
" check_mutex"
#endif
-#ifdef PROFILE_FIELD_ACCESS
- " profile_field_access"
-#endif
#if defined(WITH_JIT)
" jit(" ARCH_VARIANT ")"
#endif
@@ -189,7 +188,7 @@
/*
* Show helpful information on JDWP options.
*/
-static void showJdwpHelp(void)
+static void showJdwpHelp()
{
dvmFprintf(stderr,
"Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
@@ -200,7 +199,7 @@
/*
* Show version and copyright info.
*/
-static void showVersion(void)
+static void showVersion()
{
dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
@@ -516,7 +515,7 @@
*
* This must only be called from the main thread during zygote init.
*/
-void dvmLateEnableAssertions(void)
+void dvmLateEnableAssertions()
{
if (gDvm.assertionCtrl == NULL) {
LOGD("Not late-enabling assertions: no assertionCtrl array\n");
@@ -540,7 +539,7 @@
/*
* Release memory associated with the AssertionCtrl array.
*/
-static void freeAssertionCtrl(void)
+static void freeAssertionCtrl()
{
int i;
@@ -1332,7 +1331,7 @@
#ifndef NDEBUG
if (!dvmTestHash())
- LOGE("dmvTestHash FAILED\n");
+ LOGE("dvmTestHash FAILED\n");
if (false /*noisy!*/ && !dvmTestIndirectRefTable())
LOGE("dvmTestIndirectRefTable FAILED\n");
#endif
@@ -1387,7 +1386,7 @@
/*
* Do zygote-mode-only initialization.
*/
-static bool initZygote(void)
+static bool initZygote()
{
/* zygote goes into its own process group */
setpgid(0,0);
@@ -1399,7 +1398,7 @@
* Do non-zygote-mode initialization. This is done during VM init for
* standard startup, or after a "zygote fork" when creating a new process.
*/
-bool dvmInitAfterZygote(void)
+bool dvmInitAfterZygote()
{
u8 startHeap, startQuit, startJdwp;
u8 endHeap, endQuit, endJdwp;
@@ -1475,7 +1474,7 @@
*
* This gets more complicated with a nonzero value for "timeout".
*/
-static bool initJdwp(void)
+static bool initJdwp()
{
assert(!gDvm.zygote);
@@ -1613,7 +1612,7 @@
* same thread that started the VM, a/k/a the main thread, but we don't
* want to assume that.)
*/
-void dvmShutdown(void)
+void dvmShutdown()
{
LOGV("VM shutting down\n");
@@ -1719,7 +1718,7 @@
*
* TODO: move this into libs/cutils and make it work for all platforms.
*/
-void dvmPrintNativeBackTrace(void)
+void dvmPrintNativeBackTrace()
{
size_t MAX_STACK_FRAMES = 64;
void* stackFrames[MAX_STACK_FRAMES];
@@ -1742,7 +1741,7 @@
free(strings);
}
#else
-void dvmPrintNativeBackTrace(void) {
+void dvmPrintNativeBackTrace() {
/* Hopefully, you're on an Android device and debuggerd will do this. */
}
#endif
@@ -1751,7 +1750,7 @@
* Abort the VM. We get here on fatal errors. Try very hard not to use
* this; whenever possible, return an error to somebody responsible.
*/
-void dvmAbort(void)
+void dvmAbort()
{
LOGE("VM aborting\n");
diff --git a/vm/Init.h b/vm/Init.h
index ef56f26..4d85c2e 100644
--- a/vm/Init.h
+++ b/vm/Init.h
@@ -58,15 +58,6 @@
*/
bool dvmFindReferenceMembers(ClassObject* classReference);
-typedef void ObjectReferenceCallback(Object** pReference);
-
-/*
- * Perform a callback on each of the object references used directly
- * by the VM. The value passed into the callback is a pointer to where
- * the reference is stored.
- */
-void dvmForEachRequiredReference(ObjectReferenceCallback* callback);
-
/*
* Replacement for fprintf() when we want to send a message to the console.
* This defaults to fprintf(), but will use the JNI fprintf callback if
diff --git a/vm/InitRefs.c b/vm/InitRefs.cpp
similarity index 77%
rename from vm/InitRefs.c
rename to vm/InitRefs.cpp
index 5a9ba2a..2b99850 100644
--- a/vm/InitRefs.c
+++ b/vm/InitRefs.cpp
@@ -21,112 +21,10 @@
#include "Dalvik.h"
-void dvmForEachRequiredReference(ObjectReferenceCallback* callback) {
- /*
- * TODO: Check to see if this function is ever needed in practice
- * (after letting it hang out in the codebase for a little while).
- * Originally it looked like the GC might want it, but that was a
- * mistaken impression.
- */
- callback((Object**) (void*) &gDvm.classArrayBoolean);
- callback((Object**) (void*) &gDvm.classArrayByte);
- callback((Object**) (void*) &gDvm.classArrayChar);
- callback((Object**) (void*) &gDvm.classArrayDouble);
- callback((Object**) (void*) &gDvm.classArrayFloat);
- callback((Object**) (void*) &gDvm.classArrayInt);
- callback((Object**) (void*) &gDvm.classArrayLong);
- callback((Object**) (void*) &gDvm.classArrayShort);
- callback((Object**) (void*) &gDvm.classJavaLangAnnotationAnnotationArray);
- callback((Object**) (void*) &gDvm.classJavaLangAnnotationAnnotationArrayArray);
- callback((Object**) (void*) &gDvm.classJavaLangClass);
- callback((Object**) (void*) &gDvm.classJavaLangClassArray);
- callback((Object**) (void*) &gDvm.classJavaLangClassLoader);
- callback((Object**) (void*) &gDvm.classJavaLangObject);
- callback((Object**) (void*) &gDvm.classJavaLangObjectArray);
- callback((Object**) (void*) &gDvm.classJavaLangRefFinalizerReference);
- callback((Object**) (void*) &gDvm.classJavaLangReflectAccessibleObject);
- callback((Object**) (void*) &gDvm.classJavaLangReflectConstructor);
- callback((Object**) (void*) &gDvm.classJavaLangReflectConstructorArray);
- callback((Object**) (void*) &gDvm.classJavaLangReflectField);
- callback((Object**) (void*) &gDvm.classJavaLangReflectFieldArray);
- callback((Object**) (void*) &gDvm.classJavaLangReflectMethod);
- callback((Object**) (void*) &gDvm.classJavaLangReflectMethodArray);
- callback((Object**) (void*) &gDvm.classJavaLangReflectProxy);
- callback((Object**) (void*) &gDvm.classJavaLangStackTraceElement);
- callback((Object**) (void*) &gDvm.classJavaLangStackTraceElementArray);
- callback((Object**) (void*) &gDvm.classJavaLangString);
- callback((Object**) (void*) &gDvm.classJavaLangThread);
- callback((Object**) (void*) &gDvm.classJavaLangThreadGroup);
- callback((Object**) (void*) &gDvm.classJavaLangVMThread);
- callback((Object**) (void*) &gDvm.classJavaNioReadWriteDirectByteBuffer);
- callback((Object**) (void*) &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
- callback((Object**) (void*) &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
- callback((Object**) (void*) &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray);
- callback((Object**) (void*) &gDvm.classOrgApacheHarmonyDalvikDdmcChunk);
- callback((Object**) (void*) &gDvm.classOrgApacheHarmonyDalvikDdmcDdmServer);
- callback((Object**) (void*) &gDvm.exAbstractMethodError);
- callback((Object**) (void*) &gDvm.exArithmeticException);
- callback((Object**) (void*) &gDvm.exArrayIndexOutOfBoundsException);
- callback((Object**) (void*) &gDvm.exArrayStoreException);
- callback((Object**) (void*) &gDvm.exClassCastException);
- callback((Object**) (void*) &gDvm.exClassCircularityError);
- callback((Object**) (void*) &gDvm.exClassFormatError);
- callback((Object**) (void*) &gDvm.exClassNotFoundException);
- callback((Object**) (void*) &gDvm.exError);
- callback((Object**) (void*) &gDvm.exExceptionInInitializerError);
- callback((Object**) (void*) &gDvm.exFileNotFoundException);
- callback((Object**) (void*) &gDvm.exIOException);
- callback((Object**) (void*) &gDvm.exIllegalAccessError);
- callback((Object**) (void*) &gDvm.exIllegalAccessException);
- callback((Object**) (void*) &gDvm.exIllegalArgumentException);
- callback((Object**) (void*) &gDvm.exIllegalMonitorStateException);
- callback((Object**) (void*) &gDvm.exIllegalStateException);
- callback((Object**) (void*) &gDvm.exIllegalThreadStateException);
- callback((Object**) (void*) &gDvm.exIncompatibleClassChangeError);
- callback((Object**) (void*) &gDvm.exInstantiationError);
- callback((Object**) (void*) &gDvm.exInstantiationException);
- callback((Object**) (void*) &gDvm.exInternalError);
- callback((Object**) (void*) &gDvm.exInterruptedException);
- callback((Object**) (void*) &gDvm.exLinkageError);
- callback((Object**) (void*) &gDvm.exNegativeArraySizeException);
- callback((Object**) (void*) &gDvm.exNoClassDefFoundError);
- callback((Object**) (void*) &gDvm.exNoSuchFieldError);
- callback((Object**) (void*) &gDvm.exNoSuchFieldException);
- callback((Object**) (void*) &gDvm.exNoSuchMethodError);
- callback((Object**) (void*) &gDvm.exNullPointerException);
- callback((Object**) (void*) &gDvm.exOutOfMemoryError);
- callback((Object**) (void*) &gDvm.exRuntimeException);
- callback((Object**) (void*) &gDvm.exStackOverflowError);
- callback((Object**) (void*) &gDvm.exStaleDexCacheError);
- callback((Object**) (void*) &gDvm.exStringIndexOutOfBoundsException);
- callback((Object**) (void*) &gDvm.exThrowable);
- callback((Object**) (void*) &gDvm.exTypeNotPresentException);
- callback((Object**) (void*) &gDvm.exUnsatisfiedLinkError);
- callback((Object**) (void*) &gDvm.exUnsupportedOperationException);
- callback((Object**) (void*) &gDvm.exVerifyError);
- callback((Object**) (void*) &gDvm.exVirtualMachineError);
- callback((Object**) (void*) &gDvm.typeBoolean);
- callback((Object**) (void*) &gDvm.typeByte);
- callback((Object**) (void*) &gDvm.typeChar);
- callback((Object**) (void*) &gDvm.typeDouble);
- callback((Object**) (void*) &gDvm.typeFloat);
- callback((Object**) (void*) &gDvm.typeInt);
- callback((Object**) (void*) &gDvm.typeLong);
- callback((Object**) (void*) &gDvm.typeShort);
- callback((Object**) (void*) &gDvm.typeVoid);
-}
-
static bool initClassReference(ClassObject** pClass, const char* name) {
ClassObject* result;
- if (*pClass != NULL) {
- /*
- * There are a couple cases where it's legit to call this
- * function with an already-initialized reference, so just
- * silently tolerate this instead of complaining loudly.
- */
- return true;
- }
+ assert(*pClass == NULL);
if (name[0] == '[') {
result = dvmFindArrayClass(name, NULL);
@@ -143,11 +41,14 @@
return true;
}
-static bool initClassReferences(void) {
+static bool initClassReferences() {
static struct { ClassObject** ref; const char* name; } classes[] = {
+ /*
+ * Note: The class Class gets special treatment during initial
+ * VM startup, so there is no need to list it here.
+ */
/* The corest of the core classes */
- { &gDvm.classJavaLangClass, "Ljava/lang/Class;" },
{ &gDvm.classJavaLangObject, "Ljava/lang/Object;" },
{ &gDvm.exThrowable, "Ljava/lang/Throwable;" },
@@ -263,7 +164,7 @@
return true;
}
-static bool initFieldOffsets(void) {
+static bool initFieldOffsets() {
struct FieldInfo {
int* offset;
const char* name;
@@ -419,7 +320,7 @@
return initDirectMethodReferenceByClass(pMethod, clazz, name, descriptor);
}
-static bool initConstructorReferences(void) {
+static bool initConstructorReferences() {
static struct { Method** method; const char* name; const char* descriptor; } constructors[] = {
{ &gDvm.methJavaLangStackTraceElement_init, "Ljava/lang/StackTraceElement;",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" },
@@ -449,7 +350,7 @@
return true;
}
-static bool initDirectMethodReferences(void) {
+static bool initDirectMethodReferences() {
static struct {
Method** method;
const char* className;
@@ -511,7 +412,7 @@
return true;
}
-static bool initVirtualMethodOffsets(void) {
+static bool initVirtualMethodOffsets() {
static struct {
int* offset;
const char* className;
@@ -558,7 +459,7 @@
return true;
}
-static bool verifyStringOffsets(void) {
+static bool verifyStringOffsets() {
/*
* Various parts of the system use predefined constants for the
* offsets to a few fields of the class String. This code verifies
@@ -577,7 +478,7 @@
}
/* (documented in header) */
-bool dvmFindRequiredClassesAndMembers(void) {
+bool dvmFindRequiredClassesAndMembers() {
/*
* Note: Under normal VM use, this is called by dvmStartup()
* in Init.c. For dex optimization, this is called as well, but in
diff --git a/vm/InlineNative.c b/vm/InlineNative.cpp
similarity index 97%
rename from vm/InlineNative.c
rename to vm/InlineNative.cpp
index f230c12..f4f4e8c 100644
--- a/vm/InlineNative.c
+++ b/vm/InlineNative.cpp
@@ -27,7 +27,7 @@
//#warning "trying memcmp16"
//#define CHECK_MEMCMP16
/* "count" is in 16-bit units */
-extern u4 __memcmp16(const u2* s0, const u2* s1, size_t count);
+extern "C" u4 __memcmp16(const u2* s0, const u2* s1, size_t count);
#endif
/*
@@ -146,7 +146,7 @@
chars = (ArrayObject*)
dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
- pResult->i = ((const u2*) chars->contents)[arg1 + offset];
+ pResult->i = ((const u2*)(void*)chars->contents)[arg1 + offset];
return true;
}
}
@@ -238,8 +238,8 @@
dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
compArray = (ArrayObject*)
dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
- thisChars = ((const u2*) thisArray->contents) + thisOffset;
- compChars = ((const u2*) compArray->contents) + compOffset;
+ thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset;
+ compChars = ((const u2*)(void*)compArray->contents) + compOffset;
#ifdef HAVE__MEMCMP16
/*
@@ -359,8 +359,8 @@
dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
compArray = (ArrayObject*)
dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
- thisChars = ((const u2*) thisArray->contents) + thisOffset;
- compChars = ((const u2*) compArray->contents) + compOffset;
+ thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset;
+ compChars = ((const u2*)(void*)compArray->contents) + compOffset;
#ifdef HAVE__MEMCMP16
pResult->i = (__memcmp16(thisChars, compChars, thisCount) == 0);
@@ -452,7 +452,7 @@
/* pull out the basic elements */
ArrayObject* charArray =
(ArrayObject*) dvmGetFieldObject(strObj, STRING_FIELDOFF_VALUE);
- const u2* chars = (const u2*) charArray->contents;
+ const u2* chars = (const u2*)(void*)charArray->contents;
int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET);
int count = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT);
//LOGI("String.indexOf(0x%08x, 0x%04x, %d) off=%d count=%d\n",
@@ -511,16 +511,16 @@
* ===========================================================================
*/
-typedef union {
+union Convert32 {
u4 arg;
float ff;
-} Convert32;
+};
-typedef union {
+union Convert64 {
u4 arg[2];
s8 ll;
double dd;
-} Convert64;
+};
/*
* public static int abs(int)
@@ -780,7 +780,7 @@
/*
* Allocate some tables.
*/
-bool dvmInlineNativeStartup(void)
+bool dvmInlineNativeStartup()
{
gDvm.inlinedMethods =
(Method**) calloc(NELEM(gDvmInlineOpsTable), sizeof(Method*));
@@ -793,7 +793,7 @@
/*
* Free generated tables.
*/
-void dvmInlineNativeShutdown(void)
+void dvmInlineNativeShutdown()
{
free(gDvm.inlinedMethods);
}
@@ -802,7 +802,7 @@
/*
* Get a pointer to the inlineops table.
*/
-const InlineOperation* dvmGetInlineOpsTable(void)
+const InlineOperation* dvmGetInlineOpsTable()
{
return gDvmInlineOpsTable;
}
@@ -810,7 +810,7 @@
/*
* Get the number of entries in the inlineops table.
*/
-int dvmGetInlineOpsTableLength(void)
+int dvmGetInlineOpsTableLength()
{
return NELEM(gDvmInlineOpsTable);
}
diff --git a/vm/InlineNative.h b/vm/InlineNative.h
index 4ca90e2..64caec9 100644
--- a/vm/InlineNative.h
+++ b/vm/InlineNative.h
@@ -45,19 +45,19 @@
* generate assembly code that knows how many args it needs and has the
* target address embedded.
*/
-typedef struct InlineOperation {
+struct InlineOperation {
InlineOp4Func func; /* MUST be first entry */
const char* classDescriptor;
const char* methodName;
const char* methodSignature;
-} InlineOperation;
+};
/*
* Must be kept in sync w/ gDvmInlineOpsTable in InlineNative.c
*
* You should also add a test to libcore's IntrinsicTest.
*/
-typedef enum NativeInlineOps {
+enum NativeInlineOps {
INLINE_EMPTYINLINEMETHOD = 0,
INLINE_STRING_CHARAT = 1,
INLINE_STRING_COMPARETO = 2,
@@ -80,7 +80,7 @@
INLINE_DOUBLE_TO_LONG_BITS = 19,
INLINE_DOUBLE_TO_RAW_LONG_BITS = 20,
INLINE_LONG_BITS_TO_DOUBLE = 21,
-} NativeInlineOps;
+};
/*
* Get the inlineops table.
@@ -119,6 +119,75 @@
/*
* Return method & populate the table on first use.
*/
-Method* dvmResolveInlineNative(int opIndex);
+extern "C" Method* dvmResolveInlineNative(int opIndex);
+
+/*
+ * The actual inline native definitions.
+ */
+bool javaLangString_charAt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangString_equals(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangString_length(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangString_isEmpty(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangString_fastIndexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_min_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult);
+
+bool javaLangFloat_floatToIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
+
+bool javaLangFloat_floatToRawIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
+
+bool javaLangFloat_intBitsToFloat(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
+
+bool javaLangDouble_doubleToLongBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
+
+bool javaLangDouble_longBitsToDouble(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
+
+bool javaLangDouble_doubleToRawLongBits(u4 arg0, u4 arg1, u4 arg2,
+ u4 arg, JValue* pResult);
+
+bool javaLangDouble_longBitsToDouble(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+ JValue* pResult);
#endif /*_DALVIK_INLINENATIVE*/
diff --git a/vm/Inlines.c b/vm/Inlines.cpp
similarity index 96%
rename from vm/Inlines.c
rename to vm/Inlines.cpp
index f1bd621..3ab7717 100644
--- a/vm/Inlines.c
+++ b/vm/Inlines.cpp
@@ -22,7 +22,7 @@
#include "Dalvik.h"
#include "analysis/CodeVerify.h"
#include "analysis/RegisterMap.h"
-#include "mterp/c/header.c"
+#include "mterp/c/header.cpp"
#undef LOG_TAG
#include "jdwp/JdwpPriv.h"
diff --git a/vm/Intern.c b/vm/Intern.cpp
similarity index 98%
rename from vm/Intern.c
rename to vm/Intern.cpp
index 8f84528..8215107 100644
--- a/vm/Intern.c
+++ b/vm/Intern.cpp
@@ -23,7 +23,7 @@
/*
* Prep string interning.
*/
-bool dvmStringInternStartup(void)
+bool dvmStringInternStartup()
{
dvmInitMutex(&gDvm.internLock);
gDvm.internedStrings = dvmHashTableCreate(256, NULL);
@@ -40,7 +40,7 @@
*
* The contents of the list are StringObjects that live on the GC heap.
*/
-void dvmStringInternShutdown(void)
+void dvmStringInternShutdown()
{
if (gDvm.internedStrings != NULL || gDvm.literalStrings != NULL) {
dvmDestroyMutex(&gDvm.internLock);
diff --git a/vm/JarFile.c b/vm/JarFile.cpp
similarity index 99%
rename from vm/JarFile.c
rename to vm/JarFile.cpp
index f26f1d6..0288fef 100644
--- a/vm/JarFile.c
+++ b/vm/JarFile.cpp
@@ -119,7 +119,7 @@
LOGV("dvmDexCacheStatus: Checking cache for %s\n", fileName);
cachedName = dexOptGenerateCacheFileName(fileName, kDexInJarName);
if (cachedName == NULL)
- return -1;
+ return DEX_CACHE_BAD_ARCHIVE;
fd = dvmOpenCachedDexFile(fileName, cachedName,
dexGetZipEntryModTime(&archive, entry),
diff --git a/vm/JarFile.h b/vm/JarFile.h
index 36849ec..e199951 100644
--- a/vm/JarFile.h
+++ b/vm/JarFile.h
@@ -23,12 +23,12 @@
* This represents an open, scanned Jar file. (It's actually for any Zip
* archive that happens to hold a Dex file.)
*/
-typedef struct JarFile {
+struct JarFile {
ZipArchive archive;
//MemMapping map;
char* cacheFileName;
DvmDex* pDvmDex;
-} JarFile;
+};
/*
* Open the Zip archive and get a list of the classfile entries.
@@ -54,13 +54,13 @@
return pJarFile->cacheFileName;
}
-typedef enum DexCacheStatus {
+enum DexCacheStatus {
DEX_CACHE_ERROR = -2,
DEX_CACHE_BAD_ARCHIVE = -1,
DEX_CACHE_OK = 0,
DEX_CACHE_STALE,
DEX_CACHE_STALE_ODEX,
-} DexCacheStatus;
+};
/*
* Checks the dependencies of the dex cache file corresponding
diff --git a/vm/Jni.c b/vm/Jni.cpp
similarity index 68%
rename from vm/Jni.c
rename to vm/Jni.cpp
index 6f96132..e3ef617 100644
--- a/vm/Jni.c
+++ b/vm/Jni.cpp
@@ -19,6 +19,8 @@
*/
#include "Dalvik.h"
#include "JniInternal.h"
+#include "ScopedPthreadMutexLock.h"
+#include "UniquePtr.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -35,8 +37,7 @@
With a rudimentary GC we should be able to skip the status change for
simple functions, e.g. IsSameObject, GetJavaVM, GetStringLength, maybe
even access to fields with primitive types. Our options are more limited
-with a compacting GC, so we should replace JNI_ENTER with JNI_ENTER_NCGC
-or somesuch on the "lite" functions if we want to try this optimization.
+with a compacting GC.
For performance reasons we do as little error-checking as possible here.
For example, we don't check to make sure the correct type of Object is
@@ -123,125 +124,65 @@
Local reference tracking
-The table of local references can be stored on the interpreted stack or
-in a parallel data structure (one per thread).
-
-*** Approach #1: use the interpreted stack
-
-The easiest place to tuck it is between the frame ptr and the first saved
-register, which is always in0. (See the ASCII art in Stack.h.) We can
-shift the "VM-specific goop" and frame ptr down, effectively inserting
-the JNI local refs in the space normally occupied by local variables.
-
-(Three things are accessed from the frame pointer:
- (1) framePtr[N] is register vN, used to get at "ins" and "locals".
- (2) framePtr - sizeof(StackSaveArea) is the VM frame goop.
- (3) framePtr - sizeof(StackSaveArea) - numOuts is where the "outs" go.
-The only thing that isn't determined by an offset from the current FP
-is the previous frame. However, tucking things below the previous frame
-can be problematic because the "outs" of the previous frame overlap with
-the "ins" of the current frame. If the "ins" are altered they must be
-restored before we return. For a native method call, the easiest and
-safest thing to disrupt is #1, because there are no locals and the "ins"
-are all copied to the native stack.)
-
-We can implement Push/PopLocalFrame with the existing stack frame calls,
-making sure we copy some goop from the previous frame (notably the method
-ptr, so that dvmGetCurrentJNIMethod() doesn't require extra effort).
-
-We can pre-allocate the storage at the time the stack frame is first
-set up, but we have to be careful. When calling from interpreted code
-the frame ptr points directly at the arguments we're passing, but we can
-offset the args pointer when calling the native bridge.
-
-To manage the local ref collection, we need to be able to find three
-things: (1) the start of the region, (2) the end of the region, and (3)
-the next available entry. The last is only required for quick adds.
-We currently have two easily-accessible pointers, the current FP and the
-previous frame's FP. (The "stack pointer" shown in the ASCII art doesn't
-actually exist in the interpreted world.)
-
-We can't use the current FP to find the first "in", because we want to
-insert the variable-sized local refs table between them. It's awkward
-to use the previous frame's FP because native methods invoked via
-dvmCallMethod() or dvmInvokeMethod() don't have "ins", but native methods
-invoked from interpreted code do. We can either track the local refs
-table size with a field in the stack frame, or insert unnecessary items
-so that all native stack frames have "ins".
-
-Assuming we can find the region bounds, we still need pointer #3
-for an efficient implementation. This can be stored in an otherwise
-unused-for-native field in the frame goop.
-
-When we run out of room we have to make more space. If we start allocating
-locals immediately below in0 and grow downward, we will detect end-of-space
-by running into the current frame's FP. We then memmove() the goop down
-(memcpy if we guarantee the additional size is larger than the frame).
-This is nice because we only have to move sizeof(StackSaveArea) bytes
-each time.
-
-Stack walking should be okay so long as nothing tries to access the
-"ins" by an offset from the FP. In theory the "ins" could be read by
-the debugger or SIGQUIT handler looking for "this" or other arguments,
-but in practice this behavior isn't expected to work for native methods,
-so we can simply disallow it.
-
-A conservative GC can just scan the entire stack from top to bottom to find
-all references. An exact GC will need to understand the actual layout.
-
-*** Approach #2: use a parallel stack
-
-Each Thread/JNIEnv points to a reference table. The struct has
-a system-heap-allocated array of references and a pointer to the
-next-available entry ("nextEntry").
-
-Each stack frame has a pointer to what it sees as the "bottom" element
-in the array (we can double-up the "currentPc" field). This is set to
-"nextEntry" when the frame is pushed on. As local references are added
-or removed, "nextEntry" is updated.
+Each Thread/JNIEnv points to an IndirectRefTable.
We implement Push/PopLocalFrame with actual stack frames. Before a JNI
frame gets popped, we set "nextEntry" to the "top" pointer of the current
frame, effectively releasing the references.
-The GC will scan all references from the start of the table to the
-"nextEntry" pointer.
-
-*** Comparison
-
-All approaches will return a failure result when they run out of local
-reference space. For #1 that means blowing out the stack, for #2 it's
-running out of room in the array.
-
-Compared to #1, approach #2:
- - Needs only one pointer in the stack frame goop.
- - Makes pre-allocating storage unnecessary.
- - Doesn't contend with interpreted stack depth for space. In most
- cases, if something blows out the local ref storage, it's because the
- JNI code was misbehaving rather than called from way down.
- - Allows the GC to do a linear scan per thread in a buffer that is 100%
- references. The GC can be slightly less smart when scanning the stack.
- - Will be easier to work with if we combine native and interpeted stacks.
-
- - Isn't as clean, especially when popping frames, since we have to do
- explicit work. Fortunately we only have to do it when popping native
- method calls off, so it doesn't add overhead to interpreted code paths.
- - Is awkward to expand dynamically. We'll want to pre-allocate the full
- amount of space; this is fine, since something on the order of 1KB should
- be plenty. The JNI spec allows us to limit this.
- - Requires the GC to scan even more memory. With the references embedded
- in the stack we get better locality of reference.
+The GC will scan all references in the table.
*/
-/* fwd */
-static const struct JNINativeInterface gNativeInterface;
-
#ifdef WITH_JNI_STACK_CHECK
# define COMPUTE_STACK_SUM(_self) computeStackSum(_self);
# define CHECK_STACK_SUM(_self) checkStackSum(_self);
-//static void computeStackSum(Thread* self);
-//static void checkStackSum(Thread* self);
+
+/*
+ * Compute a CRC on the entire interpreted stack.
+ *
+ * Would be nice to compute it on "self" as well, but there are parts of
+ * the Thread that can be altered by other threads (e.g. prev/next pointers).
+ */
+static void computeStackSum(Thread* self) {
+ const u1* low = (const u1*)SAVEAREA_FROM_FP(self->interpSave.curFrame);
+ u4 crc = dvmInitCrc32();
+ self->stackCrc = 0;
+ crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
+ self->stackCrc = crc;
+}
+
+/*
+ * Compute a CRC on the entire interpreted stack, and compare it to what
+ * we previously computed.
+ *
+ * We can execute JNI directly from native code without calling in from
+ * interpreted code during VM initialization and immediately after JNI
+ * thread attachment. Another opportunity exists during JNI_OnLoad. Rather
+ * than catching these cases we just ignore them here, which is marginally
+ * less accurate but reduces the amount of code we have to touch with #ifdefs.
+ */
+static void checkStackSum(Thread* self) {
+ const u1* low = (const u1*)SAVEAREA_FROM_FP(self->interpSave.curFrame);
+ u4 stackCrc = self->stackCrc;
+ self->stackCrc = 0;
+ u4 crc = dvmInitCrc32();
+ crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
+ if (crc != stackCrc) {
+ const Method* meth = dvmGetCurrentJNIMethod();
+ if (dvmComputeExactFrameDepth(self->interpSave.curFrame) == 1) {
+ LOGD("JNI: bad stack CRC (0x%08x) -- okay during init", stackCrc);
+ } else if (strcmp(meth->name, "nativeLoad") == 0 &&
+ (strcmp(meth->clazz->descriptor, "Ljava/lang/Runtime;") == 0)) {
+ LOGD("JNI: bad stack CRC (0x%08x) -- okay during JNI_OnLoad", stackCrc);
+ } else {
+ LOGW("JNI: bad stack CRC (%08x vs %08x)", crc, stackCrc);
+ dvmAbort();
+ }
+ }
+ self->stackCrc = (u4) -1; /* make logic errors more noticeable */
+}
+
#else
# define COMPUTE_STACK_SUM(_self) ((void)0)
# define CHECK_STACK_SUM(_self) ((void)0)
@@ -257,29 +198,36 @@
/*
* Entry/exit processing for all JNI calls.
*
- * If TRUSTED_JNIENV is set, we get to skip the (curiously expensive)
- * thread-local storage lookup on our Thread*. If the caller has passed
- * the wrong JNIEnv in, we're going to be accessing unsynchronized
+ * We skip the (curiously expensive) thread-local storage lookup on our Thread*.
+ * If the caller has passed the wrong JNIEnv in, we're going to be accessing unsynchronized
* structures from more than one thread, and things are going to fail
* in bizarre ways. This is only sensible if the native code has been
* fully exercised with CheckJNI enabled.
*/
-#define TRUSTED_JNIENV
-#ifdef TRUSTED_JNIENV
-# define JNI_ENTER() \
- Thread* _self = ((JNIEnvExt*)env)->self; \
- CHECK_STACK_SUM(_self); \
- dvmChangeStatus(_self, THREAD_RUNNING)
-#else
-# define JNI_ENTER() \
- Thread* _self = dvmThreadSelf(); \
- UNUSED_PARAMETER(env); \
- CHECK_STACK_SUM(_self); \
- dvmChangeStatus(_self, THREAD_RUNNING)
-#endif
-#define JNI_EXIT() \
- dvmChangeStatus(_self, THREAD_NATIVE); \
- COMPUTE_STACK_SUM(_self)
+class ScopedJniThreadState {
+public:
+ explicit ScopedJniThreadState(JNIEnv* env) {
+ mSelf = ((JNIEnvExt*) env)->self; // dvmThreadSelf() would be safer
+ CHECK_STACK_SUM(mSelf);
+ dvmChangeStatus(mSelf, THREAD_RUNNING);
+ }
+
+ ~ScopedJniThreadState() {
+ dvmChangeStatus(mSelf, THREAD_NATIVE);
+ COMPUTE_STACK_SUM(mSelf);
+ }
+
+ Thread* self() {
+ return mSelf;
+ }
+
+private:
+ Thread* mSelf;
+
+ // Disallow copy and assignment.
+ ScopedJniThreadState(const ScopedJniThreadState&);
+ void operator=(const ScopedJniThreadState&);
+};
#define kGlobalRefsTableInitialSize 512
#define kGlobalRefsTableMaxSize 51200 /* arbitrary, must be < 64K */
@@ -292,155 +240,61 @@
#define kPinTableMaxSize 1024
#define kPinComplainThreshold 10
-/*
- * Allocate the global references table, and look up some classes for
- * the benefit of direct buffer access.
- */
-bool dvmJniStartup(void)
-{
+bool dvmJniStartup() {
if (!dvmInitIndirectRefTable(&gDvm.jniGlobalRefTable,
kGlobalRefsTableInitialSize,
kGlobalRefsTableMaxSize,
- kIndirectKindGlobal))
+ kIndirectKindGlobal)) {
return false;
+ }
if (!dvmInitIndirectRefTable(&gDvm.jniWeakGlobalRefTable,
kWeakGlobalRefsTableInitialSize,
kGlobalRefsTableMaxSize,
- kIndirectKindWeakGlobal))
+ kIndirectKindWeakGlobal)) {
return false;
+ }
dvmInitMutex(&gDvm.jniGlobalRefLock);
dvmInitMutex(&gDvm.jniWeakGlobalRefLock);
gDvm.jniGlobalRefLoMark = 0;
gDvm.jniGlobalRefHiMark = kGrefWaterInterval * 2;
- if (!dvmInitReferenceTable(&gDvm.jniPinRefTable,
- kPinTableInitialSize, kPinTableMaxSize))
+ if (!dvmInitReferenceTable(&gDvm.jniPinRefTable, kPinTableInitialSize, kPinTableMaxSize)) {
return false;
+ }
dvmInitMutex(&gDvm.jniPinRefLock);
return true;
}
-/*
- * Free the global references table.
- */
-void dvmJniShutdown(void)
-{
+void dvmJniShutdown() {
dvmClearIndirectRefTable(&gDvm.jniGlobalRefTable);
dvmClearIndirectRefTable(&gDvm.jniWeakGlobalRefTable);
dvmClearReferenceTable(&gDvm.jniPinRefTable);
}
-
/*
* Find the JNIEnv associated with the current thread.
*
* Currently stored in the Thread struct. Could also just drop this into
* thread-local storage.
*/
-JNIEnvExt* dvmGetJNIEnvForThread(void)
-{
+JNIEnvExt* dvmGetJNIEnvForThread() {
Thread* self = dvmThreadSelf();
- if (self == NULL)
+ if (self == NULL) {
return NULL;
+ }
return (JNIEnvExt*) dvmGetThreadJNIEnv(self);
}
/*
- * Create a new JNIEnv struct and add it to the VM's list.
- *
- * "self" will be NULL for the main thread, since the VM hasn't started
- * yet; the value will be filled in later.
- */
-JNIEnv* dvmCreateJNIEnv(Thread* self)
-{
- JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
- JNIEnvExt* newEnv;
-
- //if (self != NULL)
- // LOGI("Ent CreateJNIEnv: threadid=%d %p\n", self->threadId, self);
-
- assert(vm != NULL);
-
- newEnv = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
- newEnv->funcTable = &gNativeInterface;
- newEnv->vm = vm;
- newEnv->forceDataCopy = vm->forceDataCopy;
- if (self != NULL) {
- dvmSetJniEnvThreadId((JNIEnv*) newEnv, self);
- assert(newEnv->envThreadId != 0);
- } else {
- /* make it obvious if we fail to initialize these later */
- newEnv->envThreadId = 0x77777775;
- newEnv->self = (Thread*) 0x77777779;
- }
- if (vm->useChecked)
- dvmUseCheckedJniEnv(newEnv);
-
- dvmLockMutex(&vm->envListLock);
-
- /* insert at head of list */
- newEnv->next = vm->envList;
- assert(newEnv->prev == NULL);
- if (vm->envList == NULL) // rare, but possible
- vm->envList = newEnv;
- else
- vm->envList->prev = newEnv;
- vm->envList = newEnv;
-
- dvmUnlockMutex(&vm->envListLock);
-
- //if (self != NULL)
- // LOGI("Xit CreateJNIEnv: threadid=%d %p\n", self->threadId, self);
- return (JNIEnv*) newEnv;
-}
-
-/*
- * Remove a JNIEnv struct from the list and free it.
- */
-void dvmDestroyJNIEnv(JNIEnv* env)
-{
- JNIEnvExt* extEnv = (JNIEnvExt*) env;
- JavaVMExt* vm = extEnv->vm;
- Thread* self;
-
- if (env == NULL)
- return;
-
- self = dvmThreadSelf();
- assert(self != NULL);
-
- //LOGI("Ent DestroyJNIEnv: threadid=%d %p\n", self->threadId, self);
-
- dvmLockMutex(&vm->envListLock);
-
- if (extEnv == vm->envList) {
- assert(extEnv->prev == NULL);
- vm->envList = extEnv->next;
- } else {
- assert(extEnv->prev != NULL);
- extEnv->prev->next = extEnv->next;
- }
- if (extEnv->next != NULL)
- extEnv->next->prev = extEnv->prev;
-
- dvmUnlockMutex(&extEnv->vm->envListLock);
-
- free(env);
- //LOGI("Xit DestroyJNIEnv: threadid=%d %p\n", self->threadId, self);
-}
-
-
-/*
* Retrieve the ReferenceTable struct for the current thread.
*
* Going through "env" rather than dvmThreadSelf() is faster but will
* get weird if the JNI code is passing the wrong JNIEnv around.
*/
-static inline IndirectRefTable* getLocalRefTable(JNIEnv* env)
-{
+static inline IndirectRefTable* getLocalRefTable(JNIEnv* env) {
return &((JNIEnvExt*)env)->self->jniLocalRefTable;
}
@@ -452,10 +306,10 @@
* been cleared, this returns NULL. If jobj is an invalid indirect
* reference, kInvalidIndirectRefObject is returned.
*/
-Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj)
-{
- if (jobj == NULL)
+Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj) {
+ if (jobj == NULL) {
return NULL;
+ }
Object* result;
@@ -470,18 +324,18 @@
{
// TODO: find a way to avoid the mutex activity here
IndirectRefTable* pRefTable = &gDvm.jniGlobalRefTable;
- dvmLockMutex(&gDvm.jniGlobalRefLock);
+ ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
result = dvmGetFromIndirectRefTable(pRefTable, jobj);
- dvmUnlockMutex(&gDvm.jniGlobalRefLock);
}
break;
case kIndirectKindWeakGlobal:
{
// TODO: find a way to avoid the mutex activity here
IndirectRefTable* pRefTable = &gDvm.jniWeakGlobalRefTable;
- dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
- result = dvmGetFromIndirectRefTable(pRefTable, jobj);
- dvmUnlockMutex(&gDvm.jniWeakGlobalRefLock);
+ {
+ ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
+ result = dvmGetFromIndirectRefTable(pRefTable, jobj);
+ }
/*
* TODO: this is a temporary workaround for broken weak global
* refs (bug 4260055). We treat any invalid reference as if it
@@ -491,14 +345,14 @@
* This must be removed when weak global refs get fixed.
*/
if (result == kInvalidIndirectRefObject) {
- LOGW("Warning: used weak global ref hack\n");
+ LOGW("Warning: used weak global ref hack");
result = NULL;
}
}
break;
case kIndirectKindInvalid:
default:
- LOGW("Invalid indirect reference %p in decodeIndirectRef\n", jobj);
+ LOGW("Invalid indirect reference %p in decodeIndirectRef", jobj);
dvmAbort();
result = kInvalidIndirectRefObject;
break;
@@ -519,23 +373,23 @@
* Returns the local reference (currently just the same pointer that was
* passed in), or NULL on failure.
*/
-static jobject addLocalReference(JNIEnv* env, Object* obj)
-{
- if (obj == NULL)
+static jobject addLocalReference(JNIEnv* env, Object* obj) {
+ if (obj == NULL) {
return NULL;
+ }
IndirectRefTable* pRefTable = getLocalRefTable(env);
- void* curFrame = ((JNIEnvExt*)env)->self->curFrame;
+ void* curFrame = ((JNIEnvExt*)env)->self->interpSave.curFrame;
u4 cookie = SAVEAREA_FROM_FP(curFrame)->xtra.localRefCookie;
jobject jobj = (jobject) dvmAddToIndirectRefTable(pRefTable, cookie, obj);
if (jobj == NULL) {
dvmDumpIndirectRefTable(pRefTable, "JNI local");
- LOGE("Failed adding to JNI local ref table (has %d entries)\n",
+ LOGE("Failed adding to JNI local ref table (has %d entries)",
(int) dvmIndirectRefTableEntries(pRefTable));
dvmDumpThread(dvmThreadSelf(), false);
dvmAbort(); // spec says call FatalError; this is equivalent
} else {
- LOGVV("LREF add %p (%s.%s) (ent=%d)\n", obj,
+ LOGVV("LREF add %p (%s.%s) (ent=%d)", obj,
dvmGetCurrentJNIMethod()->clazz->descriptor,
dvmGetCurrentJNIMethod()->name,
(int) dvmReferenceTableEntries(pRefTable));
@@ -547,8 +401,7 @@
* Ensure that at least "capacity" references can be held in the local
* refs table of the current thread.
*/
-static bool ensureLocalCapacity(JNIEnv* env, int capacity)
-{
+static bool ensureLocalCapacity(JNIEnv* env, int capacity) {
IndirectRefTable* pRefTable = getLocalRefTable(env);
int numEntries = dvmIndirectRefTableEntries(pRefTable);
// TODO: this isn't quite right, since "numEntries" includes holes
@@ -558,14 +411,15 @@
/*
* Explicitly delete a reference from the local list.
*/
-static void deleteLocalReference(JNIEnv* env, jobject jobj)
-{
- if (jobj == NULL)
+static void deleteLocalReference(JNIEnv* env, jobject jobj) {
+ if (jobj == NULL) {
return;
+ }
IndirectRefTable* pRefTable = getLocalRefTable(env);
Thread* self = ((JNIEnvExt*)env)->self;
- u4 cookie = SAVEAREA_FROM_FP(self->curFrame)->xtra.localRefCookie;
+ u4 cookie =
+ SAVEAREA_FROM_FP(self->interpSave.curFrame)->xtra.localRefCookie;
if (!dvmRemoveFromIndirectRefTable(pRefTable, cookie, jobj)) {
/*
@@ -575,7 +429,7 @@
* complain about it so the user will notice that things aren't
* going quite the way they expect.
*/
- LOGW("JNI WARNING: DeleteLocalRef(%p) failed to find entry\n", jobj);
+ LOGW("JNI WARNING: DeleteLocalRef(%p) failed to find entry", jobj);
}
}
@@ -585,26 +439,26 @@
* We may add the same object more than once. Add/remove calls are paired,
* so it needs to appear on the list multiple times.
*/
-static jobject addGlobalReference(Object* obj)
-{
- if (obj == NULL)
+static jobject addGlobalReference(Object* obj) {
+ if (obj == NULL) {
return NULL;
+ }
- //LOGI("adding obj=%p\n", obj);
+ //LOGI("adding obj=%p", obj);
//dvmDumpThread(dvmThreadSelf(), false);
- if (false && ((Object*)obj)->clazz == gDvm.classJavaLangClass) {
+ if (false && dvmIsClassObject((Object*)obj)) {
ClassObject* clazz = (ClassObject*) obj;
- LOGI("-------\n");
- LOGI("Adding global ref on class %s\n", clazz->descriptor);
+ LOGI("-------");
+ LOGI("Adding global ref on class %s", clazz->descriptor);
dvmDumpThread(dvmThreadSelf(), false);
}
if (false && ((Object*)obj)->clazz == gDvm.classJavaLangString) {
StringObject* strObj = (StringObject*) obj;
char* str = dvmCreateCstrFromString(strObj);
if (strcmp(str, "sync-response") == 0) {
- LOGI("-------\n");
- LOGI("Adding global ref on string '%s'\n", str);
+ LOGI("-------");
+ LOGI("Adding global ref on string '%s'", str);
dvmDumpThread(dvmThreadSelf(), false);
//dvmAbort();
}
@@ -615,15 +469,13 @@
if (arrayObj->length == 8192 /*&&
dvmReferenceTableEntries(&gDvm.jniGlobalRefTable) > 400*/)
{
- LOGI("Adding global ref on byte array %p (len=%d)\n",
+ LOGI("Adding global ref on byte array %p (len=%d)",
arrayObj, arrayObj->length);
dvmDumpThread(dvmThreadSelf(), false);
}
}
- jobject jobj;
-
- dvmLockMutex(&gDvm.jniGlobalRefLock);
+ ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
/*
* Throwing an exception on failure is problematic, because JNI code
@@ -634,16 +486,16 @@
* we're either leaking global ref table entries or we're going to
* run out of space in the GC heap.
*/
- jobj = dvmAddToIndirectRefTable(&gDvm.jniGlobalRefTable, IRT_FIRST_SEGMENT,
+ jobject jobj = (jobject) dvmAddToIndirectRefTable(&gDvm.jniGlobalRefTable, IRT_FIRST_SEGMENT,
obj);
if (jobj == NULL) {
dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
- LOGE("Failed adding to JNI global ref table (%d entries)\n",
+ LOGE("Failed adding to JNI global ref table (%d entries)",
(int) dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable));
dvmAbort();
}
- LOGVV("GREF add %p (%s.%s)\n", obj,
+ LOGVV("GREF add %p (%s.%s)", obj,
dvmGetCurrentJNIMethod()->clazz->descriptor,
dvmGetCurrentJNIMethod()->name);
@@ -652,54 +504,51 @@
int count = dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable);
// TODO: adjust for "holes"
if (count > gDvm.jniGlobalRefHiMark) {
- LOGD("GREF has increased to %d\n", count);
+ LOGD("GREF has increased to %d", count);
gDvm.jniGlobalRefHiMark += kGrefWaterInterval;
gDvm.jniGlobalRefLoMark += kGrefWaterInterval;
/* watch for "excessive" use; not generally appropriate */
if (count >= gDvm.jniGrefLimit) {
- JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
- if (vm->warnError) {
- dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable,
- "JNI global");
- LOGE("Excessive JNI global references (%d)\n", count);
- dvmAbort();
+ if (gDvmJni.warnOnly) {
+ LOGW("Excessive JNI global references (%d)", count);
} else {
- LOGW("Excessive JNI global references (%d)\n", count);
+ dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
+ LOGE("Excessive JNI global references (%d)", count);
+ dvmAbort();
}
}
}
}
- dvmUnlockMutex(&gDvm.jniGlobalRefLock);
return jobj;
}
-static jobject addWeakGlobalReference(Object* obj)
-{
- if (obj == NULL)
+static jobject addWeakGlobalReference(Object* obj) {
+ if (obj == NULL) {
return NULL;
- dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
+ }
+
+ ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
- jobject jobj = dvmAddToIndirectRefTable(table, IRT_FIRST_SEGMENT, obj);
+ jobject jobj = (jobject) dvmAddToIndirectRefTable(table, IRT_FIRST_SEGMENT, obj);
if (jobj == NULL) {
dvmDumpIndirectRefTable(table, "JNI weak global");
LOGE("Failed adding to JNI weak global ref table (%zd entries)",
dvmIndirectRefTableEntries(table));
}
- dvmUnlockMutex(&gDvm.jniWeakGlobalRefLock);
return jobj;
}
-static void deleteWeakGlobalReference(jobject jobj)
-{
- if (jobj == NULL)
+static void deleteWeakGlobalReference(jobject jobj) {
+ if (jobj == NULL) {
return;
- dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
+ }
+
+ ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
if (!dvmRemoveFromIndirectRefTable(table, IRT_FIRST_SEGMENT, jobj)) {
LOGW("JNI: DeleteWeakGlobalRef(%p) failed to find entry", jobj);
}
- dvmUnlockMutex(&gDvm.jniWeakGlobalRefLock);
}
/*
@@ -709,30 +558,26 @@
* Thought: if it's not the most recent entry, just null it out. When we
* fill up, do a compaction pass before we expand the list.
*/
-static void deleteGlobalReference(jobject jobj)
-{
- if (jobj == NULL)
+static void deleteGlobalReference(jobject jobj) {
+ if (jobj == NULL) {
return;
+ }
- dvmLockMutex(&gDvm.jniGlobalRefLock);
- if (!dvmRemoveFromIndirectRefTable(&gDvm.jniGlobalRefTable,
- IRT_FIRST_SEGMENT, jobj))
- {
- LOGW("JNI: DeleteGlobalRef(%p) failed to find entry\n", jobj);
- goto bail;
+ ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
+ if (!dvmRemoveFromIndirectRefTable(&gDvm.jniGlobalRefTable, IRT_FIRST_SEGMENT, jobj)) {
+ LOGW("JNI: DeleteGlobalRef(%p) failed to find entry", jobj);
+ return;
}
if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
int count = dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable);
// TODO: not quite right, need to subtract holes
if (count < gDvm.jniGlobalRefLoMark) {
- LOGD("GREF has decreased to %d\n", count);
+ LOGD("GREF has decreased to %d", count);
gDvm.jniGlobalRefHiMark -= kGrefWaterInterval;
gDvm.jniGlobalRefLoMark -= kGrefWaterInterval;
}
}
-bail:
- dvmUnlockMutex(&gDvm.jniGlobalRefLock);
}
/*
@@ -741,15 +586,16 @@
*
* We use a separate reference table, which is part of the GC root set.
*/
-static void pinPrimitiveArray(ArrayObject* arrayObj)
-{
- if (arrayObj == NULL)
+static void pinPrimitiveArray(ArrayObject* arrayObj) {
+ if (arrayObj == NULL) {
return;
+ }
- dvmLockMutex(&gDvm.jniPinRefLock);
+ ScopedPthreadMutexLock lock(&gDvm.jniPinRefLock);
+
if (!dvmAddToReferenceTable(&gDvm.jniPinRefTable, (Object*)arrayObj)) {
dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
- LOGE("Failed adding to JNI pinned array ref table (%d entries)\n",
+ LOGE("Failed adding to JNI pinned array ref table (%d entries)",
(int) dvmReferenceTableEntries(&gDvm.jniPinRefTable));
dvmDumpThread(dvmThreadSelf(), false);
dvmAbort();
@@ -772,35 +618,30 @@
}
if (count > kPinComplainThreshold) {
- LOGW("JNI: pin count on array %p (%s) is now %d\n",
- arrayObj, arrayObj->obj.clazz->descriptor, count);
+ LOGW("JNI: pin count on array %p (%s) is now %d",
+ arrayObj, arrayObj->clazz->descriptor, count);
/* keep going */
}
}
-
- dvmUnlockMutex(&gDvm.jniPinRefLock);
}
/*
* Un-pin the array object. If an object was pinned twice, it must be
* unpinned twice before it's free to move.
*/
-static void unpinPrimitiveArray(ArrayObject* arrayObj)
-{
- if (arrayObj == NULL)
+static void unpinPrimitiveArray(ArrayObject* arrayObj) {
+ if (arrayObj == NULL) {
return;
+ }
- dvmLockMutex(&gDvm.jniPinRefLock);
+ ScopedPthreadMutexLock lock(&gDvm.jniPinRefLock);
if (!dvmRemoveFromReferenceTable(&gDvm.jniPinRefTable,
gDvm.jniPinRefTable.table, (Object*) arrayObj))
{
- LOGW("JNI: unpinPrimitiveArray(%p) failed to find entry (valid=%d)\n",
+ LOGW("JNI: unpinPrimitiveArray(%p) failed to find entry (valid=%d)",
arrayObj, dvmIsValidObject((Object*) arrayObj));
- goto bail;
+ return;
}
-
-bail:
- dvmUnlockMutex(&gDvm.jniPinRefLock);
}
/*
@@ -808,8 +649,7 @@
*
* We only dump the local refs associated with the current thread.
*/
-void dvmDumpJniReferenceTables(void)
-{
+void dvmDumpJniReferenceTables() {
Thread* self = dvmThreadSelf();
JNIEnv* env = self->jniEnv;
IndirectRefTable* pLocalRefs = getLocalRefTable(env);
@@ -830,8 +670,7 @@
*
* Used by -Xcheck:jni and GetObjectRefType.
*/
-jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj)
-{
+jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj) {
/*
* IndirectRefKind is currently defined as an exact match of
* jobjectRefType, so this is easy. We have to decode it to determine
@@ -848,8 +687,7 @@
}
}
-static void dumpMethods(Method* methods, size_t methodCount, const char* name)
-{
+static void dumpMethods(Method* methods, size_t methodCount, const char* name) {
size_t i;
for (i = 0; i < methodCount; ++i) {
Method* method = &methods[i];
@@ -861,9 +699,7 @@
}
}
-static void dumpCandidateMethods(ClassObject* clazz, const char* methodName,
- const char* signature)
-{
+static void dumpCandidateMethods(ClassObject* clazz, const char* methodName, const char* signature) {
LOGE("ERROR: couldn't find native method");
LOGE("Requested: %s.%s:%s", clazz->descriptor, methodName, signature);
dumpMethods(clazz->virtualMethods, clazz->virtualMethodCount, methodName);
@@ -876,28 +712,27 @@
static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
const char* signature, void* fnPtr)
{
- if (fnPtr == NULL)
+ if (fnPtr == NULL) {
return false;
+ }
- Method* method =
- dvmFindDirectMethodByDescriptor(clazz, methodName, signature);
- if (method == NULL)
+ Method* method = dvmFindDirectMethodByDescriptor(clazz, methodName, signature);
+ if (method == NULL) {
method = dvmFindVirtualMethodByDescriptor(clazz, methodName, signature);
+ }
if (method == NULL) {
dumpCandidateMethods(clazz, methodName, signature);
return false;
}
if (!dvmIsNativeMethod(method)) {
- LOGW("Unable to register: not native: %s.%s:%s",
- clazz->descriptor, methodName, signature);
+ LOGW("Unable to register: not native: %s.%s:%s", clazz->descriptor, methodName, signature);
return false;
}
if (method->nativeFunc != dvmResolveNativeMethod) {
/* this is allowed, but unusual */
- LOGV("Note: %s.%s:%s was already registered",
- clazz->descriptor, methodName, signature);
+ LOGV("Note: %s.%s:%s was already registered", clazz->descriptor, methodName, signature);
}
dvmUseJNIBridge(method, fnPtr);
@@ -907,20 +742,10 @@
}
/*
- * Returns "true" if CheckJNI is enabled in the VM.
- */
-static bool dvmIsCheckJNIEnabled(void)
-{
- JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
- return vm->useChecked;
-}
-
-/*
* Returns the appropriate JNI bridge for 'method', also taking into account
* the -Xcheck:jni setting.
*/
-static DalvikBridgeFunc dvmSelectJNIBridge(const Method* method)
-{
+static DalvikBridgeFunc dvmSelectJNIBridge(const Method* method) {
enum {
kJNIGeneral = 0,
kJNISync = 1,
@@ -964,21 +789,22 @@
kind = kJNIGeneral;
} else {
/* virtual methods have a ref in args[0] (not in signature) */
- if (dvmIsStaticMethod(method))
+ if (dvmIsStaticMethod(method)) {
kind = kJNIStaticNoRef;
- else
+ } else {
kind = kJNIVirtualNoRef;
+ }
}
}
- return dvmIsCheckJNIEnabled() ? checkFunc[kind] : stdFunc[kind];
+ return gDvmJni.useCheckJni ? checkFunc[kind] : stdFunc[kind];
}
/*
* Trace a call into native code.
*/
static void dvmTraceCallJNIMethod(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
+ const Method* method, Thread* self)
{
dvmLogNativeMethodEntry(method, args);
DalvikBridgeFunc bridge = dvmSelectJNIBridge(method);
@@ -989,8 +815,7 @@
/**
* Returns true if the -Xjnitrace setting implies we should trace 'method'.
*/
-static bool shouldTrace(Method* method)
-{
+static bool shouldTrace(Method* method) {
return gDvm.jniTrace && strstr(method->clazz->descriptor, gDvm.jniTrace);
}
@@ -998,8 +823,7 @@
* Point "method->nativeFunc" at the JNI bridge, and overload "method->insns"
* to point at the actual function.
*/
-void dvmUseJNIBridge(Method* method, void* func)
-{
+void dvmUseJNIBridge(Method* method, void* func) {
DalvikBridgeFunc bridge = shouldTrace(method)
? dvmTraceCallJNIMethod
: dvmSelectJNIBridge(method);
@@ -1009,11 +833,10 @@
/*
* Get the method currently being executed by examining the interp stack.
*/
-const Method* dvmGetCurrentJNIMethod(void)
-{
+const Method* dvmGetCurrentJNIMethod() {
assert(dvmThreadSelf() != NULL);
- void* fp = dvmThreadSelf()->curFrame;
+ void* fp = dvmThreadSelf()->interpSave.curFrame;
const Method* meth = SAVEAREA_FROM_FP(fp)->method;
assert(meth != NULL);
@@ -1021,7 +844,6 @@
return meth;
}
-
/*
* Track a JNI MonitorEnter in the current thread.
*
@@ -1032,8 +854,7 @@
* enter call. It would be more efficient to keep a counter. At present
* there's no real motivation to improve this however.
*/
-static void trackMonitorEnter(Thread* self, Object* obj)
-{
+static void trackMonitorEnter(Thread* self, Object* obj) {
static const int kInitialSize = 16;
ReferenceTable* refTable = &self->jniMonitorRefTable;
@@ -1042,53 +863,50 @@
assert(refTable->maxEntries == 0);
if (!dvmInitReferenceTable(refTable, kInitialSize, INT_MAX)) {
- LOGE("Unable to initialize monitor tracking table\n");
+ LOGE("Unable to initialize monitor tracking table");
dvmAbort();
}
}
if (!dvmAddToReferenceTable(refTable, obj)) {
/* ran out of memory? could throw exception instead */
- LOGE("Unable to add entry to monitor tracking table\n");
+ LOGE("Unable to add entry to monitor tracking table");
dvmAbort();
} else {
- LOGVV("--- added monitor %p\n", obj);
+ LOGVV("--- added monitor %p", obj);
}
}
-
/*
* Track a JNI MonitorExit in the current thread.
*/
-static void trackMonitorExit(Thread* self, Object* obj)
-{
+static void trackMonitorExit(Thread* self, Object* obj) {
ReferenceTable* pRefTable = &self->jniMonitorRefTable;
if (!dvmRemoveFromReferenceTable(pRefTable, pRefTable->table, obj)) {
- LOGE("JNI monitor %p not found in tracking list\n", obj);
+ LOGE("JNI monitor %p not found in tracking list", obj);
/* keep going? */
} else {
- LOGVV("--- removed monitor %p\n", obj);
+ LOGVV("--- removed monitor %p", obj);
}
}
/*
* Release all monitors held by the jniMonitorRefTable list.
*/
-void dvmReleaseJniMonitors(Thread* self)
-{
+void dvmReleaseJniMonitors(Thread* self) {
ReferenceTable* pRefTable = &self->jniMonitorRefTable;
Object** top = pRefTable->table;
- if (top == NULL)
+ if (top == NULL) {
return;
-
+ }
Object** ptr = pRefTable->nextEntry;
while (--ptr >= top) {
if (!dvmUnlockObject(self, *ptr)) {
- LOGW("Unable to unlock monitor %p at thread detach\n", *ptr);
+ LOGW("Unable to unlock monitor %p at thread detach", *ptr);
} else {
- LOGVV("--- detach-releasing monitor %p\n", *ptr);
+ LOGVV("--- detach-releasing monitor %p", *ptr);
}
}
@@ -1103,75 +921,19 @@
* array classes. We also want to reject attempts to create new Class
* objects, since only DefineClass should do that.
*/
-static bool canAllocClass(ClassObject* clazz)
-{
+static bool canAllocClass(ClassObject* clazz) {
if (dvmIsAbstractClass(clazz) || dvmIsInterfaceClass(clazz)) {
/* JNI spec defines what this throws */
dvmThrowInstantiationException(clazz, "abstract class or interface");
return false;
- } else if (dvmIsArrayClass(clazz) || clazz == gDvm.classJavaLangClass) {
+ } else if (dvmIsArrayClass(clazz) || dvmIsTheClassClass(clazz)) {
/* spec says "must not" for arrays, ignores Class */
dvmThrowInstantiationException(clazz, "wrong JNI function");
return false;
}
-
return true;
}
-#ifdef WITH_JNI_STACK_CHECK
-/*
- * Compute a CRC on the entire interpreted stack.
- *
- * Would be nice to compute it on "self" as well, but there are parts of
- * the Thread that can be altered by other threads (e.g. prev/next pointers).
- */
-static void computeStackSum(Thread* self)
-{
- const u1* low = (const u1*)SAVEAREA_FROM_FP(self->curFrame);
- u4 crc = dvmInitCrc32();
- self->stackCrc = 0;
- crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
- self->stackCrc = crc;
-}
-
-/*
- * Compute a CRC on the entire interpreted stack, and compare it to what
- * we previously computed.
- *
- * We can execute JNI directly from native code without calling in from
- * interpreted code during VM initialization and immediately after JNI
- * thread attachment. Another opportunity exists during JNI_OnLoad. Rather
- * than catching these cases we just ignore them here, which is marginally
- * less accurate but reduces the amount of code we have to touch with #ifdefs.
- */
-static void checkStackSum(Thread* self)
-{
- const u1* low = (const u1*)SAVEAREA_FROM_FP(self->curFrame);
- u4 stackCrc, crc;
-
- stackCrc = self->stackCrc;
- self->stackCrc = 0;
- crc = dvmInitCrc32();
- crc = dvmComputeCrc32(crc, low, self->interpStackStart - low);
- if (crc != stackCrc) {
- const Method* meth = dvmGetCurrentJNIMethod();
- if (dvmComputeExactFrameDepth(self->curFrame) == 1) {
- LOGD("JNI: bad stack CRC (0x%08x) -- okay during init\n",
- stackCrc);
- } else if (strcmp(meth->name, "nativeLoad") == 0 &&
- (strcmp(meth->clazz->descriptor, "Ljava/lang/Runtime;") == 0))
- {
- LOGD("JNI: bad stack CRC (0x%08x) -- okay during JNI_OnLoad\n",
- stackCrc);
- } else {
- LOGW("JNI: bad stack CRC (%08x vs %08x)\n", crc, stackCrc);
- dvmAbort();
- }
- }
- self->stackCrc = (u4) -1; /* make logic errors more noticeable */
-}
-#endif
-
/*
* ===========================================================================
@@ -1223,25 +985,20 @@
static inline void convertReferenceResult(JNIEnv* env, JValue* pResult,
const Method* method, Thread* self)
{
- if (method->shorty[0] == 'L' && !dvmCheckException(self) &&
- pResult->l != NULL)
- {
- pResult->l = dvmDecodeIndirectRef(env, pResult->l);
+ if (method->shorty[0] == 'L' && !dvmCheckException(self) && pResult->l != NULL) {
+ pResult->l = dvmDecodeIndirectRef(env, (jobject) pResult->l);
}
}
/*
* General form, handles all cases.
*/
-void dvmCallJNIMethod_general(const u4* args, JValue* pResult,
- const Method* method, Thread* self)
-{
- int oldStatus;
+void dvmCallJNIMethod_general(const u4* args, JValue* pResult, const Method* method, Thread* self) {
u4* modArgs = (u4*) args;
jclass staticMethodClass;
JNIEnv* env = self->jniEnv;
- //LOGI("JNI calling %p (%s.%s:%s):\n", method->insns,
+ //LOGI("JNI calling %p (%s.%s:%s):", method->insns,
// method->clazz->descriptor, method->name, method->shorty);
/*
@@ -1251,7 +1008,7 @@
int idx = 0;
if (dvmIsStaticMethod(method)) {
/* add the class object we pass in */
- staticMethodClass = addLocalReference(env, (Object*) method->clazz);
+ staticMethodClass = (jclass) addLocalReference(env, (Object*) method->clazz);
if (staticMethodClass == NULL) {
assert(dvmCheckException(self));
return;
@@ -1272,7 +1029,7 @@
while (*shorty != '\0') {
switch (*shorty++) {
case 'L':
- //LOGI(" local %d: 0x%08x\n", idx, modArgs[idx]);
+ //LOGI(" local %d: 0x%08x", idx, modArgs[idx]);
if (modArgs[idx] != 0) {
//if (!dvmIsValidObject((Object*) modArgs[idx]))
// dvmAbort();
@@ -1296,7 +1053,7 @@
idx++;
}
- oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+ ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
ANDROID_MEMBAR_FULL(); /* guarantee ordering on method->insns */
assert(method->insns != NULL);
@@ -1324,12 +1081,12 @@
assert(dvmIsSynchronizedMethod(method));
- if (dvmIsStaticMethod(method))
+ if (dvmIsStaticMethod(method)) {
lockObj = (Object*) method->clazz;
- else
+ } else {
lockObj = (Object*) args[0];
-
- LOGVV("Calling %s.%s: locking %p (%s)\n",
+ }
+ LOGVV("Calling %s.%s: locking %p (%s)",
method->clazz->descriptor, method->name,
lockObj, lockObj->clazz->descriptor);
@@ -1347,7 +1104,6 @@
const Method* method, Thread* self)
{
u4* modArgs = (u4*) args;
- int oldStatus;
jobject thisObj = addLocalReference(self->jniEnv, (Object*) args[0]);
if (thisObj == NULL) {
@@ -1356,7 +1112,7 @@
}
modArgs[0] = (u4) thisObj;
- oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+ ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
ANDROID_MEMBAR_FULL(); /* guarantee ordering on method->insns */
@@ -1379,16 +1135,13 @@
void dvmCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
const Method* method, Thread* self)
{
- jclass staticMethodClass;
- int oldStatus;
-
- staticMethodClass = addLocalReference(self->jniEnv, (Object*)method->clazz);
+ jclass staticMethodClass = (jclass) addLocalReference(self->jniEnv, (Object*)method->clazz);
if (staticMethodClass == NULL) {
assert(dvmCheckException(self));
return;
}
- oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+ ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
ANDROID_MEMBAR_FULL(); /* guarantee ordering on method->insns */
@@ -1406,12 +1159,10 @@
/*
* Extract the return type enum from the "jniArgInfo" field.
*/
-DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo)
-{
- return (jniArgInfo & DALVIK_JNI_RETURN_MASK) >> DALVIK_JNI_RETURN_SHIFT;
+DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo) {
+ return static_cast<DalvikJniReturnType>((jniArgInfo & DALVIK_JNI_RETURN_MASK) >> DALVIK_JNI_RETURN_SHIFT);
}
-
/*
* ===========================================================================
* JNI implementation
@@ -1421,15 +1172,13 @@
/*
* Return the version of the native method interface.
*/
-static jint GetVersion(JNIEnv* env)
-{
- JNI_ENTER();
+static jint GetVersion(JNIEnv* env) {
/*
* There is absolutely no need to toggle the mode for correct behavior.
* However, it does provide native code with a simple "suspend self
* if necessary" call.
*/
- JNI_EXIT();
+ ScopedJniThreadState ts(env);
return JNI_VERSION_1_6;
}
@@ -1446,9 +1195,8 @@
UNUSED_PARAMETER(buf);
UNUSED_PARAMETER(bufLen);
- JNI_ENTER();
- LOGW("JNI DefineClass is not supported\n");
- JNI_EXIT();
+ ScopedJniThreadState ts(env);
+ LOGW("JNI DefineClass is not supported");
return NULL;
}
@@ -1466,65 +1214,48 @@
* method, but it's likely they meant ClassLoader.getSystemClassLoader.
* We can't get that until after the VM has initialized though.
*/
-static jclass FindClass(JNIEnv* env, const char* name)
-{
- JNI_ENTER();
+static jclass FindClass(JNIEnv* env, const char* name) {
+ ScopedJniThreadState ts(env);
- const Method* thisMethod;
- ClassObject* clazz;
- jclass jclazz = NULL;
- Object* loader;
- Object* trackedLoader = NULL;
- char* descriptor = NULL;
-
- thisMethod = dvmGetCurrentJNIMethod();
+ const Method* thisMethod = dvmGetCurrentJNIMethod();
assert(thisMethod != NULL);
- descriptor = dvmNameToDescriptor(name);
- if (descriptor == NULL) {
- clazz = NULL;
- goto bail;
- }
-
- //Thread* self = dvmThreadSelf();
- if (_self->classLoaderOverride != NULL) {
+ Object* loader;
+ Object* trackedLoader = NULL;
+ if (ts.self()->classLoaderOverride != NULL) {
/* hack for JNI_OnLoad */
assert(strcmp(thisMethod->name, "nativeLoad") == 0);
- loader = _self->classLoaderOverride;
+ loader = ts.self()->classLoaderOverride;
} else if (thisMethod == gDvm.methDalvikSystemNativeStart_main) {
/* start point of invocation interface */
- if (!gDvm.initializing)
+ if (!gDvm.initializing) {
loader = trackedLoader = dvmGetSystemClassLoader();
- else
+ } else {
loader = NULL;
+ }
} else {
loader = thisMethod->clazz->classLoader;
}
- clazz = dvmFindClassNoInit(descriptor, loader);
- jclazz = addLocalReference(env, (Object*) clazz);
-
- dvmReleaseTrackedAlloc(trackedLoader, _self);
-
-bail:
+ char* descriptor = dvmNameToDescriptor(name);
+ if (descriptor == NULL) {
+ return NULL;
+ }
+ ClassObject* clazz = dvmFindClassNoInit(descriptor, loader);
free(descriptor);
- JNI_EXIT();
+ jclass jclazz = (jclass) addLocalReference(env, (Object*) clazz);
+ dvmReleaseTrackedAlloc(trackedLoader, ts.self());
return jclazz;
}
/*
* Return the superclass of a class.
*/
-static jclass GetSuperclass(JNIEnv* env, jclass jclazz)
-{
- JNI_ENTER();
-
+static jclass GetSuperclass(JNIEnv* env, jclass jclazz) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jclass jsuper = addLocalReference(env, (Object*)clazz->super);
-
- JNI_EXIT();
- return jsuper;
+ return (jclass) addLocalReference(env, (Object*)clazz->super);
}
/*
@@ -1532,43 +1263,29 @@
*
* Like IsInstanceOf, but with a pair of class objects instead of obj+class.
*/
-static jboolean IsAssignableFrom(JNIEnv* env, jclass jclazz1, jclass jclazz2)
-{
- JNI_ENTER();
-
+static jboolean IsAssignableFrom(JNIEnv* env, jclass jclazz1, jclass jclazz2) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz1 = (ClassObject*) dvmDecodeIndirectRef(env, jclazz1);
ClassObject* clazz2 = (ClassObject*) dvmDecodeIndirectRef(env, jclazz2);
-
- jboolean result = dvmInstanceof(clazz1, clazz2);
-
- JNI_EXIT();
- return result;
+ return dvmInstanceof(clazz1, clazz2);
}
/*
* Given a java.lang.reflect.Method or .Constructor, return a methodID.
*/
-static jmethodID FromReflectedMethod(JNIEnv* env, jobject jmethod)
-{
- JNI_ENTER();
- jmethodID methodID;
+static jmethodID FromReflectedMethod(JNIEnv* env, jobject jmethod) {
+ ScopedJniThreadState ts(env);
Object* method = dvmDecodeIndirectRef(env, jmethod);
- methodID = (jmethodID) dvmGetMethodFromReflectObj(method);
- JNI_EXIT();
- return methodID;
+ return (jmethodID) dvmGetMethodFromReflectObj(method);
}
/*
* Given a java.lang.reflect.Field, return a fieldID.
*/
-static jfieldID FromReflectedField(JNIEnv* env, jobject jfield)
-{
- JNI_ENTER();
- jfieldID fieldID;
+static jfieldID FromReflectedField(JNIEnv* env, jobject jfield) {
+ ScopedJniThreadState ts(env);
Object* field = dvmDecodeIndirectRef(env, jfield);
- fieldID = (jfieldID) dvmGetFieldFromReflectObj(field);
- JNI_EXIT();
- return fieldID;
+ return (jfieldID) dvmGetFieldFromReflectObj(field);
}
/*
@@ -1578,16 +1295,12 @@
*
* Throws OutOfMemory and returns NULL on failure.
*/
-static jobject ToReflectedMethod(JNIEnv* env, jclass jcls, jmethodID methodID,
- jboolean isStatic)
-{
- JNI_ENTER();
+static jobject ToReflectedMethod(JNIEnv* env, jclass jcls, jmethodID methodID, jboolean isStatic) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jcls);
Object* obj = dvmCreateReflectObjForMethod(clazz, (Method*) methodID);
dvmReleaseTrackedAlloc(obj, NULL);
- jobject jobj = addLocalReference(env, obj);
- JNI_EXIT();
- return jobj;
+ return addLocalReference(env, obj);
}
/*
@@ -1597,52 +1310,36 @@
*
* Throws OutOfMemory and returns NULL on failure.
*/
-static jobject ToReflectedField(JNIEnv* env, jclass jcls, jfieldID fieldID,
- jboolean isStatic)
-{
- JNI_ENTER();
+static jobject ToReflectedField(JNIEnv* env, jclass jcls, jfieldID fieldID, jboolean isStatic) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jcls);
Object* obj = dvmCreateReflectObjForField(clazz, (Field*) fieldID);
dvmReleaseTrackedAlloc(obj, NULL);
- jobject jobj = addLocalReference(env, obj);
- JNI_EXIT();
- return jobj;
+ return addLocalReference(env, obj);
}
/*
* Take this exception and throw it.
*/
-static jint Throw(JNIEnv* env, jthrowable jobj)
-{
- JNI_ENTER();
-
- jint retval;
-
+static jint Throw(JNIEnv* env, jthrowable jobj) {
+ ScopedJniThreadState ts(env);
if (jobj != NULL) {
Object* obj = dvmDecodeIndirectRef(env, jobj);
- dvmSetException(_self, obj);
- retval = JNI_OK;
- } else {
- retval = JNI_ERR;
+ dvmSetException(ts.self(), obj);
+ return JNI_OK;
}
-
- JNI_EXIT();
- return retval;
+ return JNI_ERR;
}
/*
* Constructs an exception object from the specified class with the message
* specified by "message", and throws it.
*/
-static jint ThrowNew(JNIEnv* env, jclass jclazz, const char* message)
-{
- JNI_ENTER();
-
+static jint ThrowNew(JNIEnv* env, jclass jclazz, const char* message) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
dvmThrowException(clazz, message);
// TODO: should return failure if this didn't work (e.g. OOM)
-
- JNI_EXIT();
return JNI_OK;
}
@@ -1654,15 +1351,10 @@
* enter/exit checks. If we find one, we need to enter and then re-fetch
* the exception (in case it got moved by a compacting GC).
*/
-static jthrowable ExceptionOccurred(JNIEnv* env)
-{
- JNI_ENTER();
-
- Object* exception;
- jobject localException;
-
- exception = dvmGetException(_self);
- localException = addLocalReference(env, exception);
+static jthrowable ExceptionOccurred(JNIEnv* env) {
+ ScopedJniThreadState ts(env);
+ Object* exception = dvmGetException(ts.self());
+ jthrowable localException = (jthrowable) addLocalReference(env, exception);
if (localException == NULL && exception != NULL) {
/*
* We were unable to add a new local reference, and threw a new
@@ -1671,28 +1363,22 @@
* there was no exception, even though it's pretty much raining
* exceptions in here.
*/
- LOGW("JNI WARNING: addLocal/exception combo\n");
+ LOGW("JNI WARNING: addLocal/exception combo");
}
-
- JNI_EXIT();
return localException;
}
/*
* Print an exception and stack trace to stderr.
*/
-static void ExceptionDescribe(JNIEnv* env)
-{
- JNI_ENTER();
-
- Object* exception = dvmGetException(_self);
+static void ExceptionDescribe(JNIEnv* env) {
+ ScopedJniThreadState ts(env);
+ Object* exception = dvmGetException(ts.self());
if (exception != NULL) {
dvmPrintExceptionStackTrace();
} else {
- LOGI("Odd: ExceptionDescribe called, but no exception pending\n");
+ LOGI("Odd: ExceptionDescribe called, but no exception pending");
}
-
- JNI_EXIT();
}
/*
@@ -1700,20 +1386,17 @@
*
* TODO: we should be able to skip the enter/exit stuff.
*/
-static void ExceptionClear(JNIEnv* env)
-{
- JNI_ENTER();
- dvmClearException(_self);
- JNI_EXIT();
+static void ExceptionClear(JNIEnv* env) {
+ ScopedJniThreadState ts(env);
+ dvmClearException(ts.self());
}
/*
* Kill the VM. This function does not return.
*/
-static void FatalError(JNIEnv* env, const char* msg)
-{
+static void FatalError(JNIEnv* env, const char* msg) {
//dvmChangeStatus(NULL, THREAD_RUNNING);
- LOGE("JNI posting fatal error: %s\n", msg);
+ LOGE("JNI posting fatal error: %s", msg);
dvmAbort();
}
@@ -1723,219 +1406,168 @@
* The new frame must have the same method pointer. (If for no other
* reason than FindClass needs it to get the appropriate class loader.)
*/
-static jint PushLocalFrame(JNIEnv* env, jint capacity)
-{
- JNI_ENTER();
- int result = JNI_OK;
+static jint PushLocalFrame(JNIEnv* env, jint capacity) {
+ ScopedJniThreadState ts(env);
if (!ensureLocalCapacity(env, capacity) ||
- !dvmPushLocalFrame(_self /*dvmThreadSelf()*/, dvmGetCurrentJNIMethod()))
+ !dvmPushLocalFrame(ts.self(), dvmGetCurrentJNIMethod()))
{
/* yes, OutOfMemoryError, not StackOverflowError */
- dvmClearException(_self);
+ dvmClearException(ts.self());
dvmThrowOutOfMemoryError("out of stack in JNI PushLocalFrame");
- result = JNI_ERR;
+ return JNI_ERR;
}
- JNI_EXIT();
- return result;
+ return JNI_OK;
}
/*
* Pop the local frame off. If "jresult" is not null, add it as a
* local reference on the now-current frame.
*/
-static jobject PopLocalFrame(JNIEnv* env, jobject jresult)
-{
- JNI_ENTER();
+static jobject PopLocalFrame(JNIEnv* env, jobject jresult) {
+ ScopedJniThreadState ts(env);
Object* result = dvmDecodeIndirectRef(env, jresult);
- if (!dvmPopLocalFrame(_self /*dvmThreadSelf()*/)) {
- LOGW("JNI WARNING: too many PopLocalFrame calls\n");
- dvmClearException(_self);
+ if (!dvmPopLocalFrame(ts.self())) {
+ LOGW("JNI WARNING: too many PopLocalFrame calls");
+ dvmClearException(ts.self());
dvmThrowRuntimeException("too many PopLocalFrame calls");
}
- jresult = addLocalReference(env, result);
- JNI_EXIT();
- return jresult;
+ return addLocalReference(env, result);
}
/*
* Add a reference to the global list.
*/
-static jobject NewGlobalRef(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jobject NewGlobalRef(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- jobject retval = addGlobalReference(obj);
- JNI_EXIT();
- return retval;
+ return addGlobalReference(obj);
}
/*
* Delete a reference from the global list.
*/
-static void DeleteGlobalRef(JNIEnv* env, jobject jglobalRef)
-{
- JNI_ENTER();
+static void DeleteGlobalRef(JNIEnv* env, jobject jglobalRef) {
+ ScopedJniThreadState ts(env);
deleteGlobalReference(jglobalRef);
- JNI_EXIT();
}
/*
* Add a reference to the local list.
*/
-static jobject NewLocalRef(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jobject NewLocalRef(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- jobject retval = addLocalReference(env, obj);
- JNI_EXIT();
- return retval;
+ return addLocalReference(env, obj);
}
/*
* Delete a reference from the local list.
*/
-static void DeleteLocalRef(JNIEnv* env, jobject jlocalRef)
-{
- JNI_ENTER();
+static void DeleteLocalRef(JNIEnv* env, jobject jlocalRef) {
+ ScopedJniThreadState ts(env);
deleteLocalReference(env, jlocalRef);
- JNI_EXIT();
}
/*
* Ensure that the local references table can hold at least this many
* references.
*/
-static jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
-{
- JNI_ENTER();
+static jint EnsureLocalCapacity(JNIEnv* env, jint capacity) {
+ ScopedJniThreadState ts(env);
bool okay = ensureLocalCapacity(env, capacity);
if (!okay) {
dvmThrowOutOfMemoryError("can't ensure local reference capacity");
}
- JNI_EXIT();
- if (okay)
- return 0;
- else
- return -1;
+ return okay ? 0 : -1;
}
/*
* Determine whether two Object references refer to the same underlying object.
*/
-static jboolean IsSameObject(JNIEnv* env, jobject jref1, jobject jref2)
-{
- JNI_ENTER();
+static jboolean IsSameObject(JNIEnv* env, jobject jref1, jobject jref2) {
+ ScopedJniThreadState ts(env);
Object* obj1 = dvmDecodeIndirectRef(env, jref1);
Object* obj2 = dvmDecodeIndirectRef(env, jref2);
- jboolean result = (obj1 == obj2);
- JNI_EXIT();
- return result;
+ return (obj1 == obj2);
}
/*
* Allocate a new object without invoking any constructors.
*/
-static jobject AllocObject(JNIEnv* env, jclass jclazz)
-{
- JNI_ENTER();
+static jobject AllocObject(JNIEnv* env, jclass jclazz) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jobject result;
-
if (!canAllocClass(clazz) ||
(!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)))
{
- assert(dvmCheckException(_self));
- result = NULL;
- } else {
- Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
- result = addLocalReference(env, newObj);
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- JNI_EXIT();
- return result;
+ Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+ return addLocalReference(env, newObj);
}
/*
* Allocate a new object and invoke the supplied constructor.
*/
-static jobject NewObject(JNIEnv* env, jclass jclazz, jmethodID methodID, ...)
-{
- JNI_ENTER();
+static jobject NewObject(JNIEnv* env, jclass jclazz, jmethodID methodID, ...) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jobject result;
- if (!canAllocClass(clazz) ||
- (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)))
- {
- assert(dvmCheckException(_self));
- result = NULL;
- } else {
- Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
- result = addLocalReference(env, newObj);
- if (newObj != NULL) {
- JValue unused;
- va_list args;
- va_start(args, methodID);
- dvmCallMethodV(_self, (Method*) methodID, newObj, true, &unused,
- args);
- va_end(args);
- }
+ if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- JNI_EXIT();
+ Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+ jobject result = addLocalReference(env, newObj);
+ if (newObj != NULL) {
+ JValue unused;
+ va_list args;
+ va_start(args, methodID);
+ dvmCallMethodV(ts.self(), (Method*) methodID, newObj, true, &unused, args);
+ va_end(args);
+ }
return result;
}
-static jobject NewObjectV(JNIEnv* env, jclass jclazz, jmethodID methodID,
- va_list args)
-{
- JNI_ENTER();
- ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jobject result;
- if (!canAllocClass(clazz) ||
- (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)))
- {
- assert(dvmCheckException(_self));
- result = NULL;
- } else {
- Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
- result = addLocalReference(env, newObj);
- if (newObj != NULL) {
- JValue unused;
- dvmCallMethodV(_self, (Method*) methodID, newObj, true, &unused,
- args);
- }
+static jobject NewObjectV(JNIEnv* env, jclass jclazz, jmethodID methodID, va_list args) {
+ ScopedJniThreadState ts(env);
+ ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+
+ if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- JNI_EXIT();
+ Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+ jobject result = addLocalReference(env, newObj);
+ if (newObj != NULL) {
+ JValue unused;
+ dvmCallMethodV(ts.self(), (Method*) methodID, newObj, true, &unused, args);
+ }
return result;
}
-static jobject NewObjectA(JNIEnv* env, jclass jclazz, jmethodID methodID,
- jvalue* args)
-{
- JNI_ENTER();
- ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jobject result;
- if (!canAllocClass(clazz) ||
- (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)))
- {
- assert(dvmCheckException(_self));
- result = NULL;
- } else {
- Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
- result = addLocalReference(env, newObj);
- if (newObj != NULL) {
- JValue unused;
- dvmCallMethodA(_self, (Method*) methodID, newObj, true, &unused,
- args);
- }
+static jobject NewObjectA(JNIEnv* env, jclass jclazz, jmethodID methodID, jvalue* args) {
+ ScopedJniThreadState ts(env);
+ ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+
+ if (!canAllocClass(clazz) || (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))) {
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- JNI_EXIT();
+ Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+ jobject result = addLocalReference(env, newObj);
+ if (newObj != NULL) {
+ JValue unused;
+ dvmCallMethodA(ts.self(), (Method*) methodID, newObj, true, &unused, args);
+ }
return result;
}
@@ -1944,40 +1576,29 @@
*
* JNI spec says: obj must not be NULL.
*/
-static jclass GetObjectClass(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jclass GetObjectClass(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
assert(jobj != NULL);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- jclass jclazz = addLocalReference(env, (Object*) obj->clazz);
-
- JNI_EXIT();
- return jclazz;
+ return (jclass) addLocalReference(env, (Object*) obj->clazz);
}
/*
* Determine whether "obj" is an instance of "clazz".
*/
-static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass jclazz)
-{
- JNI_ENTER();
+static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass jclazz) {
+ ScopedJniThreadState ts(env);
assert(jclazz != NULL);
-
- jboolean result;
-
if (jobj == NULL) {
- result = true;
- } else {
- Object* obj = dvmDecodeIndirectRef(env, jobj);
- ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- result = dvmInstanceof(obj->clazz, clazz);
+ return true;
}
- JNI_EXIT();
- return result;
+ Object* obj = dvmDecodeIndirectRef(env, jobj);
+ ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+ return dvmInstanceof(obj->clazz, clazz);
}
/*
@@ -1994,16 +1615,12 @@
* Dalvik also puts all private methods into the "direct" list, so we
* really need to just search both lists.
*/
-static jmethodID GetMethodID(JNIEnv* env, jclass jclazz, const char* name,
- const char* sig)
-{
- JNI_ENTER();
+static jmethodID GetMethodID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jmethodID id = NULL;
-
if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
- assert(dvmCheckException(_self));
+ assert(dvmCheckException(ts.self()));
} else if (dvmIsInterfaceClass(clazz)) {
Method* meth = dvmFindInterfaceMethodHierByDescriptor(clazz, name, sig);
if (meth == NULL) {
@@ -2011,133 +1628,111 @@
"no method with name='%s' signature='%s' in interface %s",
name, sig, clazz->descriptor);
}
- id = (jmethodID) meth;
- } else {
- Method* meth = dvmFindVirtualMethodHierByDescriptor(clazz, name, sig);
- if (meth == NULL) {
- /* search private methods and constructors; non-hierarchical */
- meth = dvmFindDirectMethodByDescriptor(clazz, name, sig);
- }
- if (meth != NULL && dvmIsStaticMethod(meth)) {
- IF_LOGD() {
- char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGD("GetMethodID: not returning static method %s.%s %s\n",
+ return (jmethodID) meth;
+ }
+ Method* meth = dvmFindVirtualMethodHierByDescriptor(clazz, name, sig);
+ if (meth == NULL) {
+ /* search private methods and constructors; non-hierarchical */
+ meth = dvmFindDirectMethodByDescriptor(clazz, name, sig);
+ }
+ if (meth != NULL && dvmIsStaticMethod(meth)) {
+ IF_LOGD() {
+ char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
+ LOGD("GetMethodID: not returning static method %s.%s %s",
clazz->descriptor, meth->name, desc);
- free(desc);
- }
- meth = NULL;
+ free(desc);
}
- if (meth == NULL) {
- dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
+ meth = NULL;
+ }
+ if (meth == NULL) {
+ dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
"no method with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
- } else {
- /*
- * The method's class may not be the same as clazz, but if
- * it isn't this must be a virtual method and the class must
- * be a superclass (and, hence, already initialized).
- */
- assert(dvmIsClassInitialized(meth->clazz) ||
- dvmIsClassInitializing(meth->clazz));
- }
- id = (jmethodID) meth;
+ } else {
+ /*
+ * The method's class may not be the same as clazz, but if
+ * it isn't this must be a virtual method and the class must
+ * be a superclass (and, hence, already initialized).
+ */
+ assert(dvmIsClassInitialized(meth->clazz) || dvmIsClassInitializing(meth->clazz));
}
- JNI_EXIT();
- return id;
+ return (jmethodID) meth;
}
/*
* Get a field ID (instance fields).
*/
-static jfieldID GetFieldID(JNIEnv* env, jclass jclazz, const char* name,
- const char* sig)
-{
- JNI_ENTER();
+static jfieldID GetFieldID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jfieldID id;
if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
- assert(dvmCheckException(_self));
- id = NULL;
- } else {
- id = (jfieldID) dvmFindInstanceFieldHier(clazz, name, sig);
- if (id == NULL) {
- dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
+ assert(dvmCheckException(ts.self()));
+ return NULL;
+ }
+
+ jfieldID id = (jfieldID) dvmFindInstanceFieldHier(clazz, name, sig);
+ if (id == NULL) {
+ dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
"no field with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
- }
}
- JNI_EXIT();
return id;
}
/*
* Get the method ID for a static method in a class.
*/
-static jmethodID GetStaticMethodID(JNIEnv* env, jclass jclazz,
- const char* name, const char* sig)
-{
- JNI_ENTER();
+static jmethodID GetStaticMethodID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jmethodID id;
-
if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
- assert(dvmCheckException(_self));
- id = NULL;
- } else {
- Method* meth;
-
- meth = dvmFindDirectMethodHierByDescriptor(clazz, name, sig);
-
- /* make sure it's static, not virtual+private */
- if (meth != NULL && !dvmIsStaticMethod(meth)) {
- IF_LOGD() {
- char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGD("GetStaticMethodID: "
- "not returning nonstatic method %s.%s %s\n",
- clazz->descriptor, meth->name, desc);
- free(desc);
- }
- meth = NULL;
- }
-
- id = (jmethodID) meth;
- if (id == NULL) {
- dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
- "no static method with name='%s' signature='%s' in class %s",
- name, sig, clazz->descriptor);
- }
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- JNI_EXIT();
+ Method* meth = dvmFindDirectMethodHierByDescriptor(clazz, name, sig);
+
+ /* make sure it's static, not virtual+private */
+ if (meth != NULL && !dvmIsStaticMethod(meth)) {
+ IF_LOGD() {
+ char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
+ LOGD("GetStaticMethodID: not returning nonstatic method %s.%s %s",
+ clazz->descriptor, meth->name, desc);
+ free(desc);
+ }
+ meth = NULL;
+ }
+
+ jmethodID id = (jmethodID) meth;
+ if (id == NULL) {
+ dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
+ "no static method with name='%s' signature='%s' in class %s",
+ name, sig, clazz->descriptor);
+ }
return id;
}
/*
* Get a field ID (static fields).
*/
-static jfieldID GetStaticFieldID(JNIEnv* env, jclass jclazz,
- const char* name, const char* sig)
-{
- JNI_ENTER();
+static jfieldID GetStaticFieldID(JNIEnv* env, jclass jclazz, const char* name, const char* sig) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jfieldID id;
-
if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
- assert(dvmCheckException(_self));
- id = NULL;
- } else {
- id = (jfieldID) dvmFindStaticField(clazz, name, sig);
- if (id == NULL) {
- dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
+ assert(dvmCheckException(ts.self()));
+ return NULL;
+ }
+
+ jfieldID id = (jfieldID) dvmFindStaticFieldHier(clazz, name, sig);
+ if (id == NULL) {
+ dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
"no static field with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
- }
}
- JNI_EXIT();
return id;
}
@@ -2151,7 +1746,7 @@
jfieldID fieldID) \
{ \
UNUSED_PARAMETER(jclazz); \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
StaticField* sfield = (StaticField*) fieldID; \
_ctype value; \
if (dvmIsVolatileField(&sfield->field)) { \
@@ -2159,17 +1754,16 @@
Object* obj = dvmGetStaticFieldObjectVolatile(sfield); \
value = (_ctype)(u4)addLocalReference(env, obj); \
} else { \
- value = dvmGetStaticField##_jname##Volatile(sfield); \
+ value = (_ctype) dvmGetStaticField##_jname##Volatile(sfield);\
} \
} else { \
if (_isref) { \
Object* obj = dvmGetStaticFieldObject(sfield); \
value = (_ctype)(u4)addLocalReference(env, obj); \
} else { \
- value = dvmGetStaticField##_jname(sfield); \
+ value = (_ctype) dvmGetStaticField##_jname(sfield); \
} \
} \
- JNI_EXIT(); \
return value; \
}
GET_STATIC_TYPE_FIELD(jobject, Object, true);
@@ -2190,7 +1784,7 @@
jfieldID fieldID, _ctype value) \
{ \
UNUSED_PARAMETER(jclazz); \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
StaticField* sfield = (StaticField*) fieldID; \
if (dvmIsVolatileField(&sfield->field)) { \
if (_isref) { /* only when _ctype==jobject */ \
@@ -2209,7 +1803,6 @@
dvmSetStaticField##_jname(sfield, (_ctype2)value); \
} \
} \
- JNI_EXIT(); \
}
SET_STATIC_TYPE_FIELD(jobject, Object*, Object, true);
SET_STATIC_TYPE_FIELD(jboolean, bool, Boolean, false);
@@ -2230,7 +1823,7 @@
static _ctype Get##_jname##Field(JNIEnv* env, jobject jobj, \
jfieldID fieldID) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
InstField* field = (InstField*) fieldID; \
_ctype value; \
@@ -2240,7 +1833,7 @@
dvmGetFieldObjectVolatile(obj, field->byteOffset); \
value = (_ctype)(u4)addLocalReference(env, valObj); \
} else { \
- value = \
+ value = (_ctype) \
dvmGetField##_jname##Volatile(obj, field->byteOffset); \
} \
} else { \
@@ -2248,10 +1841,9 @@
Object* valObj = dvmGetFieldObject(obj, field->byteOffset); \
value = (_ctype)(u4)addLocalReference(env, valObj); \
} else { \
- value = dvmGetField##_jname(obj, field->byteOffset); \
+ value = (_ctype) dvmGetField##_jname(obj, field->byteOffset);\
} \
} \
- JNI_EXIT(); \
return value; \
}
GET_TYPE_FIELD(jobject, Object, true);
@@ -2271,7 +1863,7 @@
static void Set##_jname##Field(JNIEnv* env, jobject jobj, \
jfieldID fieldID, _ctype value) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
InstField* field = (InstField*) fieldID; \
if (dvmIsVolatileField(&field->field)) { \
@@ -2293,7 +1885,6 @@
field->byteOffset, (_ctype2)value); \
} \
} \
- JNI_EXIT(); \
}
SET_TYPE_FIELD(jobject, Object*, Object, true);
SET_TYPE_FIELD(jboolean, bool, Boolean, false);
@@ -2315,61 +1906,55 @@
static _ctype Call##_jname##Method(JNIEnv* env, jobject jobj, \
jmethodID methodID, ...) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
const Method* meth; \
va_list args; \
JValue result; \
meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
va_start(args, methodID); \
- dvmCallMethodV(_self, meth, obj, true, &result, args); \
+ dvmCallMethodV(ts.self(), meth, obj, true, &result, args); \
va_end(args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
} \
static _ctype Call##_jname##MethodV(JNIEnv* env, jobject jobj, \
jmethodID methodID, va_list args) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
const Method* meth; \
JValue result; \
meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
- dvmCallMethodV(_self, meth, obj, true, &result, args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodV(ts.self(), meth, obj, true, &result, args); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
} \
static _ctype Call##_jname##MethodA(JNIEnv* env, jobject jobj, \
jmethodID methodID, jvalue* args) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
const Method* meth; \
JValue result; \
meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
- dvmCallMethodA(_self, meth, obj, true, &result, args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodA(ts.self(), meth, obj, true, &result, args); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
}
-CALL_VIRTUAL(jobject, Object, NULL, result.l, true);
+CALL_VIRTUAL(jobject, Object, NULL, (jobject) result.l, true);
CALL_VIRTUAL(jboolean, Boolean, 0, result.z, false);
CALL_VIRTUAL(jbyte, Byte, 0, result.b, false);
CALL_VIRTUAL(jchar, Char, 0, result.c, false);
@@ -2391,7 +1976,7 @@
static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, jobject jobj, \
jclass jclazz, jmethodID methodID, ...) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
ClassObject* clazz = \
(ClassObject*) dvmDecodeIndirectRef(env, jclazz); \
@@ -2400,21 +1985,19 @@
JValue result; \
meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
va_start(args, methodID); \
- dvmCallMethodV(_self, meth, obj, true, &result, args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
+ dvmCallMethodV(ts.self(), meth, obj, true, &result, args); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
va_end(args); \
- JNI_EXIT(); \
return _retok; \
} \
static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, jobject jobj,\
jclass jclazz, jmethodID methodID, va_list args) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
ClassObject* clazz = \
(ClassObject*) dvmDecodeIndirectRef(env, jclazz); \
@@ -2422,19 +2005,17 @@
JValue result; \
meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
- dvmCallMethodV(_self, meth, obj, true, &result, args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodV(ts.self(), meth, obj, true, &result, args); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
} \
static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, jobject jobj,\
jclass jclazz, jmethodID methodID, jvalue* args) \
{ \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
Object* obj = dvmDecodeIndirectRef(env, jobj); \
ClassObject* clazz = \
(ClassObject*) dvmDecodeIndirectRef(env, jclazz); \
@@ -2442,16 +2023,14 @@
JValue result; \
meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID); \
if (meth == NULL) { \
- JNI_EXIT(); \
return _retfail; \
} \
- dvmCallMethodA(_self, meth, obj, true, &result, args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodA(ts.self(), meth, obj, true, &result, args); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
}
-CALL_NONVIRTUAL(jobject, Object, NULL, result.l, true);
+CALL_NONVIRTUAL(jobject, Object, NULL, (jobject) result.l, true);
CALL_NONVIRTUAL(jboolean, Boolean, 0, result.z, false);
CALL_NONVIRTUAL(jbyte, Byte, 0, result.b, false);
CALL_NONVIRTUAL(jchar, Char, 0, result.c, false);
@@ -2471,42 +2050,39 @@
jmethodID methodID, ...) \
{ \
UNUSED_PARAMETER(jclazz); \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
JValue result; \
va_list args; \
va_start(args, methodID); \
- dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\
+ dvmCallMethodV(ts.self(), (Method*)methodID, NULL, true, &result, args);\
va_end(args); \
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
} \
static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass jclazz, \
jmethodID methodID, va_list args) \
{ \
UNUSED_PARAMETER(jclazz); \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
JValue result; \
- dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodV(ts.self(), (Method*)methodID, NULL, true, &result, args);\
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
} \
static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass jclazz, \
jmethodID methodID, jvalue* args) \
{ \
UNUSED_PARAMETER(jclazz); \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
JValue result; \
- dvmCallMethodA(_self, (Method*)methodID, NULL, true, &result, args);\
- if (_isref && !dvmCheckException(_self)) \
- result.l = addLocalReference(env, (Object*)result.l); \
- JNI_EXIT(); \
+ dvmCallMethodA(ts.self(), (Method*)methodID, NULL, true, &result, args);\
+ if (_isref && !dvmCheckException(ts.self())) \
+ result.l = (Object*)addLocalReference(env, result.l); \
return _retok; \
}
-CALL_STATIC(jobject, Object, NULL, result.l, true);
+CALL_STATIC(jobject, Object, NULL, (jobject) result.l, true);
CALL_STATIC(jboolean, Boolean, 0, result.z, false);
CALL_STATIC(jbyte, Byte, 0, result.b, false);
CALL_STATIC(jchar, Char, 0, result.c, false);
@@ -2523,35 +2099,23 @@
* If "len" is zero, we will return an empty string even if "unicodeChars"
* is NULL. (The JNI spec is vague here.)
*/
-static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len)
-{
- JNI_ENTER();
- jobject retval;
-
+static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
+ ScopedJniThreadState ts(env);
StringObject* jstr = dvmCreateStringFromUnicode(unicodeChars, len);
if (jstr == NULL) {
- retval = NULL;
- } else {
- dvmReleaseTrackedAlloc((Object*) jstr, NULL);
- retval = addLocalReference(env, (Object*) jstr);
+ return NULL;
}
-
- JNI_EXIT();
- return retval;
+ dvmReleaseTrackedAlloc((Object*) jstr, NULL);
+ return (jstring) addLocalReference(env, (Object*) jstr);
}
/*
* Return the length of a String in Unicode character units.
*/
-static jsize GetStringLength(JNIEnv* env, jstring jstr)
-{
- JNI_ENTER();
-
+static jsize GetStringLength(JNIEnv* env, jstring jstr) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
- jsize len = dvmStringLen(strObj);
-
- JNI_EXIT();
- return len;
+ return dvmStringLen(strObj);
}
@@ -2561,9 +2125,8 @@
* The result is guaranteed to be valid until ReleaseStringChars is
* called, which means we have to pin it or return a copy.
*/
-static const jchar* GetStringChars(JNIEnv* env, jstring jstr, jboolean* isCopy)
-{
- JNI_ENTER();
+static const jchar* GetStringChars(JNIEnv* env, jstring jstr, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
ArrayObject* strChars = dvmStringCharArray(strObj);
@@ -2571,23 +2134,20 @@
pinPrimitiveArray(strChars);
const u2* data = dvmStringChars(strObj);
- if (isCopy != NULL)
+ if (isCopy != NULL) {
*isCopy = JNI_FALSE;
-
- JNI_EXIT();
- return (jchar*)data;
+ }
+ return (jchar*) data;
}
/*
* Release our grip on some characters from a string.
*/
-static void ReleaseStringChars(JNIEnv* env, jstring jstr, const jchar* chars)
-{
- JNI_ENTER();
+static void ReleaseStringChars(JNIEnv* env, jstring jstr, const jchar* chars) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
ArrayObject* strChars = dvmStringCharArray(strObj);
unpinPrimitiveArray(strChars);
- JNI_EXIT();
}
/*
@@ -2596,37 +2156,25 @@
* The spec doesn't say how to handle a NULL string. Popular desktop VMs
* accept it and return a NULL pointer in response.
*/
-static jstring NewStringUTF(JNIEnv* env, const char* bytes)
-{
- JNI_ENTER();
-
- jstring result;
-
+static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
+ ScopedJniThreadState ts(env);
if (bytes == NULL) {
- result = NULL;
- } else {
- /* note newStr could come back NULL on OOM */
- StringObject* newStr = dvmCreateStringFromCstr(bytes);
- result = addLocalReference(env, (Object*) newStr);
- dvmReleaseTrackedAlloc((Object*)newStr, NULL);
+ return NULL;
}
-
- JNI_EXIT();
+ /* note newStr could come back NULL on OOM */
+ StringObject* newStr = dvmCreateStringFromCstr(bytes);
+ jstring result = (jstring) addLocalReference(env, (Object*) newStr);
+ dvmReleaseTrackedAlloc((Object*)newStr, NULL);
return result;
}
/*
* Return the length in bytes of the modified UTF-8 form of the string.
*/
-static jsize GetStringUTFLength(JNIEnv* env, jstring jstr)
-{
- JNI_ENTER();
-
+static jsize GetStringUTFLength(JNIEnv* env, jstring jstr) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
- jsize len = dvmStringUtf8ByteLen(strObj);
-
- JNI_EXIT();
- return len;
+ return dvmStringUtf8ByteLen(strObj);
}
/*
@@ -2643,53 +2191,39 @@
* which should catch this sort of thing during development.) Certain other
* VMs will crash with a segmentation fault.
*/
-static const char* GetStringUTFChars(JNIEnv* env, jstring jstr,
- jboolean* isCopy)
-{
- JNI_ENTER();
- char* newStr;
-
+static const char* GetStringUTFChars(JNIEnv* env, jstring jstr, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
if (jstr == NULL) {
/* this shouldn't happen; throw NPE? */
- newStr = NULL;
- } else {
- if (isCopy != NULL)
- *isCopy = JNI_TRUE;
-
- StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
- newStr = dvmCreateCstrFromString(strObj);
- if (newStr == NULL) {
- /* assume memory failure */
- dvmThrowOutOfMemoryError("native heap string alloc failed");
- }
+ return NULL;
}
-
- JNI_EXIT();
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+ char* newStr = dvmCreateCstrFromString(strObj);
+ if (newStr == NULL) {
+ /* assume memory failure */
+ dvmThrowOutOfMemoryError("native heap string alloc failed");
+ }
return newStr;
}
/*
* Release a string created by GetStringUTFChars().
*/
-static void ReleaseStringUTFChars(JNIEnv* env, jstring jstr, const char* utf)
-{
- JNI_ENTER();
- free((char*)utf);
- JNI_EXIT();
+static void ReleaseStringUTFChars(JNIEnv* env, jstring jstr, const char* utf) {
+ ScopedJniThreadState ts(env);
+ free((char*) utf);
}
/*
* Return the capacity of the array.
*/
-static jsize GetArrayLength(JNIEnv* env, jarray jarr)
-{
- JNI_ENTER();
-
+static jsize GetArrayLength(JNIEnv* env, jarray jarr) {
+ ScopedJniThreadState ts(env);
ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
- jsize length = arrObj->length;
-
- JNI_EXIT();
- return length;
+ return arrObj->length;
}
/*
@@ -2698,40 +2232,34 @@
static jobjectArray NewObjectArray(JNIEnv* env, jsize length,
jclass jelementClass, jobject jinitialElement)
{
- JNI_ENTER();
-
- jobjectArray newArray = NULL;
+ ScopedJniThreadState ts(env);
if (jelementClass == NULL) {
dvmThrowNullPointerException("JNI NewObjectArray element class");
- goto bail;
+ return NULL;
}
- ClassObject* elemClassObj =
- (ClassObject*) dvmDecodeIndirectRef(env, jelementClass);
- ArrayObject* newObj =
- dvmAllocObjectArray(elemClassObj, length, ALLOC_DEFAULT);
+ ClassObject* elemClassObj = (ClassObject*) dvmDecodeIndirectRef(env, jelementClass);
+ ClassObject* arrayClass = dvmFindArrayClassForElement(elemClassObj);
+ ArrayObject* newObj = dvmAllocArrayByClass(arrayClass, length, ALLOC_DEFAULT);
if (newObj == NULL) {
- assert(dvmCheckException(_self));
- goto bail;
+ assert(dvmCheckException(ts.self()));
+ return NULL;
}
- newArray = addLocalReference(env, (Object*) newObj);
+ jobjectArray newArray = (jobjectArray) addLocalReference(env, (Object*) newObj);
dvmReleaseTrackedAlloc((Object*) newObj, NULL);
/*
- * Initialize the array. Trashes "length".
+ * Initialize the array.
*/
if (jinitialElement != NULL) {
Object* initialElement = dvmDecodeIndirectRef(env, jinitialElement);
- Object** arrayData = (Object**) newObj->contents;
-
- while (length--)
- *arrayData++ = initialElement;
+ Object** arrayData = (Object**) (void*) newObj->contents;
+ for (jsize i = 0; i < length; ++i) {
+ arrayData[i] = initialElement;
+ }
}
-
-bail:
- JNI_EXIT();
return newArray;
}
@@ -2749,64 +2277,48 @@
*
* Add the object to the local references table in case the array goes away.
*/
-static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray jarr,
- jsize index)
-{
- JNI_ENTER();
+static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray jarr, jsize index) {
+ ScopedJniThreadState ts(env);
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
- jobject retval = NULL;
if (!checkArrayElementBounds(arrayObj, index)) {
- goto bail;
+ return NULL;
}
- Object* value = ((Object**) arrayObj->contents)[index];
- retval = addLocalReference(env, value);
-
-bail:
- JNI_EXIT();
- return retval;
+ Object* value = ((Object**) (void*) arrayObj->contents)[index];
+ return addLocalReference(env, value);
}
/*
* Set one element of an Object array.
*/
-static void SetObjectArrayElement(JNIEnv* env, jobjectArray jarr,
- jsize index, jobject jobj)
-{
- JNI_ENTER();
+static void SetObjectArrayElement(JNIEnv* env, jobjectArray jarr, jsize index, jobject jobj) {
+ ScopedJniThreadState ts(env);
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
if (!checkArrayElementBounds(arrayObj, index)) {
- goto bail;
+ return;
}
- //LOGV("JNI: set element %d in array %p to %p\n", index, array, value);
+ //LOGV("JNI: set element %d in array %p to %p", index, array, value);
Object* obj = dvmDecodeIndirectRef(env, jobj);
dvmSetObjectArrayElement(arrayObj, index, obj);
-
-bail:
- JNI_EXIT();
}
/*
* Create a new array of primitive elements.
*/
-#define NEW_PRIMITIVE_ARRAY(_artype, _jname, _typechar) \
- static _artype New##_jname##Array(JNIEnv* env, jsize length) \
- { \
- JNI_ENTER(); \
- ArrayObject* arrayObj; \
- arrayObj = dvmAllocPrimitiveArray(_typechar, length, \
- ALLOC_DEFAULT); \
- jarray jarr = NULL; \
- if (arrayObj != NULL) { \
- jarr = addLocalReference(env, (Object*) arrayObj); \
- dvmReleaseTrackedAlloc((Object*) arrayObj, NULL); \
- } \
- JNI_EXIT(); \
- return (_artype)jarr; \
+#define NEW_PRIMITIVE_ARRAY(_artype, _jname, _typechar) \
+ static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
+ ScopedJniThreadState ts(env); \
+ ArrayObject* arrayObj = dvmAllocPrimitiveArray(_typechar, length, ALLOC_DEFAULT); \
+ if (arrayObj == NULL) { \
+ return NULL; \
+ } \
+ _artype result = (_artype) addLocalReference(env, (Object*) arrayObj); \
+ dvmReleaseTrackedAlloc((Object*) arrayObj, NULL); \
+ return result; \
}
NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean, 'Z');
NEW_PRIMITIVE_ARRAY(jbyteArray, Byte, 'B');
@@ -2826,20 +2338,18 @@
* buffer as the destination of e.g. a blocking read() call that wakes up
* during a GC.
*/
-#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
- static _ctype* Get##_jname##ArrayElements(JNIEnv* env, \
- _ctype##Array jarr, jboolean* isCopy) \
- { \
- JNI_ENTER(); \
- _ctype* data; \
- ArrayObject* arrayObj = \
- (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
- pinPrimitiveArray(arrayObj); \
- data = (_ctype*) arrayObj->contents; \
- if (isCopy != NULL) \
- *isCopy = JNI_FALSE; \
- JNI_EXIT(); \
- return data; \
+#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
+ static _ctype* Get##_jname##ArrayElements(JNIEnv* env, \
+ _ctype##Array jarr, jboolean* isCopy) \
+ { \
+ ScopedJniThreadState ts(env); \
+ ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
+ pinPrimitiveArray(arrayObj); \
+ _ctype* data = (_ctype*) (void*) arrayObj->contents; \
+ if (isCopy != NULL) { \
+ *isCopy = JNI_FALSE; \
+ } \
+ return data; \
}
/*
@@ -2855,11 +2365,10 @@
{ \
UNUSED_PARAMETER(elems); \
if (mode != JNI_COMMIT) { \
- JNI_ENTER(); \
+ ScopedJniThreadState ts(env); \
ArrayObject* arrayObj = \
(ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
unpinPrimitiveArray(arrayObj); \
- JNI_EXIT(); \
} \
}
@@ -2868,46 +2377,42 @@
{
dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
"%s offset=%d length=%d %s.length=%d",
- arrayObj->obj.clazz->descriptor, start, len, arrayIdentifier,
+ arrayObj->clazz->descriptor, start, len, arrayIdentifier,
arrayObj->length);
}
/*
* Copy a section of a primitive array to a buffer.
*/
-#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
- static void Get##_jname##ArrayRegion(JNIEnv* env, \
- _ctype##Array jarr, jsize start, jsize len, _ctype* buf) \
- { \
- JNI_ENTER(); \
- ArrayObject* arrayObj = \
- (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
- _ctype* data = (_ctype*) arrayObj->contents; \
+#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
+ static void Get##_jname##ArrayRegion(JNIEnv* env, \
+ _ctype##Array jarr, jsize start, jsize len, _ctype* buf) \
+ { \
+ ScopedJniThreadState ts(env); \
+ ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
+ _ctype* data = (_ctype*) (void*) arrayObj->contents; \
if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
- throwArrayRegionOutOfBounds(arrayObj, start, len, "src"); \
- } else { \
- memcpy(buf, data + start, len * sizeof(_ctype)); \
- } \
- JNI_EXIT(); \
+ throwArrayRegionOutOfBounds(arrayObj, start, len, "src"); \
+ } else { \
+ memcpy(buf, data + start, len * sizeof(_ctype)); \
+ } \
}
/*
* Copy a section of a primitive array from a buffer.
*/
-#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
- static void Set##_jname##ArrayRegion(JNIEnv* env, \
- _ctype##Array jarr, jsize start, jsize len, const _ctype* buf) \
- { \
- JNI_ENTER(); \
- ArrayObject* arrayObj = \
- (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
- _ctype* data = (_ctype*) arrayObj->contents; \
+#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
+ static void Set##_jname##ArrayRegion(JNIEnv* env, \
+ _ctype##Array jarr, jsize start, jsize len, const _ctype* buf) \
+ { \
+ ScopedJniThreadState ts(env); \
+ ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr); \
+ _ctype* data = (_ctype*) (void*) arrayObj->contents; \
if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
- throwArrayRegionOutOfBounds(arrayObj, start, len, "dst"); \
- } else { \
- memcpy(data + start, buf, len * sizeof(_ctype)); \
- } \
- JNI_EXIT(); \
+ throwArrayRegionOutOfBounds(arrayObj, start, len, "dst"); \
+ } else { \
+ memcpy(data + start, buf, len * sizeof(_ctype)); \
+ } \
}
/*
@@ -2941,27 +2446,23 @@
static jint RegisterNatives(JNIEnv* env, jclass jclazz,
const JNINativeMethod* methods, jint nMethods)
{
- JNI_ENTER();
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jint retval = JNI_OK;
- int i;
if (gDvm.verboseJni) {
- LOGI("[Registering JNI native methods for class %s]\n",
+ LOGI("[Registering JNI native methods for class %s]",
clazz->descriptor);
}
- for (i = 0; i < nMethods; i++) {
+ for (int i = 0; i < nMethods; i++) {
if (!dvmRegisterJNIMethod(clazz, methods[i].name,
methods[i].signature, methods[i].fnPtr))
{
- retval = JNI_ERR;
+ return JNI_ERR;
}
}
-
- JNI_EXIT();
- return retval;
+ return JNI_OK;
}
/*
@@ -2990,18 +2491,15 @@
* with methods that only exist in the old or new form of the library (maybe
* the lib wants to try the call and catch the UnsatisfiedLinkError).
*/
-static jint UnregisterNatives(JNIEnv* env, jclass jclazz)
-{
- JNI_ENTER();
+static jint UnregisterNatives(JNIEnv* env, jclass jclazz) {
+ ScopedJniThreadState ts(env);
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
if (gDvm.verboseJni) {
- LOGI("[Unregistering JNI native methods for class %s]\n",
+ LOGI("[Unregistering JNI native methods for class %s]",
clazz->descriptor);
}
dvmUnregisterJNINativeMethods(clazz);
-
- JNI_EXIT();
return JNI_OK;
}
@@ -3011,13 +2509,11 @@
* We have to track all monitor enters and exits, so that we can undo any
* outstanding synchronization before the thread exits.
*/
-static jint MonitorEnter(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jint MonitorEnter(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- dvmLockObject(_self, obj);
- trackMonitorEnter(_self, obj);
- JNI_EXIT();
+ dvmLockObject(ts.self(), obj);
+ trackMonitorEnter(ts.self(), obj);
return JNI_OK;
}
@@ -3030,63 +2526,52 @@
* According to the 1.6 spec, it's legal to call here with an exception
* pending. If this fails, we'll stomp the original exception.
*/
-static jint MonitorExit(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jint MonitorExit(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
Object* obj = dvmDecodeIndirectRef(env, jobj);
- bool success = dvmUnlockObject(_self, obj);
- if (success)
- trackMonitorExit(_self, obj);
- JNI_EXIT();
+ bool success = dvmUnlockObject(ts.self(), obj);
+ if (success) {
+ trackMonitorExit(ts.self(), obj);
+ }
return success ? JNI_OK : JNI_ERR;
}
/*
* Return the JavaVM interface associated with the current thread.
*/
-static jint GetJavaVM(JNIEnv* env, JavaVM** vm)
-{
- JNI_ENTER();
- //*vm = gDvm.vmList;
- *vm = (JavaVM*) ((JNIEnvExt*)env)->vm;
- JNI_EXIT();
- if (*vm == NULL)
- return JNI_ERR;
- else
- return JNI_OK;
+static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
+ ScopedJniThreadState ts(env);
+ *vm = gDvmJni.jniVm;
+ return (*vm == NULL) ? JNI_ERR : JNI_OK;
}
/*
* Copies "len" Unicode characters, from offset "start".
*/
-static void GetStringRegion(JNIEnv* env, jstring jstr, jsize start, jsize len,
- jchar* buf)
-{
- JNI_ENTER();
+static void GetStringRegion(JNIEnv* env, jstring jstr, jsize start, jsize len, jchar* buf) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
int strLen = dvmStringLen(strObj);
- if (((start|len) < 0) || (start + len > dvmStringLen(strObj)))
+ if (((start|len) < 0) || (start + len > dvmStringLen(strObj))) {
dvmThrowStringIndexOutOfBoundsExceptionWithRegion(strLen, start, len);
- else
- memcpy(buf, dvmStringChars(strObj) + start, len * sizeof(u2));
- JNI_EXIT();
+ return;
+ }
+ memcpy(buf, dvmStringChars(strObj) + start, len * sizeof(u2));
}
/*
* Translates "len" Unicode characters, from offset "start", into
* modified UTF-8 encoding.
*/
-static void GetStringUTFRegion(JNIEnv* env, jstring jstr, jsize start,
- jsize len, char* buf)
-{
- JNI_ENTER();
+static void GetStringUTFRegion(JNIEnv* env, jstring jstr, jsize start, jsize len, char* buf) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
int strLen = dvmStringLen(strObj);
- if (((start|len) < 0) || (start + len > dvmStringLen(strObj)))
+ if (((start|len) < 0) || (start + len > dvmStringLen(strObj))) {
dvmThrowStringIndexOutOfBoundsExceptionWithRegion(strLen, start, len);
- else
- dvmCreateCstrFromStringRegion(strObj, start, len, buf);
- JNI_EXIT();
+ return;
+ }
+ dvmCreateCstrFromStringRegion(strObj, start, len, buf);
}
/*
@@ -3097,87 +2582,71 @@
*
* We need to pin the memory or block GC.
*/
-static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray jarr,
- jboolean* isCopy)
-{
- JNI_ENTER();
- void* data;
+static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray jarr, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
pinPrimitiveArray(arrayObj);
- data = arrayObj->contents;
- if (isCopy != NULL)
+ void* data = arrayObj->contents;
+ if (isCopy != NULL) {
*isCopy = JNI_FALSE;
- JNI_EXIT();
+ }
return data;
}
/*
* Release an array obtained with GetPrimitiveArrayCritical.
*/
-static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray jarr,
- void* carray, jint mode)
-{
+static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray jarr, void* carray, jint mode) {
if (mode != JNI_COMMIT) {
- JNI_ENTER();
+ ScopedJniThreadState ts(env);
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
unpinPrimitiveArray(arrayObj);
- JNI_EXIT();
}
}
/*
* Like GetStringChars, but with restricted use.
*/
-static const jchar* GetStringCritical(JNIEnv* env, jstring jstr,
- jboolean* isCopy)
-{
- JNI_ENTER();
+static const jchar* GetStringCritical(JNIEnv* env, jstring jstr, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
+
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
ArrayObject* strChars = dvmStringCharArray(strObj);
pinPrimitiveArray(strChars);
const u2* data = dvmStringChars(strObj);
- if (isCopy != NULL)
+ if (isCopy != NULL) {
*isCopy = JNI_FALSE;
-
- JNI_EXIT();
- return (jchar*)data;
+ }
+ return (jchar*) data;
}
/*
* Like ReleaseStringChars, but with restricted use.
*/
-static void ReleaseStringCritical(JNIEnv* env, jstring jstr,
- const jchar* carray)
-{
- JNI_ENTER();
+static void ReleaseStringCritical(JNIEnv* env, jstring jstr, const jchar* carray) {
+ ScopedJniThreadState ts(env);
StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
ArrayObject* strChars = dvmStringCharArray(strObj);
unpinPrimitiveArray(strChars);
- JNI_EXIT();
}
/*
* Create a new weak global reference.
*/
-static jweak NewWeakGlobalRef(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
+static jweak NewWeakGlobalRef(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
Object *obj = dvmDecodeIndirectRef(env, jobj);
- jweak retval = addWeakGlobalReference(obj);
- JNI_EXIT();
- return retval;
+ return (jweak) addWeakGlobalReference(obj);
}
/*
* Delete the specified weak global reference.
*/
-static void DeleteWeakGlobalRef(JNIEnv* env, jweak wref)
-{
- JNI_ENTER();
+static void DeleteWeakGlobalRef(JNIEnv* env, jweak wref) {
+ ScopedJniThreadState ts(env);
deleteWeakGlobalReference(wref);
- JNI_EXIT();
}
/*
@@ -3185,12 +2654,9 @@
*
* TODO: we should be able to skip the enter/exit macros here.
*/
-static jboolean ExceptionCheck(JNIEnv* env)
-{
- JNI_ENTER();
- bool result = dvmCheckException(_self);
- JNI_EXIT();
- return result;
+static jboolean ExceptionCheck(JNIEnv* env) {
+ ScopedJniThreadState ts(env);
+ return dvmCheckException(ts.self());
}
/*
@@ -3201,12 +2667,9 @@
* the same time, so while the return value is accurate it may not tell
* the whole story.
*/
-static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj)
-{
- JNI_ENTER();
- jobjectRefType type = dvmGetJNIRefType(env, jobj);
- JNI_EXIT();
- return type;
+static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj) {
+ ScopedJniThreadState ts(env);
+ return dvmGetJNIRefType(env, jobj);
}
/*
@@ -3215,33 +2678,27 @@
* "address" may not be NULL, and "capacity" must be > 0. (These are only
* verified when CheckJNI is enabled.)
*/
-static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity)
-{
- JNI_ENTER();
-
- Thread* self = _self /*dvmThreadSelf()*/;
- JValue unused;
- jobject result = NULL;
- ClassObject* bufferClazz = gDvm.classJavaNioReadWriteDirectByteBuffer;
+static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
+ ScopedJniThreadState ts(env);
/* create an instance of java.nio.ReadWriteDirectByteBuffer */
- if (!dvmIsClassInitialized(bufferClazz) && !dvmInitClass(bufferClazz))
- goto bail;
- Object* newObj = dvmAllocObject(bufferClazz, ALLOC_DONT_TRACK);
- if (newObj != NULL) {
- /* call the constructor */
- result = addLocalReference(env, newObj);
- dvmCallMethod(self, gDvm.methJavaNioReadWriteDirectByteBuffer_init,
- newObj, &unused, (jint) address, (jint) capacity);
- if (dvmGetException(self) != NULL) {
- deleteLocalReference(env, result);
- result = NULL;
- goto bail;
- }
+ ClassObject* bufferClazz = gDvm.classJavaNioReadWriteDirectByteBuffer;
+ if (!dvmIsClassInitialized(bufferClazz) && !dvmInitClass(bufferClazz)) {
+ return NULL;
}
-
-bail:
- JNI_EXIT();
+ Object* newObj = dvmAllocObject(bufferClazz, ALLOC_DONT_TRACK);
+ if (newObj == NULL) {
+ return NULL;
+ }
+ /* call the constructor */
+ jobject result = addLocalReference(env, newObj);
+ JValue unused;
+ dvmCallMethod(ts.self(), gDvm.methJavaNioReadWriteDirectByteBuffer_init,
+ newObj, &unused, (jint) address, (jint) capacity);
+ if (dvmGetException(ts.self()) != NULL) {
+ deleteLocalReference(env, result);
+ return NULL;
+ }
return result;
}
@@ -3250,20 +2707,12 @@
*
* If this is not a "direct" buffer, we return NULL.
*/
-static void* GetDirectBufferAddress(JNIEnv* env, jobject jbuf)
-{
- JNI_ENTER();
+static void* GetDirectBufferAddress(JNIEnv* env, jobject jbuf) {
+ ScopedJniThreadState ts(env);
+ // All Buffer objects have an effectiveDirectAddress field.
Object* bufObj = dvmDecodeIndirectRef(env, jbuf);
-
- /*
- * All Buffer objects have an effectiveDirectAddress field.
- */
- void* result = (void*) dvmGetFieldInt(bufObj,
- gDvm.offJavaNioBuffer_effectiveDirectAddress);
-
- JNI_EXIT();
- return result;
+ return (void*) dvmGetFieldInt(bufObj, gDvm.offJavaNioBuffer_effectiveDirectAddress);
}
/*
@@ -3273,9 +2722,8 @@
* this check, since it's expensive to determine, and just return the
* capacity regardless.)
*/
-static jlong GetDirectBufferCapacity(JNIEnv* env, jobject jbuf)
-{
- JNI_ENTER();
+static jlong GetDirectBufferCapacity(JNIEnv* env, jobject jbuf) {
+ ScopedJniThreadState ts(env);
/*
* The capacity is always in the Buffer.capacity field.
@@ -3284,10 +2732,7 @@
* but we're not required to do so here.)
*/
Object* buf = dvmDecodeIndirectRef(env, jbuf);
- jlong result = dvmGetFieldInt(buf, gDvm.offJavaNioBuffer_capacity);
-
- JNI_EXIT();
- return result;
+ return dvmGetFieldInt(buf, gDvm.offJavaNioBuffer_capacity);
}
@@ -3316,17 +2761,13 @@
* Remember that some code may call this as a way to find the per-thread
* JNIEnv pointer. Don't do excess work for that case.
*/
-static jint attachThread(JavaVM* vm, JNIEnv** p_env, void* thr_args,
- bool isDaemon)
-{
+static jint attachThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool isDaemon) {
JavaVMAttachArgs* args = (JavaVMAttachArgs*) thr_args;
- Thread* self;
- bool result = false;
/*
* Return immediately if we're already one with the VM.
*/
- self = dvmThreadSelf();
+ Thread* self = dvmThreadSelf();
if (self != NULL) {
*p_env = self->jniEnv;
return JNI_OK;
@@ -3343,7 +2784,7 @@
dvmLockThreadList(NULL);
if (gDvm.nonDaemonThreadCount == 0) {
// dead or dying
- LOGV("Refusing to attach thread '%s' -- VM is shutting down\n",
+ LOGV("Refusing to attach thread '%s' -- VM is shutting down",
(thr_args == NULL) ? "(unknown)" : args->name);
dvmUnlockThreadList();
return JNI_ERR;
@@ -3357,19 +2798,20 @@
/* allow the v1.1 calling convention */
argsCopy.version = JNI_VERSION_1_2;
argsCopy.name = NULL;
- argsCopy.group = dvmGetMainThreadGroup();
+ argsCopy.group = (jobject) dvmGetMainThreadGroup();
} else {
assert(args->version >= JNI_VERSION_1_2);
argsCopy.version = args->version;
argsCopy.name = args->name;
- if (args->group != NULL)
+ if (args->group != NULL) {
argsCopy.group = args->group;
- else
- argsCopy.group = dvmGetMainThreadGroup();
+ } else {
+ argsCopy.group = (jobject) dvmGetMainThreadGroup();
+ }
}
- result = dvmAttachCurrentThread(&argsCopy, isDaemon);
+ bool result = dvmAttachCurrentThread(&argsCopy, isDaemon);
/* restore the count */
dvmLockThreadList(NULL);
@@ -3396,16 +2838,14 @@
* Attach the current thread to the VM. If the thread is already attached,
* this is a no-op.
*/
-static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args)
-{
+static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
return attachThread(vm, p_env, thr_args, false);
}
/*
* Like AttachCurrentThread, but set the "daemon" flag.
*/
-static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
- void* thr_args)
+static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args)
{
return attachThread(vm, p_env, thr_args, true);
}
@@ -3413,12 +2853,12 @@
/*
* Dissociate the current thread from the VM.
*/
-static jint DetachCurrentThread(JavaVM* vm)
-{
+static jint DetachCurrentThread(JavaVM* vm) {
Thread* self = dvmThreadSelf();
-
- if (self == NULL) /* not attached, can't do anything */
+ if (self == NULL) {
+ /* not attached, can't do anything */
return JNI_ERR;
+ }
/* switch to "running" to check for suspension */
dvmChangeStatus(self, THREAD_RUNNING);
@@ -3437,12 +2877,12 @@
* JVMTI overloads this by specifying a magic value for "version", so we
* do want to check that here.
*/
-static jint GetEnv(JavaVM* vm, void** env, jint version)
-{
+static jint GetEnv(JavaVM* vm, void** env, jint version) {
Thread* self = dvmThreadSelf();
- if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6)
+ if (version < JNI_VERSION_1_1 || version > JNI_VERSION_1_6) {
return JNI_EVERSION;
+ }
if (self == NULL) {
*env = NULL;
@@ -3452,10 +2892,7 @@
*env = (void*) dvmGetThreadJNIEnv(self);
dvmChangeStatus(self, THREAD_NATIVE);
}
- if (*env == NULL)
- return JNI_EDETACHED;
- else
- return JNI_OK;
+ return (*env != NULL) ? JNI_OK : JNI_EDETACHED;
}
/*
@@ -3472,30 +2909,28 @@
* the condition variable forever. Not sure this situation is interesting
* in real life.
*/
-static jint DestroyJavaVM(JavaVM* vm)
-{
+static jint DestroyJavaVM(JavaVM* vm) {
JavaVMExt* ext = (JavaVMExt*) vm;
- Thread* self;
-
- if (ext == NULL)
+ if (ext == NULL) {
return JNI_ERR;
+ }
- if (gDvm.verboseShutdown)
- LOGD("DestroyJavaVM waiting for non-daemon threads to exit\n");
+ if (gDvm.verboseShutdown) {
+ LOGD("DestroyJavaVM waiting for non-daemon threads to exit");
+ }
/*
* Sleep on a condition variable until it's okay to exit.
*/
- self = dvmThreadSelf();
+ Thread* self = dvmThreadSelf();
if (self == NULL) {
JNIEnv* tmpEnv;
if (AttachCurrentThread(vm, &tmpEnv, NULL) != JNI_OK) {
- LOGV("Unable to reattach main for Destroy; assuming VM is "
- "shutting down (count=%d)\n",
+ LOGV("Unable to reattach main for Destroy; assuming VM is shutting down (count=%d)",
gDvm.nonDaemonThreadCount);
goto shutdown;
} else {
- LOGV("Attached to wait for shutdown in Destroy\n");
+ LOGV("Attached to wait for shutdown in Destroy");
}
}
dvmChangeStatus(self, THREAD_VMWAIT);
@@ -3503,8 +2938,9 @@
dvmLockThreadList(self);
gDvm.nonDaemonThreadCount--; // remove current thread from count
- while (gDvm.nonDaemonThreadCount > 0)
+ while (gDvm.nonDaemonThreadCount > 0) {
pthread_cond_wait(&gDvm.vmExitCond, &gDvm.threadListLock);
+ }
dvmUnlockThreadList();
self = NULL;
@@ -3513,8 +2949,9 @@
// TODO: call System.exit() to run any registered shutdown hooks
// (this may not return -- figure out how this should work)
- if (gDvm.verboseShutdown)
- LOGD("DestroyJavaVM shutting VM down\n");
+ if (gDvm.verboseShutdown) {
+ LOGD("DestroyJavaVM shutting VM down");
+ }
dvmShutdown();
// TODO - free resources associated with JNI-attached daemon threads
@@ -3804,6 +3241,7 @@
GetObjectRefType
};
+
static const struct JNIInvokeInterface gInvokeInterface = {
NULL,
NULL,
@@ -3818,7 +3256,6 @@
AttachCurrentThreadAsDaemon,
};
-
/*
* ===========================================================================
* VM/Env creation
@@ -3826,6 +3263,82 @@
*/
/*
+ * Create a new JNIEnv struct and add it to the VM's list.
+ *
+ * "self" will be NULL for the main thread, since the VM hasn't started
+ * yet; the value will be filled in later.
+ */
+JNIEnv* dvmCreateJNIEnv(Thread* self) {
+ JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
+
+ //if (self != NULL)
+ // LOGI("Ent CreateJNIEnv: threadid=%d %p", self->threadId, self);
+
+ assert(vm != NULL);
+
+ JNIEnvExt* newEnv = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
+ newEnv->funcTable = &gNativeInterface;
+ if (self != NULL) {
+ dvmSetJniEnvThreadId((JNIEnv*) newEnv, self);
+ assert(newEnv->envThreadId != 0);
+ } else {
+ /* make it obvious if we fail to initialize these later */
+ newEnv->envThreadId = 0x77777775;
+ newEnv->self = (Thread*) 0x77777779;
+ }
+ if (gDvmJni.useCheckJni) {
+ dvmUseCheckedJniEnv(newEnv);
+ }
+
+ ScopedPthreadMutexLock lock(&vm->envListLock);
+
+ /* insert at head of list */
+ newEnv->next = vm->envList;
+ assert(newEnv->prev == NULL);
+ if (vm->envList == NULL) {
+ // rare, but possible
+ vm->envList = newEnv;
+ } else {
+ vm->envList->prev = newEnv;
+ }
+ vm->envList = newEnv;
+
+ //if (self != NULL)
+ // LOGI("Xit CreateJNIEnv: threadid=%d %p", self->threadId, self);
+ return (JNIEnv*) newEnv;
+}
+
+/*
+ * Remove a JNIEnv struct from the list and free it.
+ */
+void dvmDestroyJNIEnv(JNIEnv* env) {
+ if (env == NULL) {
+ return;
+ }
+
+ //LOGI("Ent DestroyJNIEnv: threadid=%d %p", self->threadId, self);
+
+ JNIEnvExt* extEnv = (JNIEnvExt*) env;
+ JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
+
+ ScopedPthreadMutexLock lock(&vm->envListLock);
+
+ if (extEnv == vm->envList) {
+ assert(extEnv->prev == NULL);
+ vm->envList = extEnv->next;
+ } else {
+ assert(extEnv->prev != NULL);
+ extEnv->prev->next = extEnv->next;
+ }
+ if (extEnv->next != NULL) {
+ extEnv->next->prev = extEnv->prev;
+ }
+
+ free(env);
+ //LOGI("Xit DestroyJNIEnv: threadid=%d %p", self->threadId, self);
+}
+
+/*
* Enable "checked JNI" after the VM has partially started. This must
* only be called in "zygote" mode, when we have one thread running.
*
@@ -3833,36 +3346,28 @@
* native methods, so we won't get those checks for any methods that have
* already been resolved.
*/
-void dvmLateEnableCheckedJni(void)
-{
- JNIEnvExt* extEnv;
- JavaVMExt* extVm;
-
- extEnv = dvmGetJNIEnvForThread();
+void dvmLateEnableCheckedJni() {
+ JNIEnvExt* extEnv = dvmGetJNIEnvForThread();
if (extEnv == NULL) {
- LOGE("dvmLateEnableCheckedJni: thread has no JNIEnv\n");
+ LOGE("dvmLateEnableCheckedJni: thread has no JNIEnv");
return;
}
- extVm = extEnv->vm;
+ JavaVMExt* extVm = (JavaVMExt*) gDvmJni.jniVm;
assert(extVm != NULL);
- if (!extVm->useChecked) {
- LOGD("Late-enabling CheckJNI\n");
+ if (!gDvmJni.useCheckJni) {
+ LOGD("Late-enabling CheckJNI");
dvmUseCheckedJniVm(extVm);
- extVm->useChecked = true;
dvmUseCheckedJniEnv(extEnv);
-
- /* currently no way to pick up jniopts features */
} else {
- LOGD("Not late-enabling CheckJNI (already on)\n");
+ LOGD("Not late-enabling CheckJNI (already on)");
}
}
/*
* Not supported.
*/
-jint JNI_GetDefaultJavaVMInitArgs(void* vm_args)
-{
+jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
return JNI_ERR;
}
@@ -3871,42 +3376,29 @@
*
* We always have zero or one.
*/
-jint JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
-{
- if (gDvm.vmList != NULL) {
+jint JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) {
+ if (gDvmJni.jniVm != NULL) {
*nVMs = 1;
-
- if (bufLen > 0)
- *vmBuf++ = gDvm.vmList;
+ if (bufLen > 0) {
+ *vmBuf++ = gDvmJni.jniVm;
+ }
} else {
*nVMs = 0;
}
-
return JNI_OK;
}
-
/*
* Create a new VM instance.
*
* The current thread becomes the main VM thread. We return immediately,
* which effectively means the caller is executing in a native method.
*/
-jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)
-{
+jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
const JavaVMInitArgs* args = (JavaVMInitArgs*) vm_args;
- JNIEnvExt* pEnv = NULL;
- JavaVMExt* pVM = NULL;
- const char** argv;
- int argc = 0;
- int i, curOpt;
- int result = JNI_ERR;
- bool checkJni = false;
- bool warnError = true;
- bool forceDataCopy = false;
-
- if (args->version < JNI_VERSION_1_2)
+ if (args->version < JNI_VERSION_1_2) {
return JNI_EVERSION;
+ }
// TODO: don't allow creation of multiple VMs -- one per customer for now
@@ -3916,21 +3408,14 @@
/*
* Set up structures for JNIEnv and VM.
*/
- //pEnv = (JNIEnvExt*) malloc(sizeof(JNIEnvExt));
- pVM = (JavaVMExt*) malloc(sizeof(JavaVMExt));
-
- //memset(pEnv, 0, sizeof(JNIEnvExt));
- //pEnv->funcTable = &gNativeInterface;
- //pEnv->vm = pVM;
+ JavaVMExt* pVM = (JavaVMExt*) malloc(sizeof(JavaVMExt));
memset(pVM, 0, sizeof(JavaVMExt));
pVM->funcTable = &gInvokeInterface;
- pVM->envList = pEnv;
+ pVM->envList = NULL;
dvmInitMutex(&pVM->envListLock);
- argv = (const char**) malloc(sizeof(char*) * (args->nOptions));
- memset(argv, 0, sizeof(char*) * (args->nOptions));
-
- curOpt = 0;
+ UniquePtr<const char*[]> argv(new const char*[args->nOptions]);
+ memset(argv.get(), 0, sizeof(char*) * (args->nOptions));
/*
* Convert JNI args to argv.
@@ -3939,15 +3424,15 @@
* "extraInfo" field to pass function pointer "hooks" in. We also
* look for the -Xcheck:jni stuff here.
*/
- for (i = 0; i < args->nOptions; i++) {
+ int argc = 0;
+ bool sawJniOpts = false;
+ for (int i = 0; i < args->nOptions; i++) {
const char* optStr = args->options[i].optionString;
-
if (optStr == NULL) {
- fprintf(stderr, "ERROR: arg %d string was null\n", i);
- goto bail;
+ dvmFprintf(stderr, "ERROR: CreateJavaVM failed: argument %d was NULL\n", i);
+ return JNI_ERR;
} else if (strcmp(optStr, "vfprintf") == 0) {
- gDvm.vfprintfHook =
- (int (*)(FILE *, const char*, va_list))args->options[i].extraInfo;
+ gDvm.vfprintfHook = (int (*)(FILE *, const char*, va_list))args->options[i].extraInfo;
} else if (strcmp(optStr, "exit") == 0) {
gDvm.exitHook = (void (*)(int)) args->options[i].extraInfo;
} else if (strcmp(optStr, "abort") == 0) {
@@ -3955,50 +3440,69 @@
} else if (strcmp(optStr, "sensitiveThread") == 0) {
gDvm.isSensitiveThreadHook = (bool (*)(void))args->options[i].extraInfo;
} else if (strcmp(optStr, "-Xcheck:jni") == 0) {
- checkJni = true;
+ gDvmJni.useCheckJni = true;
} else if (strncmp(optStr, "-Xjniopts:", 10) == 0) {
- const char* jniOpts = optStr + 9;
- while (jniOpts != NULL) {
- jniOpts++; /* skip past ':' or ',' */
- if (strncmp(jniOpts, "warnonly", 8) == 0) {
- warnError = false;
- } else if (strncmp(jniOpts, "forcecopy", 9) == 0) {
- forceDataCopy = true;
- } else {
- LOGW("unknown jni opt starting at '%s'\n", jniOpts);
+ sawJniOpts = true;
+ char* jniOpts = strdup(optStr + 10);
+ size_t jniOptCount = 1;
+ for (char* p = jniOpts; *p != 0; ++p) {
+ if (*p == ',') {
+ ++jniOptCount;
+ *p = 0;
}
- jniOpts = strchr(jniOpts, ',');
}
+ char* jniOpt = jniOpts;
+ for (size_t i = 0; i < jniOptCount; ++i) {
+ if (strcmp(jniOpt, "warnonly") == 0) {
+ gDvmJni.warnOnly = true;
+ } else if (strcmp(jniOpt, "forcecopy") == 0) {
+ gDvmJni.forceCopy = true;
+ } else {
+ dvmFprintf(stderr, "ERROR: CreateJavaVM failed: unknown -Xjniopts option '%s'\n",
+ jniOpt);
+ return JNI_ERR;
+ }
+ jniOpt += strlen(jniOpt) + 1;
+ }
+ free(jniOpts);
} else {
/* regular option */
- argv[curOpt++] = optStr;
+ argv[argc++] = optStr;
}
}
- argc = curOpt;
- if (checkJni) {
- dvmUseCheckedJniVm(pVM);
- pVM->useChecked = true;
+ if (sawJniOpts && !gDvmJni.useCheckJni) {
+ dvmFprintf(stderr, "ERROR: -Xjniopts only makes sense with -Xcheck:jni\n");
+ return JNI_ERR;
}
- pVM->warnError = warnError;
- pVM->forceDataCopy = forceDataCopy;
- /* set this up before initializing VM, so it can create some JNIEnvs */
- gDvm.vmList = (JavaVM*) pVM;
+ if (gDvmJni.useCheckJni) {
+ dvmUseCheckedJniVm(pVM);
+ }
+
+ if (gDvmJni.jniVm != NULL) {
+ dvmFprintf(stderr, "ERROR: Dalvik only supports one VM per process\n");
+ return JNI_ERR;
+ }
+ gDvmJni.jniVm = (JavaVM*) pVM;
/*
- * Create an env for main thread. We need to have something set up
+ * Create a JNIEnv for the main thread. We need to have something set up
* here because some of the class initialization we do when starting
* up the VM will call into native code.
*/
- pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
+ JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
- /* initialize VM */
+ /* Initialize VM. */
gDvm.initializing = true;
- if (dvmStartup(argc, argv, args->ignoreUnrecognized, (JNIEnv*)pEnv) != 0) {
+ int rc = dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
+ gDvm.initializing = false;
+
+ if (rc != 0) {
free(pEnv);
free(pVM);
- goto bail;
+ LOGW("CreateJavaVM failed");
+ return JNI_ERR;
}
/*
@@ -4007,14 +3511,6 @@
dvmChangeStatus(NULL, THREAD_NATIVE);
*p_env = (JNIEnv*) pEnv;
*p_vm = (JavaVM*) pVM;
- result = JNI_OK;
-
-bail:
- gDvm.initializing = false;
- if (result == JNI_OK)
- LOGV("JNI_CreateJavaVM succeeded\n");
- else
- LOGW("JNI_CreateJavaVM failed\n");
- free(argv);
- return result;
+ LOGV("CreateJavaVM succeeded");
+ return JNI_OK;
}
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index bc88cad..9412ab8 100644
--- a/vm/JniInternal.h
+++ b/vm/JniInternal.h
@@ -32,43 +32,30 @@
*/
struct JavaVMExt;
-typedef struct JNIEnvExt {
+struct JNIEnvExt {
const struct JNINativeInterface* funcTable; /* must be first */
const struct JNINativeInterface* baseFuncTable;
- /* pointer to the VM we are a part of */
- struct JavaVMExt* vm;
-
u4 envThreadId;
Thread* self;
/* if nonzero, we are in a "critical" JNI call */
int critical;
- /* keep a copy of this here for speed */
- bool forceDataCopy;
-
struct JNIEnvExt* prev;
struct JNIEnvExt* next;
-} JNIEnvExt;
+};
-typedef struct JavaVMExt {
+struct JavaVMExt {
const struct JNIInvokeInterface* funcTable; /* must be first */
const struct JNIInvokeInterface* baseFuncTable;
- /* if multiple VMs are desired, add doubly-linked list stuff here */
-
- /* per-VM feature flags */
- bool useChecked;
- bool warnError;
- bool forceDataCopy;
-
/* head of list of JNIEnvs associated with this VM */
JNIEnvExt* envList;
pthread_mutex_t envListLock;
-} JavaVMExt;
+};
/*
* Native function return type; used by dvmPlatformInvoke().
@@ -77,7 +64,7 @@
* Note: Assembly code in arch/<arch>/Call<arch>.S relies on
* the enum values defined here.
*/
-typedef enum DalvikJniReturnType {
+enum DalvikJniReturnType {
DALVIK_JNI_RETURN_VOID = 0, /* must be zero */
DALVIK_JNI_RETURN_FLOAT = 1,
DALVIK_JNI_RETURN_DOUBLE = 2,
@@ -86,7 +73,7 @@
DALVIK_JNI_RETURN_S2 = 5,
DALVIK_JNI_RETURN_U2 = 6,
DALVIK_JNI_RETURN_S1 = 7
-} DalvikJniReturnType;
+};
#define DALVIK_JNI_NO_ARG_INFO 0x80000000
#define DALVIK_JNI_RETURN_MASK 0x70000000
diff --git a/vm/LinearAlloc.c b/vm/LinearAlloc.cpp
similarity index 100%
rename from vm/LinearAlloc.c
rename to vm/LinearAlloc.cpp
diff --git a/vm/LinearAlloc.h b/vm/LinearAlloc.h
index aa33fe1..3305e5b 100644
--- a/vm/LinearAlloc.h
+++ b/vm/LinearAlloc.h
@@ -30,7 +30,7 @@
* allocated region, but that would prevent us from sharing the rest of
* that first page.
*/
-typedef struct LinearAllocHdr {
+struct LinearAllocHdr {
int curOffset; /* offset where next data goes */
pthread_mutex_t lock; /* controls updates to this struct */
@@ -39,7 +39,7 @@
int firstOffset; /* for chasing through */
short* writeRefCount; /* for ENFORCE_READ_ONLY */
-} LinearAllocHdr;
+};
/*
diff --git a/vm/Misc.c b/vm/Misc.cpp
similarity index 99%
rename from vm/Misc.c
rename to vm/Misc.cpp
index 2c3926c..5412c75 100644
--- a/vm/Misc.c
+++ b/vm/Misc.cpp
@@ -410,7 +410,7 @@
* computing durations (e.g. "operation X took 52nsec"), so the result
* should not be used to get the current date/time.
*/
-u8 dvmGetRelativeTimeNsec(void)
+u8 dvmGetRelativeTimeNsec()
{
#ifdef HAVE_POSIX_CLOCKS
struct timespec now;
@@ -428,7 +428,7 @@
*
* Only useful for time deltas.
*/
-u8 dvmGetThreadCpuTimeNsec(void)
+u8 dvmGetThreadCpuTimeNsec()
{
#ifdef HAVE_POSIX_CLOCKS
struct timespec now;
diff --git a/vm/Misc.h b/vm/Misc.h
index c1c3d47..7ce9708 100644
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -20,11 +20,10 @@
#ifndef _DALVIK_MISC
#define _DALVIK_MISC
-#include "Inlines.h"
-
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
+#include "Inlines.h"
/*
* Used to shut up the compiler when a parameter isn't used.
@@ -64,7 +63,7 @@
*
* If "tag" is NULL the default tag ("dalvikvm") will be used.
*/
-typedef enum { kHexDumpLocal, kHexDumpMem } HexDumpMode;
+enum HexDumpMode { kHexDumpLocal, kHexDumpMem };
void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
size_t length, HexDumpMode mode);
@@ -87,17 +86,19 @@
#endif
}
+enum DebugTargetKind {
+ kDebugTargetUnknown = 0,
+ kDebugTargetLog,
+ kDebugTargetFile,
+};
+
/*
* We pass one of these around when we want code to be able to write debug
* info to either the log or to a file (or stdout/stderr).
*/
-typedef struct DebugOutputTarget {
+struct DebugOutputTarget {
/* where to? */
- enum {
- kDebugTargetUnknown = 0,
- kDebugTargetLog,
- kDebugTargetFile,
- } which;
+ DebugTargetKind which;
/* additional bits */
union {
@@ -109,7 +110,7 @@
FILE* fp;
} file;
} data;
-} DebugOutputTarget;
+};
/*
* Fill in a DebugOutputTarget struct.
@@ -140,7 +141,7 @@
* of 'descriptor'. So "I" would be "int", "[[I" would be "int[][]",
* "[Ljava/lang/String;" would be "java.lang.String[]", and so forth.
*/
-char* dvmHumanReadableDescriptor(const char* descriptor);
+extern "C" char* dvmHumanReadableDescriptor(const char* descriptor);
/*
* Return a newly-allocated string for the "dot version" of the class
@@ -255,12 +256,12 @@
* get from the abort may point at the wrong call site. Best to leave
* it undecorated.
*/
-void dvmAbort(void);
+extern "C" void dvmAbort(void);
void dvmPrintNativeBackTrace(void);
#if (!HAVE_STRLCPY)
/* Implementation of strlcpy() for platforms that don't already have it. */
-size_t strlcpy(char *dst, const char *src, size_t size);
+extern "C" size_t strlcpy(char *dst, const char *src, size_t size);
#endif
/*
@@ -273,11 +274,11 @@
/*
* Get some per-thread stats from /proc/self/task/N/stat.
*/
-typedef struct {
+struct ProcStatData {
unsigned long utime; /* number of jiffies scheduled in user mode */
unsigned long stime; /* number of jiffies scheduled in kernel mode */
int processor; /* number of CPU that last executed thread */
-} ProcStatData;
+};
bool dvmGetThreadStats(ProcStatData* pData, pid_t tid);
/*
diff --git a/vm/Native.c b/vm/Native.cpp
similarity index 96%
rename from vm/Native.c
rename to vm/Native.cpp
index a06bf3c..bbb4ce6 100644
--- a/vm/Native.c
+++ b/vm/Native.cpp
@@ -33,7 +33,7 @@
/*
* Initialize the native code loader.
*/
-bool dvmNativeStartup(void)
+bool dvmNativeStartup()
{
gDvm.nativeLibs = dvmHashTableCreate(4, freeSharedLibEntry);
if (gDvm.nativeLibs == NULL)
@@ -45,7 +45,7 @@
/*
* Free up our tables.
*/
-void dvmNativeShutdown(void)
+void dvmNativeShutdown()
{
dvmHashTableFree(gDvm.nativeLibs);
gDvm.nativeLibs = NULL;
@@ -71,7 +71,6 @@
const Method* method, Thread* self)
{
ClassObject* clazz = method->clazz;
- void* func;
/*
* If this is a static method, it could be called before the class
@@ -88,8 +87,8 @@
}
/* start with our internal-native methods */
- func = dvmLookupInternalNativeMethod(method);
- if (func != NULL) {
+ DalvikNativeFunc infunc = dvmLookupInternalNativeMethod(method);
+ if (infunc != NULL) {
/* resolution always gets the same answer, so no race here */
IF_LOGVV() {
char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
@@ -102,14 +101,14 @@
LOGE("Failing on %s.%s\n", method->clazz->descriptor, method->name);
dvmAbort(); // harsh, but this is VM-internal problem
}
- DalvikBridgeFunc dfunc = (DalvikBridgeFunc) func;
+ DalvikBridgeFunc dfunc = (DalvikBridgeFunc) infunc;
dvmSetNativeFunc((Method*) method, dfunc, NULL);
dfunc(args, pResult, method, self);
return;
}
/* now scan any DLLs we have loaded for JNI signatures */
- func = lookupSharedLibMethod(method);
+ void* func = lookupSharedLibMethod(method);
if (func != NULL) {
/* found it, point it at the JNI bridge and then call it */
dvmUseJNIBridge((Method*) method, func);
@@ -138,17 +137,17 @@
// are associated with it. (Or not -- can't determine if native code
// is still using parts of it.)
-typedef enum OnLoadState {
+enum OnLoadState {
kOnLoadPending = 0, /* initial state, must be zero */
kOnLoadFailed,
kOnLoadOkay,
-} OnLoadState;
+};
/*
* We add one of these to the hash table for every library we load. The
* hash is on the "pathName" field.
*/
-typedef struct SharedLib {
+struct SharedLib {
char* pathName; /* absolute path to library */
void* handle; /* from dlopen */
Object* classLoader; /* ClassLoader we are associated with */
@@ -157,7 +156,7 @@
pthread_cond_t onLoadCond; /* wait for JNI_OnLoad in other thread */
u4 onLoadThreadId; /* recursive invocation guard */
OnLoadState onLoadResult; /* result of earlier JNI_OnLoad */
-} SharedLib;
+};
/*
* (This is a dvmHashTableLookup callback.)
@@ -432,7 +431,7 @@
self->classLoaderOverride = classLoader;
oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
LOGV("+++ calling JNI_OnLoad(%s)\n", pathName);
- version = (*func)(gDvm.vmList, NULL);
+ version = (*func)(gDvmJni.jniVm, NULL);
dvmChangeStatus(self, oldStatus);
self->classLoaderOverride = prevOverride;
@@ -580,27 +579,22 @@
*/
static char* mangleString(const char* str, int len)
{
- u2* utf16 = NULL;
- char* mangle = NULL;
- int charLen;
-
//LOGI("mangling '%s' %d\n", str, len);
assert(str[len] == '\0');
- charLen = dvmUtf8Len(str);
- utf16 = (u2*) malloc(sizeof(u2) * charLen);
+ size_t charLen = dvmUtf8Len(str);
+ u2* utf16 = (u2*) malloc(sizeof(u2) * charLen);
if (utf16 == NULL)
- goto bail;
+ return NULL;
dvmConvertUtf8ToUtf16(utf16, str);
/*
* Compute the length of the mangled string.
*/
- int i, mangleLen = 0;
-
- for (i = 0; i < charLen; i++) {
+ size_t mangleLen = 0;
+ for (size_t i = 0; i < charLen; i++) {
u2 ch = utf16[i];
if (ch == '$' || ch > 127) {
@@ -619,13 +613,14 @@
}
}
- char* cp;
+ char* mangle = (char*) malloc(mangleLen +1);
+ if (mangle == NULL) {
+ free(utf16);
+ return NULL;
+ }
- mangle = (char*) malloc(mangleLen +1);
- if (mangle == NULL)
- goto bail;
-
- for (i = 0, cp = mangle; i < charLen; i++) {
+ char* cp = mangle;
+ for (size_t i = 0; i < charLen; i++) {
u2 ch = utf16[i];
if (ch == '$' || ch > 127) {
@@ -657,7 +652,6 @@
*cp = '\0';
-bail:
free(utf16);
return mangle;
}
diff --git a/vm/Native.h b/vm/Native.h
index f60ccce..eb2b84a 100644
--- a/vm/Native.h
+++ b/vm/Native.h
@@ -25,20 +25,20 @@
/*
* Method description; equivalent to a JNI struct.
*/
-typedef struct DalvikNativeMethod {
+struct DalvikNativeMethod {
const char* name;
const char* signature;
DalvikNativeFunc fnPtr;
-} DalvikNativeMethod;
+};
/*
* All methods for one class. The last "methodInfo" has a NULL "name".
*/
-typedef struct DalvikNativeClass {
+struct DalvikNativeClass {
const char* classDescriptor;
const DalvikNativeMethod* methodInfo;
u4 classDescriptorHash; /* initialized at runtime */
-} DalvikNativeClass;
+};
/* init/shutdown */
@@ -49,8 +49,8 @@
/*
* Convert argc/argv into a function call. This is platform-specific.
*/
-void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
- const u4* argv, const char* signature, void* func, JValue* pResult);
+extern "C" void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo,
+ int argc, const u4* argv, const char* signature, void* func, JValue* pResult);
/*
* Generate hints to speed native calls. This is platform specific.
diff --git a/vm/PointerSet.c b/vm/PointerSet.cpp
similarity index 100%
rename from vm/PointerSet.c
rename to vm/PointerSet.cpp
diff --git a/vm/PointerSet.h b/vm/PointerSet.h
index ffc0635..ddc5532 100644
--- a/vm/PointerSet.h
+++ b/vm/PointerSet.h
@@ -21,7 +21,6 @@
#define _DALVIK_POINTERSET
struct PointerSet; /* private */
-typedef struct PointerSet PointerSet;
/*
* Allocate a new PointerSet.
diff --git a/vm/Profile.c b/vm/Profile.cpp
similarity index 94%
rename from vm/Profile.c
rename to vm/Profile.cpp
index 6faf726..c80a150 100644
--- a/vm/Profile.c
+++ b/vm/Profile.cpp
@@ -137,7 +137,7 @@
/*
* Boot-time init.
*/
-bool dvmProfilingStartup(void)
+bool dvmProfilingStartup()
{
/*
* Initialize "dmtrace" method profiling.
@@ -189,7 +189,7 @@
/*
* Free up profiling resources.
*/
-void dvmProfilingShutdown(void)
+void dvmProfilingShutdown()
{
#ifdef UPDATE_MAGIC_PAGE
if (gDvm.emulatorTracePage != NULL)
@@ -201,8 +201,7 @@
/*
* Update the set of active profilers
*/
-static void updateActiveProfilers(InterpBreakFlags newBreak,
- ExecutionSubModes newMode, bool enable)
+static void updateActiveProfilers(ExecutionSubModes newMode, bool enable)
{
int oldValue, newValue;
@@ -218,7 +217,11 @@
&gDvm.activeProfilers) != 0);
// Tell the threads
- dvmUpdateAllInterpBreak(newBreak, newMode, enable);
+ if (enable) {
+ dvmEnableAllSubMode(newMode);
+ } else {
+ dvmDisableAllSubMode(newMode);
+ }
#if defined(WITH_JIT)
dvmCompilerUpdateGlobalState();
@@ -231,7 +234,7 @@
/*
* Reset the "cpuClockBase" field in all threads.
*/
-static void resetCpuClockBase(void)
+static void resetCpuClockBase()
{
Thread* thread;
@@ -344,7 +347,7 @@
* following to take a Thread* argument, and set the appropriate
* interpBreak flags only on the target thread.
*/
- updateActiveProfilers(kInterpNoBreak, kSubModeMethodTrace, true);
+ updateActiveProfilers(kSubModeMethodTrace, true);
LOGI("TRACE STARTED: '%s' %dKB\n", traceFileName, bufferSize / 1024);
/*
@@ -412,7 +415,7 @@
return;
fail:
- updateActiveProfilers(kInterpNoBreak, kSubModeMethodTrace, false);
+ updateActiveProfilers(kSubModeMethodTrace, false);
if (state->traceFile != NULL) {
fclose(state->traceFile);
state->traceFile = NULL;
@@ -453,7 +456,7 @@
* This value is going to vary depending on what else is going on in the
* system. When examined across several runs a pattern should emerge.
*/
-static u4 getClockOverhead(void)
+static u4 getClockOverhead()
{
u8 calStart, calElapsed;
int i;
@@ -477,7 +480,7 @@
/*
* Returns "true" if method tracing is currently active.
*/
-bool dvmIsMethodTraceActive(void)
+bool dvmIsMethodTraceActive()
{
const MethodTraceState* state = &gDvm.methodTrace;
return state->traceEnabled;
@@ -487,7 +490,7 @@
* Stop method tracing. We write the buffer to disk and generate a key
* file so we can interpret it.
*/
-void dvmMethodTraceStop(void)
+void dvmMethodTraceStop()
{
MethodTraceState* state = &gDvm.methodTrace;
u8 elapsed;
@@ -504,7 +507,7 @@
dvmUnlockMutex(&state->startStopLock);
return;
} else {
- updateActiveProfilers(kInterpNoBreak, kSubModeMethodTrace, false);
+ updateActiveProfilers(kSubModeMethodTrace, false);
}
/* compute elapsed time */
@@ -831,11 +834,11 @@
* The GC calls this when it's about to start. We add a marker to the
* trace output so the tool can exclude the GC cost from the results.
*/
-void dvmMethodTraceGCBegin(void)
+void dvmMethodTraceGCBegin()
{
TRACE_METHOD_ENTER(dvmThreadSelf(), gDvm.methodTraceGcMethod);
}
-void dvmMethodTraceGCEnd(void)
+void dvmMethodTraceGCEnd()
{
TRACE_METHOD_EXIT(dvmThreadSelf(), gDvm.methodTraceGcMethod);
}
@@ -843,11 +846,11 @@
/*
* The class loader calls this when it's loading or initializing a class.
*/
-void dvmMethodTraceClassPrepBegin(void)
+void dvmMethodTraceClassPrepBegin()
{
TRACE_METHOD_ENTER(dvmThreadSelf(), gDvm.methodTraceClassPrepMethod);
}
-void dvmMethodTraceClassPrepEnd(void)
+void dvmMethodTraceClassPrepEnd()
{
TRACE_METHOD_EXIT(dvmThreadSelf(), gDvm.methodTraceClassPrepMethod);
}
@@ -856,7 +859,7 @@
/*
* Enable emulator trace info.
*/
-void dvmEmulatorTraceStart(void)
+void dvmEmulatorTraceStart()
{
/* If we could not map the emulator trace page, then do not enable tracing */
if (gDvm.emulatorTracePage == NULL)
@@ -866,14 +869,13 @@
gDvm.emulatorTraceEnableCount++;
if (gDvm.emulatorTraceEnableCount == 1)
LOGD("--- emulator method traces enabled\n");
- updateActiveProfilers(kInterpEmulatorTraceBreak, kSubModeEmulatorTrace,
- true);
+ updateActiveProfilers(kSubModeEmulatorTrace, true);
}
/*
* Disable emulator trace info.
*/
-void dvmEmulatorTraceStop(void)
+void dvmEmulatorTraceStop()
{
if (gDvm.emulatorTraceEnableCount == 0) {
LOGE("ERROR: emulator tracing not enabled\n");
@@ -883,7 +885,7 @@
gDvm.emulatorTraceEnableCount--;
if (gDvm.emulatorTraceEnableCount == 0)
LOGD("--- emulator method traces disabled\n");
- updateActiveProfilers(kInterpEmulatorTraceBreak, kSubModeEmulatorTrace,
+ updateActiveProfilers(kSubModeEmulatorTrace,
(gDvm.emulatorTraceEnableCount != 0));
}
@@ -891,24 +893,24 @@
/*
* Start instruction counting.
*/
-void dvmStartInstructionCounting(void)
+void dvmStartInstructionCounting()
{
/* in theory we should make this an atomic inc; in practice not important */
gDvm.instructionCountEnableCount++;
- updateActiveProfilers(kInterpInstCountBreak, kSubModeInstCounting, true);
+ updateActiveProfilers(kSubModeInstCounting, true);
}
/*
* Stop instruction counting.
*/
-void dvmStopInstructionCounting(void)
+void dvmStopInstructionCounting()
{
if (gDvm.instructionCountEnableCount == 0) {
LOGE("ERROR: instruction counting not enabled\n");
dvmAbort();
}
gDvm.instructionCountEnableCount--;
- updateActiveProfilers(kInterpInstCountBreak, kSubModeInstCounting,
+ updateActiveProfilers(kSubModeInstCounting,
(gDvm.instructionCountEnableCount != 0));
}
@@ -917,7 +919,7 @@
* Start alloc counting. Note this doesn't affect the "active profilers"
* count, since the interpreter loop is not involved.
*/
-void dvmStartAllocCounting(void)
+void dvmStartAllocCounting()
{
gDvm.allocProf.enabled = true;
}
@@ -925,7 +927,7 @@
/*
* Stop alloc counting.
*/
-void dvmStopAllocCounting(void)
+void dvmStopAllocCounting()
{
gDvm.allocProf.enabled = false;
}
diff --git a/vm/Profile.h b/vm/Profile.h
index b821394..27d7c89 100644
--- a/vm/Profile.h
+++ b/vm/Profile.h
@@ -35,7 +35,7 @@
* Method trace state. This is currently global. In theory we could make
* most of this per-thread.
*/
-typedef struct MethodTraceState {
+struct MethodTraceState {
/* active state */
pthread_mutex_t startStopLock;
pthread_cond_t threadExitCond;
@@ -49,7 +49,7 @@
volatile int curOffset;
u8 startWhen;
int overflow;
-} MethodTraceState;
+};
/*
* Memory allocation profiler state. This is used both globally and
@@ -57,7 +57,7 @@
*
* If you add a field here, zero it out in dvmStartAllocCounting().
*/
-typedef struct AllocProfState {
+struct AllocProfState {
bool enabled; // is allocation tracking enabled?
int allocCount; // #of objects allocated
@@ -73,7 +73,7 @@
int classInitCount; // #of initialized classes
u8 classInitTime; // cumulative time spent in class init (nsec)
-} AllocProfState;
+};
/*
@@ -137,9 +137,9 @@
void dvmMethodTraceClassPrepBegin(void);
void dvmMethodTraceClassPrepEnd(void);
-void dvmFastMethodTraceEnter(const Method* method, struct Thread* self);
-void dvmFastMethodTraceExit(struct Thread* self);
-void dvmFastNativeMethodTraceExit(const Method* method, struct Thread* self);
+extern "C" void dvmFastMethodTraceEnter(const Method* method, struct Thread* self);
+extern "C" void dvmFastMethodTraceExit(struct Thread* self);
+extern "C" void dvmFastNativeMethodTraceExit(const Method* method, struct Thread* self);
/*
* Start/stop alloc counting.
diff --git a/vm/Properties.c b/vm/Properties.cpp
similarity index 93%
rename from vm/Properties.c
rename to vm/Properties.cpp
index 00d4b07..62d45db 100644
--- a/vm/Properties.c
+++ b/vm/Properties.cpp
@@ -21,7 +21,7 @@
#include <cutils/array.h>
#include <stdlib.h>
-bool dvmPropertiesStartup(void)
+bool dvmPropertiesStartup()
{
gDvm.properties = arrayCreate();
if (gDvm.properties == NULL) {
@@ -30,7 +30,7 @@
return true;
}
-void dvmPropertiesShutdown(void)
+void dvmPropertiesShutdown()
{
size_t size = arraySize(gDvm.properties);
size_t i;
diff --git a/vm/RawDexFile.c b/vm/RawDexFile.cpp
similarity index 100%
rename from vm/RawDexFile.c
rename to vm/RawDexFile.cpp
diff --git a/vm/RawDexFile.h b/vm/RawDexFile.h
index cbcb3b6..ba777bb 100644
--- a/vm/RawDexFile.h
+++ b/vm/RawDexFile.h
@@ -25,10 +25,10 @@
* Structure representing a "raw" DEX file, in its unswapped unoptimized
* state.
*/
-typedef struct RawDexFile {
+struct RawDexFile {
char* cacheFileName;
DvmDex* pDvmDex;
-} RawDexFile;
+};
/*
* Open a raw ".dex" file, optimize it, and load it.
diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.cpp
similarity index 98%
rename from vm/ReferenceTable.c
rename to vm/ReferenceTable.cpp
index 0e70c0d..adf3383 100644
--- a/vm/ReferenceTable.c
+++ b/vm/ReferenceTable.cpp
@@ -157,7 +157,7 @@
static size_t getElementCount(const Object* obj)
{
const ArrayObject* arrayObj = (ArrayObject*) obj;
- if (arrayObj == NULL || arrayObj->obj.clazz == NULL || !dvmIsArray(arrayObj))
+ if (arrayObj == NULL || arrayObj->clazz == NULL || !dvmIsArray(arrayObj))
return 0;
return arrayObj->length;
}
@@ -264,7 +264,7 @@
/* should only be possible right after a plain dvmMalloc() */
size_t size = dvmObjectSizeInHeap(ref);
LOGW("%5d: %p cls=(raw) (%zd bytes)\n", idx, ref, size);
- } else if (ref->clazz == gDvm.classJavaLangClass) {
+ } else if (dvmIsClassObject(ref)) {
ClassObject* clazz = (ClassObject*) ref;
LOGW("%5d: %p cls=%s '%s'\n", idx, ref, ref->clazz->descriptor,
clazz->descriptor);
diff --git a/vm/ReferenceTable.h b/vm/ReferenceTable.h
index f434f55..db2389f 100644
--- a/vm/ReferenceTable.h
+++ b/vm/ReferenceTable.h
@@ -16,7 +16,7 @@
/*
* Maintain a table of references. Used for internal local references,
- * JNI locals, JNI globals, and GC heap references.
+ * JNI monitor references, and JNI pinned array references.
*
* None of the table functions are synchronized.
*/
@@ -36,13 +36,13 @@
* (This structure is still somewhat transparent; direct access to
* table/nextEntry is allowed.)
*/
-typedef struct ReferenceTable {
+struct ReferenceTable {
Object** nextEntry; /* top of the list */
Object** table; /* bottom of the list */
int allocEntries; /* #of entries we have space for */
int maxEntries; /* max #of entries allowed */
-} ReferenceTable;
+};
/*
* Initialize a ReferenceTable.
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.cpp
similarity index 96%
rename from vm/SignalCatcher.c
rename to vm/SignalCatcher.cpp
index c8f9833..a24764a 100644
--- a/vm/SignalCatcher.c
+++ b/vm/SignalCatcher.cpp
@@ -39,7 +39,7 @@
*
* Returns immediately.
*/
-bool dvmSignalCatcherStartup(void)
+bool dvmSignalCatcherStartup()
{
gDvm.haltSignalCatcher = false;
@@ -56,7 +56,7 @@
* Since we know the thread is just sitting around waiting for signals
* to arrive, send it one.
*/
-void dvmSignalCatcherShutdown(void)
+void dvmSignalCatcherShutdown()
{
gDvm.haltSignalCatcher = true;
if (gDvm.signalCatcherHandle == 0) // not started yet
@@ -138,7 +138,7 @@
*
* If JIT tuning is compiled in, dump compiler stats as well.
*/
-static void handleSigQuit(void)
+static void handleSigQuit()
{
char* traceBuf = NULL;
size_t traceLen;
@@ -178,7 +178,7 @@
* We don't know how long it will take to do the disk I/O, so put us
* into VMWAIT for the duration.
*/
- int oldStatus = dvmChangeStatus(dvmThreadSelf(), THREAD_VMWAIT);
+ ThreadStatus oldStatus = dvmChangeStatus(dvmThreadSelf(), THREAD_VMWAIT);
/*
* Open the stack trace output file, creating it if necessary. It
@@ -208,7 +208,7 @@
/*
* Respond to a SIGUSR1 by forcing a GC.
*/
-static void handleSigUsr1(void)
+static void handleSigUsr1()
{
LOGI("SIGUSR1 forcing GC (no HPROF)\n");
dvmCollectGarbage();
@@ -227,7 +227,7 @@
* Respond to a SIGUSR2 by dumping some JIT stats and possibly resetting
* the code cache.
*/
-static void handleSigUsr2(void)
+static void handleSigUsr2()
{
static int codeCacheResetCount = 0;
gDvmJit.receivedSIGUSR2 ^= true;
diff --git a/vm/StdioConverter.c b/vm/StdioConverter.cpp
similarity index 97%
rename from vm/StdioConverter.c
rename to vm/StdioConverter.cpp
index 6a4d845..a98d473 100644
--- a/vm/StdioConverter.c
+++ b/vm/StdioConverter.cpp
@@ -30,20 +30,20 @@
/*
* Hold our replacement stdout/stderr.
*/
-typedef struct StdPipes {
+struct StdPipes {
int stdoutPipe[2];
int stderrPipe[2];
-} StdPipes;
+};
#define kMaxLine 512
/*
* Hold some data.
*/
-typedef struct BufferedData {
+struct BufferedData {
char buf[kMaxLine+1];
int count;
-} BufferedData;
+};
// fwd
static void* stdioConverterThreadStart(void* arg);
@@ -55,7 +55,7 @@
*
* Returns immediately.
*/
-bool dvmStdioConverterStartup(void)
+bool dvmStdioConverterStartup()
{
StdPipes* pipeStorage;
@@ -122,7 +122,7 @@
* Since we know the thread is just sitting around waiting for something
* to arrive on stdout, print something.
*/
-void dvmStdioConverterShutdown(void)
+void dvmStdioConverterShutdown()
{
gDvm.haltStdioConverter = true;
if (gDvm.stdioConverterHandle == 0) // not started, or still starting
diff --git a/vm/Sync.c b/vm/Sync.cpp
similarity index 98%
rename from vm/Sync.c
rename to vm/Sync.cpp
index 387cdd1..f3781b3 100644
--- a/vm/Sync.c
+++ b/vm/Sync.cpp
@@ -84,7 +84,7 @@
* Who last acquired this monitor, when lock sampling is enabled.
* Even when enabled, ownerFileName may be NULL.
*/
- char* ownerFileName;
+ const char* ownerFileName;
u4 ownerLineNumber;
};
@@ -120,7 +120,7 @@
/*
* Free the monitor list. Only used when shutting the VM down.
*/
-void dvmFreeMonitorList(void)
+void dvmFreeMonitorList()
{
Monitor* mon;
Monitor* nextMon;
@@ -276,7 +276,7 @@
size_t len;
int fd;
- saveArea = SAVEAREA_FROM_FP(self->curFrame);
+ saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
meth = saveArea->method;
cp = eventBuffer;
@@ -386,9 +386,10 @@
const StackSaveArea *saveArea;
const Method *meth;
mon->ownerLineNumber = 0;
- if (self->curFrame == NULL) {
+ if (self->interpSave.curFrame == NULL) {
mon->ownerFileName = "no_frame";
- } else if ((saveArea = SAVEAREA_FROM_FP(self->curFrame)) == NULL) {
+ } else if ((saveArea =
+ SAVEAREA_FROM_FP(self->interpSave.curFrame)) == NULL) {
mon->ownerFileName = "no_save_area";
} else if ((meth = saveArea->method) == NULL) {
mon->ownerFileName = "no_method";
@@ -617,7 +618,7 @@
bool wasInterrupted = false;
bool timed;
int ret;
- char *savedFileName;
+ const char *savedFileName;
u4 savedLineNumber;
assert(self != NULL);
@@ -1250,7 +1251,7 @@
* relocated by the collector. Use the value of the naturally
* aligned word following the instance data.
*/
- assert(obj->clazz != gDvm.classJavaLangClass);
+ assert(!dvmIsClassObject(obj));
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
size = dvmArrayObjectSize((ArrayObject *)obj);
size = (size + 2) & ~2;
@@ -1281,10 +1282,9 @@
* If the lock is thin assume it is unowned. We simulate
* an acquire, update, and release with a single CAS.
*/
- lock = DVM_LOCK_INITIAL_THIN_VALUE;
- lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
+ lock = (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
if (android_atomic_acquire_cas(
- (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
+ 0,
(int32_t)lock,
(int32_t *)lw) == 0) {
/*
diff --git a/vm/Sync.h b/vm/Sync.h
index 520366e..14b34fd 100644
--- a/vm/Sync.h
+++ b/vm/Sync.h
@@ -66,16 +66,6 @@
struct Object;
struct Monitor;
struct Thread;
-typedef struct Monitor Monitor;
-
-/*
- * Initialize a Lock to the proper starting value.
- * This is necessary for thin locking.
- */
-#define DVM_LOCK_INITIAL_THIN_VALUE (0)
-
-#define DVM_LOCK_INIT(lock) \
- do { *(lock) = DVM_LOCK_INITIAL_THIN_VALUE; } while (0)
/*
* Returns true if the lock has been fattened.
@@ -85,25 +75,25 @@
/*
* Acquire the object's monitor.
*/
-void dvmLockObject(struct Thread* self, struct Object* obj);
+extern "C" void dvmLockObject(Thread* self, Object* obj);
/* Returns true if the unlock succeeded.
* If the unlock failed, an exception will be pending.
*/
-bool dvmUnlockObject(struct Thread* self, struct Object* obj);
+extern "C" bool dvmUnlockObject(Thread* self, Object* obj);
/*
* Implementations of some java/lang/Object calls.
*/
-void dvmObjectWait(struct Thread* self, struct Object* obj,
+void dvmObjectWait(Thread* self, Object* obj,
s8 timeout, s4 nanos, bool interruptShouldThrow);
-void dvmObjectNotify(struct Thread* self, struct Object* obj);
-void dvmObjectNotifyAll(struct Thread* self, struct Object* obj);
+void dvmObjectNotify(Thread* self, Object* obj);
+void dvmObjectNotifyAll(Thread* self, Object* obj);
/*
* Implementation of System.identityHashCode().
*/
-u4 dvmIdentityHashCode(struct Object* obj);
+u4 dvmIdentityHashCode(Object* obj);
/*
* Implementation of Thread.sleep().
@@ -115,10 +105,10 @@
*
* Interrupt a thread. If it's waiting on a monitor, wake it up.
*/
-void dvmThreadInterrupt(struct Thread* thread);
+void dvmThreadInterrupt(Thread* thread);
/* create a new Monitor struct */
-Monitor* dvmCreateMonitor(struct Object* obj);
+Monitor* dvmCreateMonitor(Object* obj);
/*
* Frees unmarked monitors from the monitor list. The given callback
@@ -136,7 +126,7 @@
* Returns NULL if "mon" is NULL or the monitor is not part of an object
* (which should only happen for Thread.sleep() in the current implementation).
*/
-struct Object* dvmGetMonitorObject(Monitor* mon);
+Object* dvmGetMonitorObject(Monitor* mon);
/*
* Get the thread that holds the lock on the specified object. The
@@ -144,12 +134,12 @@
*
* The caller must lock the thread list before calling here.
*/
-struct Thread* dvmGetObjectLockHolder(struct Object* obj);
+Thread* dvmGetObjectLockHolder(Object* obj);
/*
* Checks whether the object is held by the specified thread.
*/
-bool dvmHoldsLock(struct Thread* thread, struct Object* obj);
+bool dvmHoldsLock(Thread* thread, Object* obj);
/*
* Relative timed wait on condition
diff --git a/vm/Thread.c b/vm/Thread.cpp
similarity index 96%
rename from vm/Thread.c
rename to vm/Thread.cpp
index 087c2e0..6c3f27e 100644
--- a/vm/Thread.c
+++ b/vm/Thread.cpp
@@ -240,14 +240,14 @@
static void threadExitUncaughtException(Thread* thread, Object* group);
static void threadExitCheck(void* arg);
static void waitForThreadSuspend(Thread* self, Thread* thread);
-static int getThreadPriorityFromSystem(void);
+static int getThreadPriorityFromSystem();
/*
* Initialize thread list and main thread's environment. We need to set
* up some basic stuff so that dvmThreadSelf() will work when we start
* loading classes (e.g. to check for exceptions).
*/
-bool dvmThreadStartup(void)
+bool dvmThreadStartup()
{
Thread* thread;
@@ -305,7 +305,7 @@
/*
* All threads should be stopped by now. Clean up some thread globals.
*/
-void dvmThreadShutdown(void)
+void dvmThreadShutdown()
{
if (gDvm.threadList != NULL) {
/*
@@ -329,7 +329,7 @@
/*
* Grab the suspend count global lock.
*/
-static inline void lockThreadSuspendCount(void)
+static inline void lockThreadSuspendCount()
{
/*
* Don't try to change to VMWAIT here. When we change back to RUNNING
@@ -345,7 +345,7 @@
/*
* Release the suspend count global lock.
*/
-static inline void unlockThreadSuspendCount(void)
+static inline void unlockThreadSuspendCount()
{
dvmUnlockMutex(&gDvm.threadSuspendCountLock);
}
@@ -384,8 +384,7 @@
self->status = THREAD_VMWAIT;
} else {
/* happens during VM shutdown */
- //LOGW("NULL self in dvmLockThreadList\n");
- oldStatus = -1; // shut up gcc
+ oldStatus = THREAD_UNDEFINED; // shut up gcc
}
dvmLockMutex(&gDvm.threadListLock);
@@ -400,7 +399,7 @@
* Returns "true" if we locked it. This is a "fast" mutex, so if the
* current thread holds the lock this will fail.
*/
-bool dvmTryLockThreadList(void)
+bool dvmTryLockThreadList()
{
return (dvmTryLockMutex(&gDvm.threadListLock) == 0);
}
@@ -408,7 +407,7 @@
/*
* Release the thread list global lock.
*/
-void dvmUnlockThreadList(void)
+void dvmUnlockThreadList()
{
dvmUnlockMutex(&gDvm.threadListLock);
}
@@ -503,7 +502,7 @@
/*
* Release the "thread suspend" lock.
*/
-static inline void unlockThreadSuspend(void)
+static inline void unlockThreadSuspend()
{
dvmUnlockMutex(&gDvm._threadSuspendLock);
}
@@ -529,7 +528,7 @@
* but not necessarily the main thread. It's likely, but not guaranteed,
* that the current thread has already been cleaned up.
*/
-void dvmSlayDaemons(void)
+void dvmSlayDaemons()
{
Thread* self = dvmThreadSelf(); // may be null
Thread* target;
@@ -557,7 +556,7 @@
}
char* threadName = dvmGetThreadName(target);
- LOGD("threadid=%d: suspending daemon id=%d name='%s'\n",
+ LOGV("threadid=%d: suspending daemon id=%d name='%s'\n",
threadId, target->threadId, threadName);
free(threadName);
@@ -618,7 +617,7 @@
}
if (allSuspended) {
- LOGD("threadid=%d: all daemons have suspended\n", threadId);
+ LOGV("threadid=%d: all daemons have suspended\n", threadId);
break;
} else {
if (!complained) {
@@ -679,7 +678,7 @@
* it. As part of doing so, we finish initializing Thread and ThreadGroup.
* This will execute some interpreted code (e.g. class initializers).
*/
-bool dvmPrepMainThread(void)
+bool dvmPrepMainThread()
{
Thread* thread;
Object* groupObj;
@@ -880,7 +879,7 @@
* where getpid() and gettid() sometimes agree and sometimes don't depending
* on your thread model (try "export LD_ASSUME_KERNEL=2.4.19").
*/
-pid_t dvmGetSysThreadId(void)
+pid_t dvmGetSysThreadId()
{
#ifdef HAVE_GETTID
return gettid();
@@ -1003,7 +1002,7 @@
/*
* Like pthread_self(), but on a Thread*.
*/
-Thread* dvmThreadSelf(void)
+Thread* dvmThreadSelf()
{
return (Thread*) pthread_getspecific(gDvm.pthreadKeySelf);
}
@@ -1111,7 +1110,6 @@
thread->threadId = num + 1;
assert(thread->threadId != 0);
- assert(thread->threadId != DVM_LOCK_INITIAL_THIN_VALUE);
}
/*
@@ -1159,7 +1157,7 @@
* Null out the "String[] args" argument.
*/
assert(gDvm.methDalvikSystemNativeStart_main->registersSize == 1);
- u4* framePtr = (u4*) thread->curFrame;
+ u4* framePtr = (u4*) thread->interpSave.curFrame;
framePtr[0] = 0;
return true;
@@ -1232,16 +1230,10 @@
*/
bool dvmCreateInterpThread(Object* threadObj, int reqStackSize)
{
- pthread_attr_t threadAttr;
- pthread_t threadHandle;
- Thread* self;
- Thread* newThread = NULL;
- Object* vmThreadObj = NULL;
- int stackSize;
-
assert(threadObj != NULL);
- self = dvmThreadSelf();
+ Thread* self = dvmThreadSelf();
+ int stackSize;
if (reqStackSize == 0)
stackSize = gDvm.stackSize;
else if (reqStackSize < kMinStackSize)
@@ -1251,6 +1243,7 @@
else
stackSize = reqStackSize;
+ pthread_attr_t threadAttr;
pthread_attr_init(&threadAttr);
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
@@ -1258,13 +1251,16 @@
* To minimize the time spent in the critical section, we allocate the
* vmThread object here.
*/
- vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_DEFAULT);
+ Object* vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_DEFAULT);
if (vmThreadObj == NULL)
- goto fail;
+ return false;
- newThread = allocThread(stackSize);
- if (newThread == NULL)
- goto fail;
+ Thread* newThread = allocThread(stackSize);
+ if (newThread == NULL) {
+ dvmReleaseTrackedAlloc(vmThreadObj, NULL);
+ return false;
+ }
+
newThread->threadObj = threadObj;
assert(newThread->status == THREAD_INITIALIZING);
@@ -1282,7 +1278,8 @@
dvmUnlockThreadList();
dvmThrowIllegalThreadStateException(
"thread has already been started");
- goto fail;
+ freeThread(newThread);
+ dvmReleaseTrackedAlloc(vmThreadObj, NULL);
}
/*
@@ -1302,9 +1299,10 @@
dvmUnlockThreadList();
ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
+ pthread_t threadHandle;
int cc = pthread_create(&threadHandle, &threadAttr, interpThreadStart,
- newThread);
- oldStatus = dvmChangeStatus(self, oldStatus);
+ newThread);
+ dvmChangeStatus(self, oldStatus);
if (cc != 0) {
/*
@@ -1620,7 +1618,7 @@
/* Remove this thread's suspendCount from global suspendCount sum */
lockThreadSuspendCount();
- dvmAddToSuspendCounts(self, -self->interpBreak.ctl.suspendCount, 0);
+ dvmAddToSuspendCounts(self, -self->suspendCount, 0);
unlockThreadSuspendCount();
}
@@ -1721,7 +1719,7 @@
jniArgs.version = JNI_VERSION_1_2;
jniArgs.name = pArgs->name;
- jniArgs.group = pArgs->group;
+ jniArgs.group = reinterpret_cast<jobject>(pArgs->group);
setThreadName(pArgs->name);
@@ -1995,7 +1993,7 @@
* dedicated ThreadObject class for java/lang/Thread and moving all of our
* state into that.
*/
-void dvmDetachCurrentThread(void)
+void dvmDetachCurrentThread()
{
Thread* self = dvmThreadSelf();
Object* vmThread;
@@ -2009,14 +2007,14 @@
* zero, while a JNI-attached thread will have the synthetic "stack
* starter" native method at the top.
*/
- int curDepth = dvmComputeExactFrameDepth(self->curFrame);
+ int curDepth = dvmComputeExactFrameDepth(self->interpSave.curFrame);
if (curDepth != 0) {
bool topIsNative = false;
if (curDepth == 1) {
/* not expecting a lingering break frame; just look at curFrame */
- assert(!dvmIsBreakFrame((u4*)self->curFrame));
- StackSaveArea* ssa = SAVEAREA_FROM_FP(self->curFrame);
+ assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
+ StackSaveArea* ssa = SAVEAREA_FROM_FP(self->interpSave.curFrame);
if (dvmIsNativeMethod(ssa->method))
topIsNative = true;
}
@@ -2096,7 +2094,9 @@
* parallel with us from here out. It's important to do this if
* profiling is enabled, since we can wait indefinitely.
*/
- android_atomic_release_store(THREAD_VMWAIT, &self->status);
+ volatile void* raw = reinterpret_cast<volatile void*>(&self->status);
+ volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw);
+ android_atomic_release_store(THREAD_VMWAIT, addr);
/*
* If we're doing method trace profiling, we don't want threads to exit,
@@ -2187,7 +2187,7 @@
dvmAddToSuspendCounts(thread, 1, 1);
LOG_THREAD("threadid=%d: suspend++, now=%d\n",
- thread->threadId, thread->interpBreak.ctl.suspendCount);
+ thread->threadId, thread->suspendCount);
unlockThreadSuspendCount();
waitForThreadSuspend(dvmThreadSelf(), thread);
@@ -2211,7 +2211,7 @@
//assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
lockThreadSuspendCount();
- if (thread->interpBreak.ctl.suspendCount > 0) {
+ if (thread->suspendCount > 0) {
dvmAddToSuspendCounts(thread, -1, -1);
} else {
LOG_THREAD("threadid=%d: suspendCount already zero\n",
@@ -2219,9 +2219,9 @@
}
LOG_THREAD("threadid=%d: suspend--, now=%d\n",
- thread->threadId, thread->interpBreak.ctl.suspendCount);
+ thread->threadId, thread->suspendCount);
- if (thread->interpBreak.ctl.suspendCount == 0) {
+ if (thread->suspendCount == 0) {
dvmBroadcastCond(&gDvm.threadSuspendCountCond);
}
@@ -2253,7 +2253,7 @@
/*
* Suspend ourselves.
*/
- assert(self->interpBreak.ctl.suspendCount > 0);
+ assert(self->suspendCount > 0);
self->status = THREAD_SUSPENDED;
LOG_THREAD("threadid=%d: self-suspending (dbg)\n", self->threadId);
@@ -2270,10 +2270,10 @@
dvmJdwpClearWaitForEventThread(gDvm.jdwpState);
}
- while (self->interpBreak.ctl.suspendCount != 0) {
+ while (self->suspendCount != 0) {
dvmWaitCond(&gDvm.threadSuspendCountCond,
&gDvm.threadSuspendCountLock);
- if (self->interpBreak.ctl.suspendCount != 0) {
+ if (self->suspendCount != 0) {
/*
* The condition was signaled but we're still suspended. This
* can happen if the debugger lets go while a SIGQUIT thread
@@ -2281,12 +2281,10 @@
* just long enough to try to grab the thread-suspend lock).
*/
LOGD("threadid=%d: still suspended after undo (sc=%d dc=%d)\n",
- self->threadId, self->interpBreak.ctl.suspendCount,
- self->interpBreak.ctl.dbgSuspendCount);
+ self->threadId, self->suspendCount, self->dbgSuspendCount);
}
}
- assert(self->interpBreak.ctl.suspendCount == 0 &&
- self->interpBreak.ctl.dbgSuspendCount == 0);
+ assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
self->status = THREAD_RUNNING;
LOG_THREAD("threadid=%d: self-reviving (dbg), status=%d\n",
self->threadId, self->status);
@@ -2562,7 +2560,7 @@
* This can happen when a couple of threads have simultaneous events
* of interest to the debugger.
*/
- //assert(self->interpBreak.ctl.suspendCount == 0);
+ //assert(self->suspendCount == 0);
/*
* Increment everybody's suspend count (except our own).
@@ -2613,10 +2611,8 @@
waitForThreadSuspend(self, thread);
LOG_THREAD("threadid=%d: threadid=%d status=%d sc=%d dc=%d\n",
- self->threadId,
- thread->threadId, thread->status,
- thread->interpBreak.ctl.suspendCount,
- thread->interpBreak.ctl.dbgSuspendCount);
+ self->threadId, thread->threadId, thread->status,
+ thread->suspendCount, thread->dbgSuspendCount);
}
dvmUnlockThreadList();
@@ -2657,7 +2653,7 @@
continue;
}
- if (thread->interpBreak.ctl.suspendCount > 0) {
+ if (thread->suspendCount > 0) {
dvmAddToSuspendCounts(thread, -1,
(why == SUSPEND_FOR_DEBUG ||
why == SUSPEND_FOR_DEBUG_EVENT)
@@ -2723,7 +2719,7 @@
* Undo any debugger suspensions. This is called when the debugger
* disconnects.
*/
-void dvmUndoDebuggerSuspensions(void)
+void dvmUndoDebuggerSuspensions()
{
Thread* self = dvmThreadSelf();
Thread* thread;
@@ -2745,15 +2741,13 @@
/* debugger events don't suspend JDWP thread */
if (thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState)) {
- assert(thread->interpBreak.ctl.dbgSuspendCount == 0);
+ assert(thread->dbgSuspendCount == 0);
continue;
}
- assert(thread->interpBreak.ctl.suspendCount >=
- thread->interpBreak.ctl.dbgSuspendCount);
- dvmAddToSuspendCounts(thread,
- -thread->interpBreak.ctl.dbgSuspendCount,
- -thread->interpBreak.ctl.dbgSuspendCount);
+ assert(thread->suspendCount >= thread->dbgSuspendCount);
+ dvmAddToSuspendCounts(thread, -thread->dbgSuspendCount,
+ -thread->dbgSuspendCount);
}
unlockThreadSuspendCount();
dvmUnlockThreadList();
@@ -2798,7 +2792,7 @@
* we hold suspendCountLock).
*/
- return (thread->interpBreak.ctl.suspendCount != 0 &&
+ return (thread->suspendCount != 0 &&
thread->status != THREAD_RUNNING);
}
@@ -2843,21 +2837,21 @@
static bool fullSuspendCheck(Thread* self)
{
assert(self != NULL);
- assert(self->interpBreak.ctl.suspendCount >= 0);
+ assert(self->suspendCount >= 0);
/*
* Grab gDvm.threadSuspendCountLock. This gives us exclusive write
- * access to self->interpBreak.ctl.suspendCount.
+ * access to self->suspendCount.
*/
lockThreadSuspendCount(); /* grab gDvm.threadSuspendCountLock */
- bool needSuspend = (self->interpBreak.ctl.suspendCount != 0);
+ bool needSuspend = (self->suspendCount != 0);
if (needSuspend) {
LOG_THREAD("threadid=%d: self-suspending\n", self->threadId);
ThreadStatus oldStatus = self->status; /* should be RUNNING */
self->status = THREAD_SUSPENDED;
- while (self->interpBreak.ctl.suspendCount != 0) {
+ while (self->suspendCount != 0) {
/*
* Wait for wakeup signal, releasing lock. The act of releasing
* and re-acquiring the lock provides the memory barriers we
@@ -2866,8 +2860,7 @@
dvmWaitCond(&gDvm.threadSuspendCountCond,
&gDvm.threadSuspendCountLock);
}
- assert(self->interpBreak.ctl.suspendCount == 0 &&
- self->interpBreak.ctl.dbgSuspendCount == 0);
+ assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
self->status = oldStatus;
LOG_THREAD("threadid=%d: self-reviving, status=%d\n",
self->threadId, self->status);
@@ -2885,7 +2878,7 @@
bool dvmCheckSuspendPending(Thread* self)
{
assert(self != NULL);
- if (self->interpBreak.ctl.suspendCount == 0) {
+ if (self->suspendCount == 0) {
return false;
} else {
return fullSuspendCheck(self);
@@ -2964,8 +2957,10 @@
* the thread is supposed to be suspended. This is possibly faster
* on SMP and slightly more correct, but less convenient.
*/
- android_atomic_acquire_store(newStatus, &self->status);
- if (self->interpBreak.ctl.suspendCount != 0) {
+ volatile void* raw = reinterpret_cast<volatile void*>(&self->status);
+ volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw);
+ android_atomic_acquire_store(newStatus, addr);
+ if (self->suspendCount != 0) {
fullSuspendCheck(self);
}
} else {
@@ -2977,7 +2972,9 @@
* will be observed before the state change.
*/
assert(newStatus != THREAD_SUSPENDED);
- android_atomic_release_store(newStatus, &self->status);
+ volatile void* raw = reinterpret_cast<volatile void*>(&self->status);
+ volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw);
+ android_atomic_release_store(newStatus, addr);
}
return oldStatus;
@@ -3008,11 +3005,11 @@
return groupObj;
}
-Object* dvmGetSystemThreadGroup(void)
+Object* dvmGetSystemThreadGroup()
{
return getStaticThreadGroup("mSystem");
}
-Object* dvmGetMainThreadGroup(void)
+Object* dvmGetMainThreadGroup()
{
return getStaticThreadGroup("mMain");
}
@@ -3141,7 +3138,7 @@
*
* Returns a value from 1 to 10 (compatible with java.lang.Thread values).
*/
-static int getThreadPriorityFromSystem(void)
+static int getThreadPriorityFromSystem()
{
int i, sysprio, jprio;
@@ -3374,8 +3371,8 @@
);
dvmPrintDebugMessage(target,
" | group=\"%s\" sCount=%d dsCount=%d obj=%p self=%p\n",
- groupName, thread->interpBreak.ctl.suspendCount,
- thread->interpBreak.ctl.dbgSuspendCount, thread->threadObj, thread);
+ groupName, thread->suspendCount, thread->dbgSuspendCount,
+ thread->threadObj, thread);
dvmPrintDebugMessage(target,
" | sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d\n",
thread->systemTid, getpriority(PRIO_PROCESS, thread->systemTid),
diff --git a/vm/Thread.h b/vm/Thread.h
index d84682f..57ae24f 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -26,7 +26,6 @@
#include <errno.h>
#include <cutils/sched_policy.h>
-
#if defined(CHECK_MUTEX) && !defined(__USE_UNIX98)
/* glibc lacks this unless you #define __USE_UNIX98 */
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
@@ -40,7 +39,7 @@
*
* Note that "suspended" is orthogonal to these values (so says JDWP).
*/
-typedef enum ThreadStatus {
+enum ThreadStatus {
THREAD_UNDEFINED = -1, /* makes enum compatible with int32_t */
/* these match up with JDWP values */
@@ -55,7 +54,7 @@
THREAD_NATIVE = 7, /* off in a JNI native method */
THREAD_VMWAIT = 8, /* waiting on a VM resource */
THREAD_SUSPENDED = 9, /* suspended, usually by GC or debugger */
-} ThreadStatus;
+};
/* thread priorities, from java.lang.Thread */
enum {
@@ -71,7 +70,7 @@
void dvmSlayDaemons(void);
-#define kJniLocalRefMin 32
+#define kJniLocalRefMin 64
#define kJniLocalRefMax 512 /* arbitrary; should be plenty */
#define kInternalRefDefault 32 /* equally arbitrary */
#define kInternalRefMax 4096 /* mainly a sanity check */
@@ -84,27 +83,26 @@
* Interpreter control struction. Packed into a long long to enable
* atomic updates.
*/
-typedef union InterpBreak {
+union InterpBreak {
volatile int64_t all;
struct {
+ uint16_t subMode;
uint8_t breakFlags;
- uint8_t subMode;
- int8_t suspendCount;
- int8_t dbgSuspendCount;
+ int8_t unused; /* for future expansion */
#ifndef DVM_NO_ASM_INTERP
void* curHandlerTable;
#else
void* unused;
#endif
} ctl;
-} InterpBreak;
+};
/*
* Our per-thread data.
*
* These are allocated on the system heap.
*/
-typedef struct Thread {
+struct Thread {
/*
* Interpreter state which must be preserved across nested
* interpreter invocations (via JNI callbacks). Must be the first
@@ -122,29 +120,14 @@
*/
JValue retval;
- u1* cardTable;
-
- /* current limit of stack; flexes for StackOverflowError */
- const u1* interpStackEnd;
-
- /* FP of bottom-most (currently executing) stack frame on interp stack */
- void* curFrame;
- /* current exception, or NULL if nothing pending */
- Object* exception;
-
- bool debugIsMethodEntry;
- /* interpreter stack size; our stacks are fixed-length */
- int interpStackSize;
- bool stackOverflowed;
-
- /* thread handle, as reported by pthread_self() */
- pthread_t handle;
-
/*
* interpBreak contains info about the interpreter mode, as well as
* a count of the number of times the thread has been suspended. When
* the count drops to zero, the thread resumes.
- *
+ */
+ InterpBreak interpBreak;
+
+ /*
* "dbgSuspendCount" is the portion of the suspend count that the
* debugger is responsible for. This has to be tracked separately so
* that we can recover correctly if the debugger abruptly disconnects
@@ -157,8 +140,27 @@
* Note the non-debug component will rarely be other than 1 or 0 -- (not
* sure it's even possible with the way mutexes are currently used.)
*/
- InterpBreak interpBreak;
+ int suspendCount;
+ int dbgSuspendCount;
+
+ u1* cardTable;
+
+ /* current limit of stack; flexes for StackOverflowError */
+ const u1* interpStackEnd;
+
+ /* FP of bottom-most (currently executing) stack frame on interp stack */
+ void* XcurFrame;
+ /* current exception, or NULL if nothing pending */
+ Object* exception;
+
+ bool debugIsMethodEntry;
+ /* interpreter stack size; our stacks are fixed-length */
+ int interpStackSize;
+ bool stackOverflowed;
+
+ /* thread handle, as reported by pthread_self() */
+ pthread_t handle;
/* Assembly interpreter handler tables */
#ifndef DVM_NO_ASM_INTERP
@@ -302,13 +304,13 @@
pthread_mutex_t callbackMutex;
SafePointCallback callback;
void* callbackArg;
-} Thread;
+};
/* start point for an internal thread; mimics pthread args */
typedef void* (*InternalThreadStart)(void* arg);
/* args for internal thread creation */
-typedef struct InternalStartArgs {
+struct InternalStartArgs {
/* inputs */
InternalThreadStart func;
void* funcArg;
@@ -318,7 +320,7 @@
/* result */
volatile Thread** pThread;
volatile int* pCreateStatus;
-} InternalStartArgs;
+};
/* finish init */
bool dvmPrepMainForJni(JNIEnv* pEnv);
@@ -344,7 +346,7 @@
/*
* Thread suspend/resume, used by the GC and debugger.
*/
-typedef enum SuspendCause {
+enum SuspendCause {
SUSPEND_NOT = 0,
SUSPEND_FOR_GC,
SUSPEND_FOR_DEBUG,
@@ -359,7 +361,7 @@
SUSPEND_FOR_CC_RESET, // code-cache reset
SUSPEND_FOR_REFRESH, // Reload data cached in interpState
#endif
-} SuspendCause;
+};
void dvmSuspendThread(Thread* thread);
void dvmSuspendSelf(bool jdwpActivity);
void dvmResumeThread(Thread* thread);
@@ -381,14 +383,14 @@
* Check to see if we should be suspended now. If so, suspend ourselves
* by sleeping on a condition variable.
*/
-bool dvmCheckSuspendPending(Thread* self);
+extern "C" bool dvmCheckSuspendPending(Thread* self);
/*
* Fast test for use in the interpreter. Returns "true" if our suspend
* count is nonzero.
*/
INLINE bool dvmCheckSuspendQuick(Thread* self) {
- return (self->interpBreak.ctl.breakFlags & kInterpSuspendBreak);
+ return (self->interpBreak.ctl.subMode & kSubModeSuspendPending);
}
/*
diff --git a/vm/UtfString.c b/vm/UtfString.cpp
similarity index 90%
rename from vm/UtfString.c
rename to vm/UtfString.cpp
index 58545cd..17ce40a 100644
--- a/vm/UtfString.c
+++ b/vm/UtfString.cpp
@@ -104,9 +104,10 @@
* (If this needs optimizing, try: mask against 0xa0, shift right 5,
* get increment {1-3} from table of 8 values.)
*/
-int dvmUtf8Len(const char* utf8Str)
+size_t dvmUtf8Len(const char* utf8Str)
{
- int ic, len = 0;
+ size_t len = 0;
+ int ic;
while ((ic = *utf8Str++) != '\0') {
len++;
@@ -193,7 +194,7 @@
/*
* Use the java/lang/String.computeHashCode() algorithm.
*/
-static inline u4 dvmComputeUtf16Hash(const u2* utf16Str, int len)
+static inline u4 computeUtf16Hash(const u2* utf16Str, size_t len)
{
u4 hash = 0;
@@ -202,15 +203,13 @@
return hash;
}
+
u4 dvmComputeStringHash(const StringObject* strObj) {
- ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
+ const ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
STRING_FIELDOFF_VALUE);
- int offset, len;
-
- len = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_COUNT);
- offset = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_OFFSET);
-
- return dvmComputeUtf16Hash((u2*) chars->contents + offset, len);
+ int len = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_COUNT);
+ int offset = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_OFFSET);
+ return computeUtf16Hash((u2*)(void*)chars->contents + offset, len);
}
/*
@@ -235,7 +234,7 @@
* Returns NULL and throws an exception on failure.
*/
StringObject* dvmCreateStringFromCstrAndLength(const char* utf8Str,
- u4 utf16Length)
+ size_t utf16Length)
{
assert(utf8Str != NULL);
@@ -245,9 +244,9 @@
return NULL;
}
- dvmConvertUtf8ToUtf16((u2*) chars->contents, utf8Str);
+ dvmConvertUtf8ToUtf16((u2*)(void*)chars->contents, utf8Str);
- u4 hashCode = dvmComputeUtf16Hash((u2*) chars->contents, utf16Length);
+ u4 hashCode = computeUtf16Hash((u2*)(void*)chars->contents, utf16Length);
dvmSetFieldInt((Object*) newObj, STRING_FIELDOFF_HASHCODE, hashCode);
return newObj;
@@ -269,7 +268,7 @@
if (len > 0) memcpy(chars->contents, unichars, len * sizeof(u2));
- u4 hashCode = dvmComputeUtf16Hash((u2*) chars->contents, len);
+ u4 hashCode = computeUtf16Hash((u2*)(void*)chars->contents, len);
dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_HASHCODE, hashCode);
return newObj;
@@ -296,7 +295,7 @@
offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
STRING_FIELDOFF_VALUE);
- data = (const u2*) chars->contents + offset;
+ data = (const u2*)(void*)chars->contents + offset;
assert(offset + len <= (int) chars->length);
byteLen = utf16_utf8ByteLen(data, len);
@@ -341,7 +340,7 @@
offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
STRING_FIELDOFF_VALUE);
- data = (const u2*) chars->contents + offset;
+ data = (const u2*)(void*)chars->contents + offset;
assert(offset + len <= (int) chars->length);
return utf16_utf8ByteLen(data, len);
@@ -375,7 +374,7 @@
offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
STRING_FIELDOFF_VALUE);
- return (const u2*) chars->contents + offset;
+ return (const u2*)(void*)chars->contents + offset;
}
@@ -413,23 +412,24 @@
assert(offset1 + len1 <= (int) chars1->length);
assert(offset2 + len2 <= (int) chars2->length);
- return memcmp((const u2*) chars1->contents + offset1,
- (const u2*) chars2->contents + offset2,
+ return memcmp((const u2*)(void*)chars1->contents + offset1,
+ (const u2*)(void*)chars2->contents + offset2,
len1 * sizeof(u2));
}
-ArrayObject* dvmCreateStringArray(char** strings, size_t count)
+ArrayObject* dvmCreateStringArray(const char** strings, size_t length)
{
Thread* self = dvmThreadSelf();
/*
* Allocate an array to hold the String objects.
*/
+ ClassObject* elementClass =
+ dvmFindArrayClassForElement(gDvm.classJavaLangString);
ArrayObject* stringArray =
- dvmAllocObjectArray(gDvm.classJavaLangString, count, ALLOC_DEFAULT);
+ dvmAllocArrayByClass(elementClass, length, ALLOC_DEFAULT);
if (stringArray == NULL) {
/* probably OOM */
- LOGD("Failed allocating array of %d strings\n", count);
assert(dvmCheckException(self));
return NULL;
}
@@ -437,8 +437,7 @@
/*
* Create the individual String objects and add them to the array.
*/
- size_t i;
- for (i = 0; i < count; i++) {
+ for (size_t i = 0; i < length; i++) {
Object* str =
(Object*) dvmCreateStringFromCstr(strings[i]);
if (str == NULL) {
diff --git a/vm/UtfString.h b/vm/UtfString.h
index 793d8bc..b577d3a 100644
--- a/vm/UtfString.h
+++ b/vm/UtfString.h
@@ -63,7 +63,7 @@
*
* Returns NULL and throws an exception on failure.
*/
-ArrayObject* dvmCreateStringArray(char** strings, size_t count);
+ArrayObject* dvmCreateStringArray(const char** strings, size_t count);
/*
* Create a java/lang/String from a C string.
@@ -89,7 +89,7 @@
* Compute the number of characters in a "modified UTF-8" string. This will
* match the result from strlen() so long as there are no multi-byte chars.
*/
-int dvmUtf8Len(const char* utf8Str);
+size_t dvmUtf8Len(const char* utf8Str);
/*
* Convert a UTF-8 string to UTF-16. "utf16Str" must have enough room
diff --git a/vm/alloc/Alloc.c b/vm/alloc/Alloc.cpp
similarity index 83%
rename from vm/alloc/Alloc.c
rename to vm/alloc/Alloc.cpp
index 33f45e8..a77c770 100644
--- a/vm/alloc/Alloc.c
+++ b/vm/alloc/Alloc.cpp
@@ -27,7 +27,7 @@
* We're currently using a memory-mapped arena to keep things off of the
* main heap. This needs to be replaced with something real.
*/
-bool dvmGcStartup(void)
+bool dvmGcStartup()
{
dvmInitMutex(&gDvm.gcHeapLock);
@@ -38,7 +38,7 @@
* Post-zygote heap initialization, including starting
* the HeapWorker thread.
*/
-bool dvmGcStartupAfterZygote(void)
+bool dvmGcStartupAfterZygote()
{
return dvmHeapStartupAfterZygote();
}
@@ -46,7 +46,7 @@
/*
* Shutdown the threads internal to the garbage collector.
*/
-void dvmGcThreadShutdown(void)
+void dvmGcThreadShutdown()
{
dvmHeapThreadShutdown();
}
@@ -54,7 +54,7 @@
/*
* Shut the GC down.
*/
-void dvmGcShutdown(void)
+void dvmGcShutdown()
{
//TODO: grab and destroy the lock
dvmHeapShutdown();
@@ -63,49 +63,38 @@
/*
* Do any last-minute preparation before we call fork() for the first time.
*/
-bool dvmGcPreZygoteFork(void)
+bool dvmGcPreZygoteFork()
{
return dvmHeapSourceStartupBeforeFork();
}
-bool dvmGcStartupClasses(void)
+static bool startGcClass(const char* klassName, const char* methodName)
{
- {
- const char *klassName = "Ljava/lang/ref/ReferenceQueueThread;";
- ClassObject *klass = dvmFindSystemClass(klassName);
- if (klass == NULL) {
- return false;
- }
- const char *methodName = "startReferenceQueue";
- Method *method = dvmFindDirectMethodByDescriptor(klass, methodName, "()V");
- if (method == NULL) {
- return false;
- }
- Thread *self = dvmThreadSelf();
- assert(self != NULL);
- JValue unusedResult;
- dvmCallMethod(self, method, NULL, &unusedResult);
+ ClassObject *klass = dvmFindSystemClass(klassName);
+ if (klass == NULL) {
+ return false;
}
- {
- const char *klassName = "Ljava/lang/FinalizerThread;";
- ClassObject *klass = dvmFindSystemClass(klassName);
- if (klass == NULL) {
- return false;
- }
- const char *methodName = "startFinalizer";
- Method *method = dvmFindDirectMethodByDescriptor(klass, methodName, "()V");
- if (method == NULL) {
- return false;
- }
- Thread *self = dvmThreadSelf();
- assert(self != NULL);
- JValue unusedResult;
- dvmCallMethod(self, method, NULL, &unusedResult);
+ Method *method = dvmFindDirectMethodByDescriptor(klass, methodName, "()V");
+ if (method == NULL) {
+ return false;
}
-
+ Thread *self = dvmThreadSelf();
+ assert(self != NULL);
+ JValue unusedResult;
+ dvmCallMethod(self, method, NULL, &unusedResult);
return true;
}
+bool dvmGcStartupClasses()
+{
+ bool success =
+ startGcClass("Ljava/lang/ref/ReferenceQueueThread;",
+ "startReferenceQueue") &&
+ startGcClass("Ljava/lang/FinalizerThread;",
+ "startFinalizer");
+ return success;
+}
+
/*
* Create a "stock instance" of an exception class.
*/
@@ -166,7 +155,7 @@
* We can't do this during the initial startup because we need to execute
* the constructors.
*/
-bool dvmCreateStockExceptions(void)
+bool dvmCreateStockExceptions()
{
/*
* Pre-allocate some throwables. These need to be explicitly added
@@ -224,33 +213,30 @@
*/
Object* dvmCloneObject(Object* obj, int flags)
{
- ClassObject* clazz;
- Object* copy;
- size_t size;
-
assert(dvmIsValidObject(obj));
- clazz = obj->clazz;
+ ClassObject* clazz = obj->clazz;
/* Class.java shouldn't let us get here (java.lang.Class is final
* and does not implement Clonable), but make extra sure.
* A memcpy() clone will wreak havoc on a ClassObject's "innards".
*/
- assert(clazz != gDvm.classJavaLangClass);
+ assert(!dvmIsTheClassClass(clazz));
+ size_t size;
if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
size = dvmArrayObjectSize((ArrayObject *)obj);
} else {
size = clazz->objectSize;
}
- copy = (Object*)dvmMalloc(size, flags);
+ Object* copy = (Object*)dvmMalloc(size, flags);
if (copy == NULL)
return NULL;
- /* We assume that memcpy will copy obj by words. */
- memcpy(copy, obj, size);
- DVM_LOCK_INIT(©->lock);
- dvmWriteBarrierObject(copy);
+ DVM_OBJECT_INIT(copy, clazz);
+ size_t offset = sizeof(Object);
+ /* Copy instance data. We assume memcpy copies by words. */
+ memcpy((char*)copy + offset, (char*)obj + offset, size - offset);
/* Mark the clone as finalizable if appropriate. */
if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) {
@@ -318,7 +304,7 @@
/*
* Explicitly initiate garbage collection.
*/
-void dvmCollectGarbage(void)
+void dvmCollectGarbage()
{
if (gDvm.disableExplicitGc) {
return;
@@ -329,10 +315,10 @@
dvmUnlockHeap();
}
-typedef struct {
+struct CountContext {
const ClassObject *clazz;
size_t count;
-} CountContext;
+};
static void countInstancesOfClassCallback(void *ptr, void *arg)
{
diff --git a/vm/alloc/Alloc.h b/vm/alloc/Alloc.h
index aeba3f5..c215fc2 100644
--- a/vm/alloc/Alloc.h
+++ b/vm/alloc/Alloc.h
@@ -21,6 +21,13 @@
#include <stddef.h>
+/* flags for dvmMalloc */
+enum {
+ ALLOC_DEFAULT = 0x00,
+ ALLOC_DONT_TRACK = 0x01, /* don't add to internal tracking list */
+ ALLOC_NON_MOVING = 0x02,
+};
+
/*
* Initialization.
*/
@@ -54,13 +61,7 @@
*
* Returns NULL and throws an exception on failure.
*/
-Object* dvmAllocObject(ClassObject* clazz, int flags);
-
-/* flags for dvmMalloc */
-enum {
- ALLOC_DEFAULT = 0x00,
- ALLOC_DONT_TRACK = 0x01, /* don't add to internal tracking list */
-};
+extern "C" Object* dvmAllocObject(ClassObject* clazz, int flags);
/*
* Track an object reference that is currently only visible internally.
@@ -69,7 +70,7 @@
*
* The "self" argument is allowed as an optimization; it may be NULL.
*/
-void dvmAddTrackedAlloc(Object* obj, Thread* self);
+extern "C" void dvmAddTrackedAlloc(Object* obj, Thread* self);
/*
* Remove an object from the internal tracking list.
@@ -78,7 +79,7 @@
*
* The "self" argument is allowed as an optimization; it may be NULL.
*/
-void dvmReleaseTrackedAlloc(Object* obj, Thread* self);
+extern "C" void dvmReleaseTrackedAlloc(Object* obj, Thread* self);
/*
* Returns true iff <obj> points to a valid allocated object.
@@ -95,7 +96,7 @@
/*
* Make the object finalizable.
*/
-void dvmSetFinalizable(Object* obj);
+extern "C" void dvmSetFinalizable(Object* obj);
/*
* Determine the exact number of GC heap bytes used by an object. (Internal
diff --git a/vm/alloc/CardTable.c b/vm/alloc/CardTable.cpp
similarity index 97%
rename from vm/alloc/CardTable.c
rename to vm/alloc/CardTable.cpp
index 533d5bc..ec8ba97 100644
--- a/vm/alloc/CardTable.c
+++ b/vm/alloc/CardTable.cpp
@@ -152,8 +152,7 @@
u1 *limitCard = dvmCardFromAddr(limit);
u4 *bits = (u4*)h->modUnionTableBase;
u1 *heapBase = (u1*)dvmHeapSourceGetBase();
- u1 *card;
- for (card = baseCard; card < limitCard; ++card) {
+ for (u1 *card = baseCard; card < limitCard; ++card) {
if (*card == GC_CARD_CLEAN) {
continue;
}
@@ -168,14 +167,13 @@
}
}
-void dvmClearCardTable(void)
+void dvmClearCardTable()
{
uintptr_t base[HEAP_SOURCE_MAX_HEAP_COUNT];
uintptr_t limit[HEAP_SOURCE_MAX_HEAP_COUNT];
size_t numHeaps = dvmHeapSourceGetNumHeaps();
dvmHeapSourceGetRegions(base, NULL, limit, numHeaps);
- size_t i;
- for (i = 0; i < numHeaps; ++i) {
+ for (size_t i = 0; i < numHeaps; ++i) {
if (i != 0) {
moveCardsToModUnion((u1*)base[i], (u1*)limit[i]);
} else {
@@ -241,10 +239,10 @@
/*
* Context structure for verifying the card table.
*/
-typedef struct {
+struct WhiteReferenceCounter {
HeapBitmap *markBits;
size_t whiteRefs;
-} WhiteReferenceCounter;
+};
/*
* Visitor that counts white referents.
@@ -381,9 +379,7 @@
static bool isPushedOnMarkStack(const Object *obj)
{
GcMarkStack *stack = &gDvm.gcHeap->markContext.stack;
- const Object **ptr;
-
- for (ptr = stack->base; ptr < stack->top; ++ptr) {
+ for (const Object **ptr = stack->base; ptr < stack->top; ++ptr) {
if (*ptr == obj) {
return true;
}
@@ -427,7 +423,7 @@
/*
* Verifies that gray objects are on a dirty card.
*/
-void dvmVerifyCardTable(void)
+void dvmVerifyCardTable()
{
HeapBitmap *markBits = gDvm.gcHeap->markContext.bitmap;
dvmHeapBitmapWalk(markBits, verifyCardTableCallback, markBits);
diff --git a/vm/alloc/Copying.c b/vm/alloc/Copying.cpp
similarity index 93%
rename from vm/alloc/Copying.c
rename to vm/alloc/Copying.cpp
index 097efae..47df05f 100644
--- a/vm/alloc/Copying.c
+++ b/vm/alloc/Copying.cpp
@@ -147,7 +147,7 @@
static size_t sumHeapBitmap(const HeapBitmap *bitmap);
static size_t objectSize(const Object *obj);
static void scavengeDataObject(Object *obj);
-static void scavengeBlockQueue(void);
+static void scavengeBlockQueue();
/*
* We use 512-byte blocks.
@@ -245,9 +245,7 @@
static void describeBlocks(const HeapSource *heapSource)
{
- size_t i;
-
- for (i = 0; i < heapSource->totalBlocks; ++i) {
+ for (size_t i = 0; i < heapSource->totalBlocks; ++i) {
if ((i % 32) == 0) putchar('\n');
printf("%d ", heapSource->blockSpace[i]);
}
@@ -260,12 +258,9 @@
static void *virtualAlloc(size_t length)
{
- void *addr;
- int flags, prot;
-
- flags = MAP_PRIVATE | MAP_ANONYMOUS;
- prot = PROT_READ | PROT_WRITE;
- addr = mmap(NULL, length, prot, flags, -1, 0);
+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ int prot = PROT_READ | PROT_WRITE;
+ void *addr = mmap(NULL, length, prot, flags, -1, 0);
if (addr == MAP_FAILED) {
LOGE_HEAP("mmap: %s", strerror(errno));
addr = NULL;
@@ -275,11 +270,9 @@
static void virtualFree(void *addr, size_t length)
{
- int res;
-
assert(addr != NULL);
assert((uintptr_t)addr % SYSTEM_PAGE_SIZE == 0);
- res = munmap(addr, length);
+ int res = munmap(addr, length);
if (res == -1) {
LOGE_HEAP("munmap: %s", strerror(errno));
}
@@ -302,12 +295,8 @@
*/
static void *allocateBlocks(HeapSource *heapSource, size_t blocks)
{
- void *addr;
- size_t allocBlocks, totalBlocks;
- size_t i, j;
-
- allocBlocks = heapSource->allocBlocks;
- totalBlocks = heapSource->totalBlocks;
+ size_t allocBlocks = heapSource->allocBlocks;
+ size_t totalBlocks = heapSource->totalBlocks;
/* Check underflow. */
assert(blocks != 0);
/* Check overflow. */
@@ -315,9 +304,9 @@
return NULL;
}
/* Scan block map. */
- for (i = 0; i < totalBlocks; ++i) {
+ for (size_t i = 0; i < totalBlocks; ++i) {
/* Check fit. */
- for (j = 0; j < blocks; ++j) { /* runs over totalBlocks */
+ for (size_t j = 0; j < blocks; ++j) { /* runs over totalBlocks */
if (heapSource->blockSpace[i+j] != BLOCK_FREE) {
break;
}
@@ -329,11 +318,11 @@
}
/* Fit, allocate. */
heapSource->blockSpace[i] = BLOCK_TO_SPACE; /* why to-space? */
- for (j = 1; j < blocks; ++j) {
+ for (size_t j = 1; j < blocks; ++j) {
heapSource->blockSpace[i+j] = BLOCK_CONTINUED;
}
heapSource->allocBlocks += blocks;
- addr = &heapSource->blockBase[i*BLOCK_SIZE];
+ void *addr = &heapSource->blockBase[i*BLOCK_SIZE];
memset(addr, 0, blocks*BLOCK_SIZE);
/* Collecting? */
if (heapSource->queueHead != QUEUE_TAIL) {
@@ -376,24 +365,20 @@
static void clearBlock(HeapSource *heapSource, size_t block)
{
- u1 *addr;
- size_t i;
-
assert(heapSource != NULL);
assert(block < heapSource->totalBlocks);
- addr = heapSource->blockBase + block*BLOCK_SIZE;
+ u1 *addr = heapSource->blockBase + block*BLOCK_SIZE;
memset(addr, 0xCC, BLOCK_SIZE);
- for (i = 0; i < BLOCK_SIZE; i += 8) {
+ for (size_t i = 0; i < BLOCK_SIZE; i += 8) {
dvmHeapBitmapClearObjectBit(&heapSource->allocBits, addr + i);
}
}
static void clearFromSpace(HeapSource *heapSource)
{
- size_t i, count;
-
assert(heapSource != NULL);
- i = count = 0;
+ size_t i = 0;
+ size_t count = 0;
while (i < heapSource->totalBlocks) {
if (heapSource->blockSpace[i] != BLOCK_FROM_SPACE) {
++i;
@@ -517,12 +502,12 @@
* zygote process. This is a no-op for the time being. Eventually
* this will demarcate the shared region of the heap.
*/
-bool dvmHeapSourceStartupAfterZygote(void)
+bool dvmHeapSourceStartupAfterZygote()
{
return true;
}
-bool dvmHeapSourceStartupBeforeFork(void)
+bool dvmHeapSourceStartupBeforeFork()
{
assert(!"implemented");
return false;
@@ -542,7 +527,7 @@
*gcHeap = NULL;
}
-size_t dvmHeapSourceGetValue(enum HeapSourceValueSpec spec,
+size_t dvmHeapSourceGetValue(HeapSourceValueSpec spec,
size_t perHeapStats[],
size_t arrayLen)
{
@@ -583,7 +568,7 @@
assert(!"implemented");
}
-HeapBitmap *dvmHeapSourceGetLiveBits(void)
+HeapBitmap *dvmHeapSourceGetLiveBits()
{
return &gDvm.gcHeap->heapSource->allocBits;
}
@@ -700,7 +685,7 @@
}
}
-bool dvmHeapSourceGetPtrFlag(const void *ptr, enum HeapSourcePtrFlag flag)
+bool dvmHeapSourceGetPtrFlag(const void *ptr, HeapSourcePtrFlag flag)
{
assert(!"implemented");
return false;
@@ -712,7 +697,7 @@
return 0;
}
-size_t dvmHeapSourceFootprint(void)
+size_t dvmHeapSourceFootprint()
{
assert(!"implemented");
return 0;
@@ -723,12 +708,12 @@
* bytes currently committed to the heap. This starts out at the
* start size of the heap and grows toward the maximum size.
*/
-size_t dvmHeapSourceGetIdealFootprint(void)
+size_t dvmHeapSourceGetIdealFootprint()
{
return gDvm.gcHeap->heapSource->currentSize;
}
-float dvmGetTargetHeapUtilization(void)
+float dvmGetTargetHeapUtilization()
{
return 0.5f;
}
@@ -744,7 +729,7 @@
* just a no-op. Eventually, we will either allocate or commit pages
* on an as-need basis.
*/
-void dvmHeapSourceGrowForUtilization(void)
+void dvmHeapSourceGrowForUtilization()
{
/* do nothing */
}
@@ -762,7 +747,7 @@
assert(!"implemented");
}
-size_t dvmHeapSourceGetNumHeaps(void)
+size_t dvmHeapSourceGetNumHeaps()
{
return 1;
}
@@ -778,18 +763,15 @@
/* do nothing */
}
-size_t dvmGetExternalBytesAllocated(void)
+size_t dvmGetExternalBytesAllocated()
{
assert(!"implemented");
return 0;
}
-void dvmHeapSourceFlip(void)
+void dvmHeapSourceFlip()
{
- HeapSource *heapSource;
- size_t i;
-
- heapSource = gDvm.gcHeap->heapSource;
+ HeapSource *heapSource = gDvm.gcHeap->heapSource;
/* Reset the block queue. */
heapSource->allocBlocks = 0;
@@ -802,7 +784,7 @@
heapSource->allocLimit = NULL;
/* Whiten all allocated blocks. */
- for (i = 0; i < heapSource->totalBlocks; ++i) {
+ for (size_t i = 0; i < heapSource->totalBlocks; ++i) {
if (heapSource->blockSpace[i] == BLOCK_TO_SPACE) {
heapSource->blockSpace[i] = BLOCK_FROM_SPACE;
}
@@ -811,9 +793,7 @@
static void room(size_t *alloc, size_t *avail, size_t *total)
{
- HeapSource *heapSource;
-
- heapSource = gDvm.gcHeap->heapSource;
+ HeapSource *heapSource = gDvm.gcHeap->heapSource;
*total = heapSource->totalBlocks*BLOCK_SIZE;
*alloc = heapSource->allocBlocks*BLOCK_SIZE;
*avail = *total - *alloc;
@@ -857,10 +837,8 @@
static size_t sumHeapBitmap(const HeapBitmap *bitmap)
{
- size_t i, sum;
-
- sum = 0;
- for (i = 0; i < bitmap->bitsLen >> 2; ++i) {
+ size_t sum = 0;
+ for (size_t i = 0; i < bitmap->bitsLen >> 2; ++i) {
sum += CLZ(bitmap->bits[i]);
}
return sum;
@@ -908,8 +886,6 @@
*/
static void scavengeClassObject(ClassObject *obj)
{
- int i;
-
LOG_SCAV("scavengeClassObject(obj=%p)", obj);
assert(obj != NULL);
assert(obj->obj.clazz != NULL);
@@ -929,14 +905,14 @@
/* Scavenge the class loader. */
scavengeReference(&obj->classLoader);
/* Scavenge static fields. */
- for (i = 0; i < obj->sfieldCount; ++i) {
+ for (int i = 0; i < obj->sfieldCount; ++i) {
char ch = obj->sfields[i].field.signature[0];
if (ch == '[' || ch == 'L') {
scavengeReference((Object **)(void *)&obj->sfields[i].value.l);
}
}
/* Scavenge interface class objects. */
- for (i = 0; i < obj->interfaceCount; ++i) {
+ for (int i = 0; i < obj->interfaceCount; ++i) {
scavengeReference((Object **) &obj->interfaces[i]);
}
}
@@ -946,19 +922,17 @@
*/
static size_t scavengeArrayObject(ArrayObject *array)
{
- size_t i, length;
-
LOG_SCAV("scavengeArrayObject(array=%p)", array);
/* Scavenge the class object. */
assert(toSpaceContains(array));
assert(array != NULL);
assert(array->obj.clazz != NULL);
scavengeReference((Object **) array);
- length = dvmArrayObjectSize(array);
+ size_t length = dvmArrayObjectSize(array);
/* Scavenge the array contents. */
if (IS_CLASS_FLAG_SET(array->obj.clazz, CLASS_ISOBJECTARRAY)) {
Object **contents = (Object **)array->contents;
- for (i = 0; i < array->length; ++i) {
+ for (size_t i = 0; i < array->length; ++i) {
scavengeReference(&contents[i]);
}
}
@@ -1138,7 +1112,7 @@
scavengeBlockQueue();
}
-void processFinalizableReferences(void)
+void processFinalizableReferences()
{
HeapRefTable newPendingRefs;
LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs;
@@ -1280,16 +1254,13 @@
*/
static void scavengeDataObject(Object *obj)
{
- ClassObject *clazz;
- int i;
-
// LOG_SCAV("scavengeDataObject(obj=%p)", obj);
assert(obj != NULL);
assert(obj->clazz != NULL);
assert(obj->clazz->objectSize != 0);
assert(toSpaceContains(obj));
/* Scavenge the class object. */
- clazz = obj->clazz;
+ ClassObject *clazz = obj->clazz;
scavengeReference((Object **) obj);
/* Scavenge instance fields. */
if (clazz->refOffsets != CLASS_WALK_SUPER) {
@@ -1304,7 +1275,7 @@
} else {
for (; clazz != NULL; clazz = clazz->super) {
InstField *field = clazz->ifields;
- for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
+ for (int i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
size_t offset = field->byteOffset;
Object **ref = (Object **)((u1 *)obj + offset);
scavengeReference(ref);
@@ -1426,7 +1397,7 @@
assert(obj->clazz != NULL);
assert(!((uintptr_t)obj->clazz & 0x1));
clazz = obj->clazz;
- if (clazz == gDvm.classJavaLangClass) {
+ if (dvmIsTheClassClass(clazz)) {
scavengeClassObject((ClassObject *)obj);
} else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
scavengeArrayObject((ArrayObject *)obj);
@@ -1443,18 +1414,14 @@
static void pinHashTableEntries(HashTable *table)
{
- HashEntry *entry;
- void *obj;
- int i;
-
LOG_PIN(">>> pinHashTableEntries(table=%p)", table);
if (table == NULL) {
return;
}
dvmHashTableLock(table);
- for (i = 0; i < table->tableSize; ++i) {
- entry = &table->pEntries[i];
- obj = entry->data;
+ for (int i = 0; i < table->tableSize; ++i) {
+ HashEntry *entry = &table->pEntries[i];
+ void *obj = entry->data;
if (obj == NULL || obj == HASH_TOMBSTONE) {
continue;
}
@@ -1464,13 +1431,10 @@
LOG_PIN("<<< pinHashTableEntries(table=%p)", table);
}
-static void pinPrimitiveClasses(void)
+static void pinPrimitiveClasses()
{
- size_t length;
- size_t i;
-
- length = ARRAYSIZE(gDvm.primitiveClass);
- for (i = 0; i < length; i++) {
+ size_t length = ARRAYSIZE(gDvm.primitiveClass);
+ for (size_t i = 0; i < length; i++) {
if (gDvm.primitiveClass[i] != NULL) {
pinObject((Object *)gDvm.primitiveClass[i]);
}
@@ -1482,21 +1446,16 @@
* been pinned and are therefore ignored. Non-permanent strings that
* have been forwarded are snapped. All other entries are removed.
*/
-static void scavengeInternedStrings(void)
+static void scavengeInternedStrings()
{
- HashTable *table;
- HashEntry *entry;
- Object *obj;
- int i;
-
- table = gDvm.internedStrings;
+ HashTable *table = gDvm.internedStrings;
if (table == NULL) {
return;
}
dvmHashTableLock(table);
- for (i = 0; i < table->tableSize; ++i) {
- entry = &table->pEntries[i];
- obj = (Object *)entry->data;
+ for (int i = 0; i < table->tableSize; ++i) {
+ HashEntry *entry = &table->pEntries[i];
+ Object *obj = (Object *)entry->data;
if (obj == NULL || obj == HASH_TOMBSTONE) {
continue;
} else if (!isPermanentString((StringObject *)obj)) {
@@ -1510,21 +1469,16 @@
dvmHashTableUnlock(table);
}
-static void pinInternedStrings(void)
+static void pinInternedStrings()
{
- HashTable *table;
- HashEntry *entry;
- Object *obj;
- int i;
-
- table = gDvm.internedStrings;
+ HashTable *table = gDvm.internedStrings;
if (table == NULL) {
return;
}
dvmHashTableLock(table);
- for (i = 0; i < table->tableSize; ++i) {
- entry = &table->pEntries[i];
- obj = (Object *)entry->data;
+ for (int i = 0; i < table->tableSize; ++i) {
+ HashEntry *entry = &table->pEntries[i];
+ Object *obj = (Object *)entry->data;
if (obj == NULL || obj == HASH_TOMBSTONE) {
continue;
} else if (isPermanentString((StringObject *)obj)) {
@@ -1544,12 +1498,10 @@
*/
static void pinReferenceTable(const ReferenceTable *table)
{
- Object **entry;
-
assert(table != NULL);
assert(table->table != NULL);
assert(table->nextEntry != NULL);
- for (entry = table->table; entry < table->nextEntry; ++entry) {
+ for (Object **entry = table->table; entry < table->nextEntry; ++entry) {
assert(entry != NULL);
assert(!isForward(*entry));
pinObject(*entry);
@@ -1574,7 +1526,7 @@
bool first = true;
#endif
- framePtr = (const u4 *)thread->curFrame;
+ framePtr = (const u4 *)thread->interpSave.curFrame;
while (framePtr != NULL) {
const StackSaveArea *saveArea;
const Method *method;
@@ -1656,7 +1608,6 @@
const RegisterMap* pMap;
const u1* regVector;
- int i;
Method* nonConstMethod = (Method*) method; // quiet gcc
pMap = dvmGetExpandedRegisterMap(nonConstMethod);
@@ -1705,7 +1656,7 @@
* A '1' bit indicates a live reference.
*/
u2 bits = 1 << 1;
- for (i = method->registersSize - 1; i >= 0; i--) {
+ for (int i = method->registersSize - 1; i >= 0; i--) {
u4 rval = *framePtr;
bits >>= 1;
@@ -1779,7 +1730,7 @@
scavengeThreadStack(thread);
}
-static void scavengeThreadList(void)
+static void scavengeThreadList()
{
Thread *thread;
@@ -1799,10 +1750,9 @@
Method *method;
const char *shorty;
Object *obj;
- int i;
saveArea = NULL;
- framePtr = (const u4 *)thread->curFrame;
+ framePtr = (const u4 *)thread->interpSave.curFrame;
for (; framePtr != NULL; framePtr = saveArea->prevFrame) {
saveArea = SAVEAREA_FROM_FP(framePtr);
method = (Method *)saveArea->method;
@@ -1841,7 +1791,7 @@
}
}
shorty = method->shorty+1; // skip return value
- for (i = method->registersSize - 1; i >= 0; i--, framePtr++) {
+ for (int i = method->registersSize - 1; i >= 0; i--, framePtr++) {
switch (*shorty++) {
case 'L':
obj = (Object *)*framePtr;
@@ -1878,7 +1828,7 @@
/*
* No register info for this frame, conservatively pin.
*/
- for (i = 0; i < method->registersSize; ++i) {
+ for (int i = 0; i < method->registersSize; ++i) {
u4 regValue = framePtr[i];
if (regValue != 0 && (regValue & 0x3) == 0 && dvmIsValidObject((Object *)regValue)) {
pinObject((Object *)regValue);
@@ -1915,7 +1865,7 @@
}
}
-static void pinThreadList(void)
+static void pinThreadList()
{
Thread *thread;
@@ -2059,7 +2009,7 @@
/*
* Blackens promoted objects.
*/
-static void scavengeBlockQueue(void)
+static void scavengeBlockQueue()
{
HeapSource *heapSource;
size_t block;
@@ -2082,15 +2032,11 @@
* in new space. This should be parametrized so we can invoke this
* routine outside of the context of a collection.
*/
-static void verifyNewSpace(void)
+static void verifyNewSpace()
{
- HeapSource *heapSource;
- size_t i;
- size_t c0, c1, c2, c7;
-
- c0 = c1 = c2 = c7 = 0;
- heapSource = gDvm.gcHeap->heapSource;
- for (i = 0; i < heapSource->totalBlocks; ++i) {
+ HeapSource *heapSource = gDvm.gcHeap->heapSource;
+ size_t c0 = 0, c1 = 0, c2 = 0, c7 = 0;
+ for (size_t i = 0; i < heapSource->totalBlocks; ++i) {
switch (heapSource->blockSpace[i]) {
case BLOCK_FREE: ++c0; break;
case BLOCK_TO_SPACE: ++c1; break;
@@ -2102,7 +2048,7 @@
LOG_VER("Block Demographics: "
"Free=%zu,ToSpace=%zu,FromSpace=%zu,Continued=%zu",
c0, c1, c2, c7);
- for (i = 0; i < heapSource->totalBlocks; ++i) {
+ for (size_t i = 0; i < heapSource->totalBlocks; ++i) {
if (heapSource->blockSpace[i] != BLOCK_TO_SPACE) {
continue;
}
@@ -2110,11 +2056,9 @@
}
}
-void describeHeap(void)
+void describeHeap()
{
- HeapSource *heapSource;
-
- heapSource = gDvm.gcHeap->heapSource;
+ HeapSource *heapSource = gDvm.gcHeap->heapSource;
describeBlocks(heapSource);
}
@@ -2126,7 +2070,7 @@
* registers and various globals. Lastly, a verification of the heap
* is performed. The last phase should be optional.
*/
-void dvmScavengeRoots(void) /* Needs a new name badly */
+void dvmScavengeRoots() /* Needs a new name badly */
{
GcHeap *gcHeap;
@@ -2262,22 +2206,22 @@
return true;
}
-void dvmHeapFinishMarkStep(void)
+void dvmHeapFinishMarkStep()
{
/* do nothing */
}
-void dvmHeapMarkRootSet(void)
+void dvmHeapMarkRootSet()
{
/* do nothing */
}
-void dvmHeapScanMarkedObjects(void)
+void dvmHeapScanMarkedObjects()
{
dvmScavengeRoots();
}
-void dvmHeapScheduleFinalizations(void)
+void dvmHeapScheduleFinalizations()
{
/* do nothing */
}
@@ -2289,12 +2233,12 @@
/* do nothing */
}
-void dvmMarkDirtyObjects(void)
+void dvmMarkDirtyObjects()
{
assert(!"implemented");
}
-void dvmHeapSourceThreadShutdown(void)
+void dvmHeapSourceThreadShutdown()
{
/* do nothing */
}
diff --git a/vm/alloc/DdmHeap.c b/vm/alloc/DdmHeap.cpp
similarity index 98%
rename from vm/alloc/DdmHeap.c
rename to vm/alloc/DdmHeap.cpp
index b377b1b..53dbf52 100644
--- a/vm/alloc/DdmHeap.c
+++ b/vm/alloc/DdmHeap.cpp
@@ -174,7 +174,7 @@
#define HPSG_STATE(solidity, kind) \
((u1)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
-typedef struct HeapChunkContext {
+struct HeapChunkContext {
u1 *buf;
u1 *p;
u1 *pieceLenField;
@@ -183,7 +183,7 @@
int type;
bool merge;
bool needHeader;
-} HeapChunkContext;
+};
#define ALLOCATION_UNIT_SIZE 8
@@ -290,7 +290,7 @@
* but hasn't been initialized yet.
*/
state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
- } else if (clazz == gDvm.classJavaLangClass) {
+ } else if (dvmIsTheClassClass(clazz)) {
state = HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
} else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
@@ -357,7 +357,7 @@
*/
#define HPSx_CHUNK_SIZE (16384 - 16)
-void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
+extern "C" void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
static void
walkHeap(bool merge, bool native)
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.cpp
similarity index 97%
rename from vm/alloc/Heap.c
rename to vm/alloc/Heap.cpp
index f38eb12..34f56cc 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.cpp
@@ -37,7 +37,7 @@
static const GcSpec kGcForMallocSpec = {
true, /* isPartial */
false, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_FOR_ALLOC"
};
@@ -46,7 +46,7 @@
static const GcSpec kGcConcurrentSpec = {
true, /* isPartial */
true, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_CONCURRENT"
};
@@ -55,7 +55,7 @@
static const GcSpec kGcExplicitSpec = {
false, /* isPartial */
true, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_EXPLICIT"
};
@@ -64,7 +64,7 @@
static const GcSpec kGcBeforeOomSpec = {
false, /* isPartial */
false, /* isConcurrent */
- CLEAR,
+ false, /* doPreserve */
"GC_BEFORE_OOM"
};
@@ -108,7 +108,7 @@
return true;
}
-bool dvmHeapStartupAfterZygote(void)
+bool dvmHeapStartupAfterZygote()
{
return dvmHeapSourceStartupAfterZygote();
}
@@ -129,7 +129,7 @@
/*
* Shutdown any threads internal to the heap.
*/
-void dvmHeapThreadShutdown(void)
+void dvmHeapThreadShutdown()
{
dvmHeapSourceThreadShutdown();
}
@@ -187,8 +187,8 @@
* throwing an OOME, though.
*/
if (size >= gDvm.heapGrowthLimit) {
- LOGW_HEAP("dvmMalloc(%zu/0x%08zx): "
- "someone's allocating a huge buffer\n", size, size);
+ LOGW("%zd byte allocation exceeds the %zd byte maximum heap size",
+ size, gDvm.heapGrowthLimit);
ptr = NULL;
goto collect_soft_refs;
}
@@ -436,7 +436,7 @@
return dvmHeapSourceChunkSize(obj);
}
-static void verifyRootsAndHeap(void)
+static void verifyRootsAndHeap()
{
dvmVerifyRoots();
dvmVerifyBitmap(dvmHeapSourceGetLiveBits());
@@ -447,7 +447,7 @@
* original priority if successful. Otherwise, returns INT_MAX on
* failure.
*/
-static int raiseThreadPriority(void)
+static int raiseThreadPriority()
{
/* Get the priority (the "nice" value) of the current thread. The
* getpriority() call can legitimately return -1, so we have to
@@ -622,7 +622,7 @@
* weakly-reachable objects discovered while tracing.
*/
dvmHeapProcessReferences(&gcHeap->softReferences,
- spec->softReferencePolicy == CLEAR,
+ spec->doPreserve == false,
&gcHeap->weakReferences,
&gcHeap->finalizerReferences,
&gcHeap->phantomReferences);
@@ -773,7 +773,7 @@
* suspend when the GC thread calls dvmUnlockHeap before dvmResumeAllThreads,
* but there's no risk of deadlock.)
*/
-void dvmWaitForConcurrentGcToComplete(void)
+void dvmWaitForConcurrentGcToComplete()
{
Thread *self = dvmThreadSelf();
assert(self != NULL);
diff --git a/vm/alloc/Heap.h b/vm/alloc/Heap.h
index 01a50d2..7212429 100644
--- a/vm/alloc/Heap.h
+++ b/vm/alloc/Heap.h
@@ -19,16 +19,16 @@
#ifndef _DALVIK_ALLOC_HEAP
#define _DALVIK_ALLOC_HEAP
-typedef struct {
+struct GcSpec {
/* If true, only the application heap is threatened. */
bool isPartial;
/* If true, the trace is run concurrently with the mutator. */
bool isConcurrent;
/* Toggles for the soft reference clearing policy. */
- enum { CLEAR, PRESERVE } softReferencePolicy;
+ bool doPreserve;
/* A name for this garbage collection mode. */
const char *reason;
-} GcSpec;
+};
/* Not enough space for an "ordinary" Object to be allocated. */
extern const GcSpec *GC_FOR_MALLOC;
diff --git a/vm/alloc/HeapBitmap.c b/vm/alloc/HeapBitmap.cpp
similarity index 93%
rename from vm/alloc/HeapBitmap.c
rename to vm/alloc/HeapBitmap.cpp
index ffeff62..0ffd3b0 100644
--- a/vm/alloc/HeapBitmap.c
+++ b/vm/alloc/HeapBitmap.cpp
@@ -100,14 +100,11 @@
void dvmHeapBitmapWalk(const HeapBitmap *bitmap, BitmapCallback *callback,
void *arg)
{
- uintptr_t end;
- uintptr_t i;
-
assert(bitmap != NULL);
assert(bitmap->bits != NULL);
assert(callback != NULL);
- end = HB_OFFSET_TO_INDEX(bitmap->max - bitmap->base);
- for (i = 0; i <= end; ++i) {
+ uintptr_t end = HB_OFFSET_TO_INDEX(bitmap->max - bitmap->base);
+ for (uintptr_t i = 0; i <= end; ++i) {
unsigned long word = bitmap->bits[i];
if (UNLIKELY(word != 0)) {
unsigned long highBit = 1 << (HB_BITS_PER_WORD - 1);
@@ -145,8 +142,7 @@
assert(base >= bitmap->base);
assert(max <= bitmap->max);
uintptr_t end = HB_OFFSET_TO_INDEX(max - base);
- uintptr_t i;
- for (i = 0; i <= end; ++i) {
+ for (uintptr_t i = 0; i <= end; ++i) {
unsigned long word = bitmap->bits[i];
if (UNLIKELY(word != 0)) {
unsigned long highBit = 1 << (HB_BITS_PER_WORD - 1);
@@ -174,12 +170,6 @@
uintptr_t base, uintptr_t max,
BitmapSweepCallback *callback, void *callbackArg)
{
- void *pointerBuf[4 * HB_BITS_PER_WORD];
- void **pb = pointerBuf;
- size_t i;
- size_t start, end;
- unsigned long *live, *mark;
-
assert(liveHb != NULL);
assert(liveHb->bits != NULL);
assert(markHb != NULL);
@@ -195,11 +185,13 @@
*/
return;
}
- start = HB_OFFSET_TO_INDEX(base - liveHb->base);
- end = HB_OFFSET_TO_INDEX(max - liveHb->base);
- live = liveHb->bits;
- mark = markHb->bits;
- for (i = start; i <= end; i++) {
+ void *pointerBuf[4 * HB_BITS_PER_WORD];
+ void **pb = pointerBuf;
+ size_t start = HB_OFFSET_TO_INDEX(base - liveHb->base);
+ size_t end = HB_OFFSET_TO_INDEX(max - liveHb->base);
+ unsigned long *live = liveHb->bits;
+ unsigned long *mark = markHb->bits;
+ for (size_t i = start; i <= end; i++) {
unsigned long garbage = live[i] & ~mark[i];
if (UNLIKELY(garbage != 0)) {
unsigned long highBit = 1 << (HB_BITS_PER_WORD - 1);
diff --git a/vm/alloc/HeapBitmap.h b/vm/alloc/HeapBitmap.h
index fecc2a9..90cfea9 100644
--- a/vm/alloc/HeapBitmap.h
+++ b/vm/alloc/HeapBitmap.h
@@ -41,7 +41,7 @@
(1 << \
(31-(((uintptr_t)(offset_) / HB_OBJECT_ALIGNMENT) % HB_BITS_PER_WORD)))
-typedef struct {
+struct HeapBitmap {
/* The bitmap data, which points to an mmap()ed area of zeroed
* anonymous memory.
*/
@@ -68,7 +68,7 @@
* to a set bit. If there are no bits set, (max < base).
*/
uintptr_t max;
-} HeapBitmap;
+};
/*
* Callback types used by the walking routines.
diff --git a/vm/alloc/HeapDebug.c b/vm/alloc/HeapDebug.cpp
similarity index 100%
rename from vm/alloc/HeapDebug.c
rename to vm/alloc/HeapDebug.cpp
diff --git a/vm/alloc/HeapDebug.h b/vm/alloc/HeapDebug.h
index f36b7ab..35b274d 100644
--- a/vm/alloc/HeapDebug.h
+++ b/vm/alloc/HeapDebug.h
@@ -16,13 +16,13 @@
#ifndef _DALVIK_HEAPDEBUG
#define _DALVIK_HEAPDEBUG
-typedef enum HeapDebugInfoType {
+enum HeapDebugInfoType {
kVirtualHeapSize = 0,
kNativeHeapSize = 1,
kVirtualHeapAllocated = 2,
kNativeHeapAllocated = 3,
kVirtualHeapMaximumSize = 4
-} HeapDebugInfoType;
+};
/* Return the specified value.
* Returns -1 if the type is unknown.
diff --git a/vm/alloc/HeapInternal.h b/vm/alloc/HeapInternal.h
index 1d1be07..e98290c 100644
--- a/vm/alloc/HeapInternal.h
+++ b/vm/alloc/HeapInternal.h
@@ -21,7 +21,7 @@
#include "MarkSweep.h"
-typedef struct HeapSource HeapSource;
+struct HeapSource;
struct GcHeap {
HeapSource *heapSource;
@@ -85,7 +85,10 @@
#define LOGD_HEAP(...) LOG(LOG_DEBUG, HEAP_LOG_TAG, __VA_ARGS__)
#endif
#define LOGI_HEAP(...) \
- (!gDvm.zygote ? LOG(LOG_INFO, HEAP_LOG_TAG, __VA_ARGS__) : (void)0)
+ do { \
+ if (!gDvm.zygote) { LOG(LOG_INFO, HEAP_LOG_TAG, __VA_ARGS__); } \
+ } while (0)
+
#define LOGW_HEAP(...) LOG(LOG_WARN, HEAP_LOG_TAG, __VA_ARGS__)
#define LOGE_HEAP(...) LOG(LOG_ERROR, HEAP_LOG_TAG, __VA_ARGS__)
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.cpp
similarity index 95%
rename from vm/alloc/HeapSource.c
rename to vm/alloc/HeapSource.cpp
index 4b61358..6666f88 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.cpp
@@ -15,10 +15,12 @@
*/
#include <cutils/mspace.h>
-#include <stdint.h> // for SIZE_MAX
+#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
+#define SIZE_MAX UINT_MAX // TODO: get SIZE_MAX from stdint.h
+
#include "Dalvik.h"
#include "alloc/Heap.h"
#include "alloc/HeapInternal.h"
@@ -27,10 +29,10 @@
#include "alloc/HeapBitmapInlines.h"
// TODO: find a real header file for these.
-extern int dlmalloc_trim(size_t);
-extern void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*);
+extern "C" int dlmalloc_trim(size_t);
+extern "C" void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*);
-static void snapIdealFootprint(void);
+static void snapIdealFootprint();
static void setIdealFootprint(size_t max);
static size_t getMaximumSize(const HeapSource *hs);
@@ -63,7 +65,7 @@
#define HSTRACE(...) /**/
#endif
-typedef struct {
+struct Heap {
/* The mspace to allocate from.
*/
mspace msp;
@@ -96,7 +98,7 @@
* The highest address of this heap, exclusive.
*/
char *limit;
-} Heap;
+};
struct HeapSource {
/* Target ideal heap utilization ratio; range 1..HEAP_UTILIZATION_MAX
@@ -232,11 +234,10 @@
static Heap *ptr2heap(const HeapSource *hs, const void *ptr)
{
const size_t numHeaps = hs->numHeaps;
- size_t i;
//TODO: unroll this to HEAP_SOURCE_MAX_HEAP_COUNT
if (ptr != NULL) {
- for (i = 0; i < numHeaps; i++) {
+ for (size_t i = 0; i < numHeaps; i++) {
const Heap *const heap = &hs->heaps[i];
if ((const char *)ptr >= heap->base && (const char *)ptr < heap->limit) {
@@ -425,7 +426,7 @@
return NULL;
}
-static bool gcDaemonStartup(void)
+static bool gcDaemonStartup()
{
dvmInitMutex(&gHs->gcThreadMutex);
pthread_cond_init(&gHs->gcThreadCond, NULL);
@@ -435,7 +436,7 @@
return gHs->hasGcThread;
}
-static void gcDaemonShutdown(void)
+static void gcDaemonShutdown()
{
if (gHs->hasGcThread) {
dvmLockMutex(&gHs->gcThreadMutex);
@@ -574,7 +575,7 @@
return NULL;
}
-bool dvmHeapSourceStartupAfterZygote(void)
+bool dvmHeapSourceStartupAfterZygote()
{
return gDvm.concurrentMarkSweep ? gcDaemonStartup() : true;
}
@@ -607,7 +608,7 @@
return true;
}
-void dvmHeapSourceThreadShutdown(void)
+void dvmHeapSourceThreadShutdown()
{
if (gDvm.gcHeap != NULL && gDvm.concurrentMarkSweep) {
gcDaemonShutdown();
@@ -639,7 +640,7 @@
/*
* Gets the begining of the allocation for the HeapSource.
*/
-void *dvmHeapSourceGetBase(void)
+void *dvmHeapSourceGetBase()
{
return gHs->heapBase;
}
@@ -651,18 +652,17 @@
* Caller must hold the heap lock.
*/
size_t
-dvmHeapSourceGetValue(enum HeapSourceValueSpec spec, size_t perHeapStats[],
+dvmHeapSourceGetValue(HeapSourceValueSpec spec, size_t perHeapStats[],
size_t arrayLen)
{
HeapSource *hs = gHs;
size_t value = 0;
size_t total = 0;
- size_t i;
HS_BOILERPLATE();
assert(arrayLen >= hs->numHeaps || perHeapStats == NULL);
- for (i = 0; i < hs->numHeaps; i++) {
+ for (size_t i = 0; i < hs->numHeaps; i++) {
Heap *const heap = &hs->heaps[i];
switch (spec) {
@@ -694,12 +694,11 @@
size_t numHeaps)
{
HeapSource *hs = gHs;
- size_t i;
HS_BOILERPLATE();
assert(numHeaps <= hs->numHeaps);
- for (i = 0; i < numHeaps; ++i) {
+ for (size_t i = 0; i < numHeaps; ++i) {
base[i] = (uintptr_t)hs->heaps[i].base;
if (max != NULL) {
max[i] = MIN((uintptr_t)hs->heaps[i].limit - 1, hs->markBits.max);
@@ -713,7 +712,7 @@
/*
* Get the bitmap representing all live objects.
*/
-HeapBitmap *dvmHeapSourceGetLiveBits(void)
+HeapBitmap *dvmHeapSourceGetLiveBits()
{
HS_BOILERPLATE();
@@ -723,14 +722,14 @@
/*
* Get the bitmap representing all marked objects.
*/
-HeapBitmap *dvmHeapSourceGetMarkBits(void)
+HeapBitmap *dvmHeapSourceGetMarkBits()
{
HS_BOILERPLATE();
return &gHs->markBits;
}
-void dvmHeapSourceSwapBitmaps(void)
+void dvmHeapSourceSwapBitmaps()
{
HeapBitmap tmp;
@@ -739,7 +738,7 @@
gHs->markBits = tmp;
}
-void dvmHeapSourceZeroMarkBitmap(void)
+void dvmHeapSourceZeroMarkBitmap()
{
HS_BOILERPLATE();
@@ -748,9 +747,6 @@
void dvmMarkImmuneObjects(const char *immuneLimit)
{
- char *dst, *src;
- size_t i, index, length;
-
/*
* Copy the contents of the live bit vector for immune object
* range into the mark bit vector.
@@ -764,17 +760,17 @@
assert(gHs->heaps[0].base >= immuneLimit);
assert(gHs->heaps[0].limit > immuneLimit);
- for (i = 1; i < gHs->numHeaps; ++i) {
+ for (size_t i = 1; i < gHs->numHeaps; ++i) {
if (gHs->heaps[i].base < immuneLimit) {
assert(gHs->heaps[i].limit <= immuneLimit);
/* Compute the number of words to copy in the bitmap. */
- index = HB_OFFSET_TO_INDEX(
+ size_t index = HB_OFFSET_TO_INDEX(
(uintptr_t)gHs->heaps[i].base - gHs->liveBits.base);
/* Compute the starting offset in the live and mark bits. */
- src = (char *)(gHs->liveBits.bits + index);
- dst = (char *)(gHs->markBits.bits + index);
+ char *src = (char *)(gHs->liveBits.bits + index);
+ char *dst = (char *)(gHs->markBits.bits + index);
/* Compute the number of bytes of the live bitmap to copy. */
- length = HB_OFFSET_TO_BYTE_INDEX(
+ size_t length = HB_OFFSET_TO_BYTE_INDEX(
gHs->heaps[i].limit - gHs->heaps[i].base);
/* Do the copy. */
memcpy(dst, src, length);
@@ -958,9 +954,7 @@
assert(ptr2heap(gHs, ptrs[0]) == heap);
countFree(heap, ptrs[0], &numBytes);
void *merged = ptrs[0];
-
- size_t i;
- for (i = 1; i < numPtrs; i++) {
+ for (size_t i = 1; i < numPtrs; i++) {
assert(merged != NULL);
assert(ptrs[i] != NULL);
assert((intptr_t)merged < (intptr_t)ptrs[i]);
@@ -979,8 +973,7 @@
mspace_free(msp, merged);
} else {
// This is not an 'active heap'. Only do the accounting.
- size_t i;
- for (i = 0; i < numPtrs; i++) {
+ for (size_t i = 0; i < numPtrs; i++) {
assert(ptrs[i] != NULL);
assert(ptr2heap(gHs, ptrs[i]) == heap);
countFree(heap, ptrs[i], &numBytes);
@@ -1019,7 +1012,7 @@
* Returns the value of the requested flag.
*/
bool
-dvmHeapSourceGetPtrFlag(const void *ptr, enum HeapSourcePtrFlag flag)
+dvmHeapSourceGetPtrFlag(const void *ptr, HeapSourcePtrFlag flag)
{
if (ptr == NULL) {
return false;
@@ -1400,15 +1393,13 @@
dvmHeapSourceTrim(size_t bytesTrimmed[], size_t arrayLen)
{
HeapSource *hs = gHs;
- size_t nativeBytes, heapBytes;
- size_t i;
HS_BOILERPLATE();
assert(arrayLen >= hs->numHeaps);
- heapBytes = 0;
- for (i = 0; i < hs->numHeaps; i++) {
+ size_t heapBytes = 0;
+ for (size_t i = 0; i < hs->numHeaps; i++) {
Heap *heap = &hs->heaps[i];
/* Return the wilderness chunk to the system.
@@ -1426,7 +1417,7 @@
/* Same for the native heap.
*/
dlmalloc_trim(0);
- nativeBytes = 0;
+ size_t nativeBytes = 0;
dlmalloc_walk_free_pages(releasePagesInRange, &nativeBytes);
LOGD_HEAP("madvised %zd (GC) + %zd (native) = %zd total bytes\n",
@@ -1444,14 +1435,13 @@
void *arg)
{
HeapSource *hs = gHs;
- size_t i;
HS_BOILERPLATE();
/* Walk the heaps from oldest to newest.
*/
//TODO: do this in address order
- for (i = hs->numHeaps; i > 0; --i) {
+ for (size_t i = hs->numHeaps; i > 0; --i) {
mspace_walk_heap(hs->heaps[i-1].msp, callback, arg);
}
}
diff --git a/vm/alloc/HeapSource.h b/vm/alloc/HeapSource.h
index be6d2e5..64008b3 100644
--- a/vm/alloc/HeapSource.h
+++ b/vm/alloc/HeapSource.h
@@ -28,6 +28,18 @@
*/
#define HEAP_SOURCE_MAX_HEAP_COUNT 2
+enum HeapSourceValueSpec {
+ HS_FOOTPRINT,
+ HS_ALLOWED_FOOTPRINT,
+ HS_BYTES_ALLOCATED,
+ HS_OBJECTS_ALLOCATED
+};
+
+enum HeapSourcePtrFlag {
+ HS_CONTAINS, // identical to dvmHeapSourceContains()
+ HS_ALLOCATED_IN_ZYGOTE
+};
+
/*
* Initializes the heap source; must be called before any other
* dvmHeapSource*() functions.
@@ -90,13 +102,7 @@
* Returns the requested value. If the per-heap stats are requested, fill
* them as well.
*/
-enum HeapSourceValueSpec {
- HS_FOOTPRINT,
- HS_ALLOWED_FOOTPRINT,
- HS_BYTES_ALLOCATED,
- HS_OBJECTS_ALLOCATED
-};
-size_t dvmHeapSourceGetValue(enum HeapSourceValueSpec spec,
+size_t dvmHeapSourceGetValue(HeapSourceValueSpec spec,
size_t perHeapStats[], size_t arrayLen);
/*
@@ -131,11 +137,7 @@
/*
* Returns the value of the requested flag.
*/
-enum HeapSourcePtrFlag {
- HS_CONTAINS, // identical to dvmHeapSourceContains()
- HS_ALLOCATED_IN_ZYGOTE
-};
-bool dvmHeapSourceGetPtrFlag(const void *ptr, enum HeapSourcePtrFlag flag);
+bool dvmHeapSourceGetPtrFlag(const void *ptr, HeapSourcePtrFlag flag);
/*
* Returns the number of usable bytes in an allocated chunk; the size
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.cpp
similarity index 90%
rename from vm/alloc/MarkSweep.c
rename to vm/alloc/MarkSweep.cpp
index 8e924d5..79588f2 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.cpp
@@ -110,7 +110,6 @@
assert(ctx != NULL);
assert(obj != NULL);
assert(dvmIsValidObject(obj));
-
if (obj < (Object *)ctx->immuneLimit) {
assert(isMarked(obj, ctx));
return;
@@ -144,16 +143,13 @@
* marking. Marks white objects but does not push them on the mark
* stack.
*/
-static void rootMarkObjectVisitor(void *addr, RootType type, u4 thread,
+static void rootMarkObjectVisitor(void *addr, u4 thread, RootType type,
void *arg)
{
- Object *obj;
- GcMarkContext *ctx;
-
assert(addr != NULL);
assert(arg != NULL);
- obj = *(Object **)addr;
- ctx = (GcMarkContext *)arg;
+ Object *obj = *(Object **)addr;
+ GcMarkContext *ctx = (GcMarkContext *)arg;
if (obj != NULL) {
markObjectNonNull(obj, ctx, false);
}
@@ -196,15 +192,13 @@
assert(byteLength <= gDvm.gcHeap->modUnionTableLength);
assert(byteLength % sizeof(*bits) == 0);
size_t wordLength = byteLength / sizeof(*bits);
- size_t i;
- for (i = 0; i < wordLength; ++i) {
+ for (size_t i = 0; i < wordLength; ++i) {
if (bits[i] == 0) {
continue;
}
u4 word = bits[i];
bits[i] = 0;
- size_t j = 0;
- for (j = 0; j < sizeof(u4)*CHAR_BIT; ++j) {
+ for (size_t j = 0; j < sizeof(u4)*CHAR_BIT; ++j) {
if (word & (1 << j)) {
/* compute the base of the card */
size_t offset = (i*sizeof(u4)*CHAR_BIT + j) * GC_CARD_SIZE;
@@ -240,10 +234,10 @@
}
}
-typedef struct {
+struct ScanImmuneObjectContext {
Object *threatenBoundary;
Object *currObject;
-} ScanImmuneObjectContext;
+};
/*
* Marks the referent of an immune object it is threatened.
@@ -363,16 +357,13 @@
* Callback applied to root references during root remarking. Marks
* white objects and pushes them on the mark stack.
*/
-static void rootReMarkObjectVisitor(void *addr, RootType type, u4 thread,
+static void rootReMarkObjectVisitor(void *addr, u4 thread, RootType type,
void *arg)
{
- Object *obj;
- GcMarkContext *ctx;
-
assert(addr != NULL);
assert(arg != NULL);
- obj = *(Object **)addr;
- ctx = (GcMarkContext *)arg;
+ Object *obj = *(Object **)addr;
+ GcMarkContext *ctx = (GcMarkContext *)arg;
if (obj != NULL) {
markObjectNonNull(obj, ctx, true);
}
@@ -381,7 +372,7 @@
/*
* Grays all references in the roots.
*/
-void dvmHeapReMarkRootSet(void)
+void dvmHeapReMarkRootSet()
{
GcMarkContext *ctx = &gDvm.gcHeap->markContext;
assert(ctx->finger == (void *)ULONG_MAX);
@@ -396,7 +387,6 @@
assert(obj != NULL);
assert(obj->clazz != NULL);
assert(ctx != NULL);
-
if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
unsigned int refOffsets = obj->clazz->refOffsets;
while (refOffsets != 0) {
@@ -407,11 +397,11 @@
refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
}
} else {
- ClassObject *clazz;
- for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
+ for (ClassObject *clazz = obj->clazz;
+ clazz != NULL;
+ clazz = clazz->super) {
InstField *field = clazz->ifields;
- int i;
- for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
+ for (int i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
void *addr = BYTE_OFFSET((Object *)obj, field->byteOffset);
Object *ref = (Object *)((JValue *)addr)->l;
markObject(ref, ctx);
@@ -425,11 +415,9 @@
*/
static void scanStaticFields(const ClassObject *clazz, GcMarkContext *ctx)
{
- int i;
-
assert(clazz != NULL);
assert(ctx != NULL);
- for (i = 0; i < clazz->sfieldCount; ++i) {
+ for (int i = 0; i < clazz->sfieldCount; ++i) {
char ch = clazz->sfields[i].field.signature[0];
if (ch == '[' || ch == 'L') {
Object *obj = (Object *)clazz->sfields[i].value.l;
@@ -443,11 +431,9 @@
*/
static void scanInterfaces(const ClassObject *clazz, GcMarkContext *ctx)
{
- int i;
-
assert(clazz != NULL);
assert(ctx != NULL);
- for (i = 0; i < clazz->interfaceCount; ++i) {
+ for (int i = 0; i < clazz->interfaceCount; ++i) {
markObject((const Object *)clazz->interfaces[i], ctx);
}
}
@@ -458,13 +444,11 @@
*/
static void scanClassObject(const Object *obj, GcMarkContext *ctx)
{
- const ClassObject *asClass;
-
assert(obj != NULL);
- assert(obj->clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(obj));
assert(ctx != NULL);
markObject((const Object *)obj->clazz, ctx);
- asClass = (const ClassObject *)obj;
+ const ClassObject *asClass = (const ClassObject *)obj;
if (IS_CLASS_FLAG_SET(asClass, CLASS_ISARRAY)) {
markObject((const Object *)asClass->elementClass, ctx);
}
@@ -492,9 +476,8 @@
markObject((const Object *)obj->clazz, ctx);
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
const ArrayObject *array = (const ArrayObject *)obj;
- const Object **contents = (const Object **)array->contents;
- size_t i;
- for (i = 0; i < array->length; ++i) {
+ const Object **contents = (const Object **)(void *)array->contents;
+ for (size_t i = 0; i < array->length; ++i) {
markObject(contents[i], ctx);
}
}
@@ -549,11 +532,9 @@
*/
static void enqueuePendingReference(Object *ref, Object **list)
{
- size_t offset;
-
assert(ref != NULL);
assert(list != NULL);
- offset = gDvm.offJavaLangRefReference_pendingNext;
+ size_t offset = gDvm.offJavaLangRefReference_pendingNext;
if (*list == NULL) {
dvmSetFieldObject(ref, offset, ref);
*list = ref;
@@ -570,13 +551,11 @@
*/
static Object *dequeuePendingReference(Object **list)
{
- Object *ref, *head;
- size_t offset;
-
assert(list != NULL);
assert(*list != NULL);
- offset = gDvm.offJavaLangRefReference_pendingNext;
- head = dvmGetFieldObject(*list, offset);
+ size_t offset = gDvm.offJavaLangRefReference_pendingNext;
+ Object *head = dvmGetFieldObject(*list, offset);
+ Object *ref;
if (*list == head) {
ref = *list;
*list = NULL;
@@ -596,18 +575,15 @@
*/
static void delayReferenceReferent(Object *obj, GcMarkContext *ctx)
{
- GcHeap *gcHeap = gDvm.gcHeap;
- Object *pending, *referent;
- size_t pendingNextOffset, referentOffset;
-
assert(obj != NULL);
assert(obj->clazz != NULL);
assert(IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE));
assert(ctx != NULL);
- pendingNextOffset = gDvm.offJavaLangRefReference_pendingNext;
- referentOffset = gDvm.offJavaLangRefReference_referent;
- pending = dvmGetFieldObject(obj, pendingNextOffset);
- referent = dvmGetFieldObject(obj, referentOffset);
+ GcHeap *gcHeap = gDvm.gcHeap;
+ size_t pendingNextOffset = gDvm.offJavaLangRefReference_pendingNext;
+ size_t referentOffset = gDvm.offJavaLangRefReference_referent;
+ Object *pending = dvmGetFieldObject(obj, pendingNextOffset);
+ Object *referent = dvmGetFieldObject(obj, referentOffset);
if (pending == NULL && referent != NULL && !isMarked(referent, ctx)) {
Object **list = NULL;
if (isSoftReference(obj)) {
@@ -646,11 +622,10 @@
static void scanObject(const Object *obj, GcMarkContext *ctx)
{
assert(obj != NULL);
+ assert(obj->clazz != NULL);
assert(ctx != NULL);
assert(isMarked(obj, ctx));
- assert(obj->clazz != NULL);
- assert(isMarked(obj, ctx));
- if (obj->clazz == gDvm.classJavaLangClass) {
+ if (dvmIsClassObject(obj)) {
scanClassObject(obj, ctx);
} else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
scanArrayObject(obj, ctx);
@@ -665,12 +640,10 @@
*/
static void processMarkStack(GcMarkContext *ctx)
{
- GcMarkStack *stack;
-
assert(ctx != NULL);
assert(ctx->finger == (void *)ULONG_MAX);
- stack = &ctx->stack;
- assert(stack->top >= stack->base);
+ assert(ctx->stack.top >= ctx->stack.base);
+ GcMarkStack *stack = &ctx->stack;
while (stack->top > stack->base) {
const Object *obj = markStackPop(stack);
scanObject(obj, ctx);
@@ -682,6 +655,8 @@
*/
static void scanGrayObjects(GcMarkContext *ctx)
{
+ assert(ctx != NULL);
+ assert(ctx->bitmap != NULL);
HeapBitmap *bitmap = ctx->bitmap;
u1 *base = (u1 *)bitmap->base;
u1 *limit = (u1 *)ALIGN_UP(bitmap->max, GC_CARD_SIZE);
@@ -694,6 +669,7 @@
*/
void dvmHeapScanImmuneObjects(const GcMarkContext *ctx)
{
+ assert(ctx != NULL);
ScanImmuneObjectContext scanCtx;
memset(&scanCtx, 0, sizeof(scanCtx));
scanCtx.threatenBoundary = (Object*)ctx->immuneLimit;
@@ -750,7 +726,7 @@
processMarkStack(ctx);
}
-void dvmHeapReScanMarkedObjects(void)
+void dvmHeapReScanMarkedObjects()
{
GcMarkContext *ctx = &gDvm.gcHeap->markContext;
@@ -778,6 +754,7 @@
*/
static bool isEnqueuable(const Object *reference)
{
+ assert(reference != NULL);
Object *queue = dvmGetFieldObject(reference,
gDvm.offJavaLangRefReference_queue);
Object *queueNext = dvmGetFieldObject(reference,
@@ -804,25 +781,19 @@
*/
static void preserveSomeSoftReferences(Object **list)
{
- GcMarkContext *ctx;
- Object *ref, *referent;
- Object *clear;
- size_t referentOffset;
- size_t counter;
- bool marked;
-
- ctx = &gDvm.gcHeap->markContext;
- referentOffset = gDvm.offJavaLangRefReference_referent;
- clear = NULL;
- counter = 0;
+ assert(list != NULL);
+ GcMarkContext *ctx = &gDvm.gcHeap->markContext;
+ size_t referentOffset = gDvm.offJavaLangRefReference_referent;
+ Object *clear = NULL;
+ size_t counter = 0;
while (*list != NULL) {
- ref = dequeuePendingReference(list);
- referent = dvmGetFieldObject(ref, referentOffset);
+ Object *ref = dequeuePendingReference(list);
+ Object *referent = dvmGetFieldObject(ref, referentOffset);
if (referent == NULL) {
/* Referent was cleared by the user during marking. */
continue;
}
- marked = isMarked(referent, ctx);
+ bool marked = isMarked(referent, ctx);
if (!marked && ((++counter) & 1)) {
/* Referent is white and biased toward saving, mark it. */
markObject(referent, ctx);
@@ -848,15 +819,12 @@
*/
static void clearWhiteReferences(Object **list)
{
- GcMarkContext *ctx;
- Object *ref, *referent;
- size_t referentOffset;
-
- ctx = &gDvm.gcHeap->markContext;
- referentOffset = gDvm.offJavaLangRefReference_referent;
+ assert(list != NULL);
+ GcMarkContext *ctx = &gDvm.gcHeap->markContext;
+ size_t referentOffset = gDvm.offJavaLangRefReference_referent;
while (*list != NULL) {
- ref = dequeuePendingReference(list);
- referent = dvmGetFieldObject(ref, referentOffset);
+ Object *ref = dequeuePendingReference(list);
+ Object *referent = dvmGetFieldObject(ref, referentOffset);
if (referent != NULL && !isMarked(referent, ctx)) {
/* Referent is white, clear it. */
clearReference(ref);
@@ -875,6 +843,7 @@
*/
static void enqueueFinalizerReferences(Object **list)
{
+ assert(list != NULL);
GcMarkContext *ctx = &gDvm.gcHeap->markContext;
size_t referentOffset = gDvm.offJavaLangRefReference_referent;
size_t zombieOffset = gDvm.offJavaLangRefFinalizerReference_zombie;
@@ -907,6 +876,7 @@
*/
void dvmSetFinalizable(Object *obj)
{
+ assert(obj != NULL);
Thread *self = dvmThreadSelf();
assert(self != NULL);
Method *meth = gDvm.methJavaLangRefFinalizerReferenceAdd;
@@ -985,9 +955,7 @@
void dvmHeapFinishMarkStep()
{
- GcMarkContext *ctx;
-
- ctx = &gDvm.gcHeap->markContext;
+ GcMarkContext *ctx = &gDvm.gcHeap->markContext;
/* The mark bits are now not needed.
*/
@@ -1000,16 +968,16 @@
ctx->finger = NULL;
}
-typedef struct {
+struct SweepContext {
size_t numObjects;
size_t numBytes;
bool isConcurrent;
-} SweepContext;
+};
static void sweepBitmapCallback(size_t numPtrs, void **ptrs, void *arg)
{
+ assert(arg != NULL);
SweepContext *ctx = (SweepContext *)arg;
-
if (ctx->isConcurrent) {
dvmLockHeap();
}
@@ -1029,14 +997,13 @@
return !isMarked((Object *)obj, &gDvm.gcHeap->markContext);
}
-void sweepWeakJniGlobals(void)
+void sweepWeakJniGlobals()
{
IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
Object **entry = table->table;
GcMarkContext *ctx = &gDvm.gcHeap->markContext;
int numEntries = dvmIndirectRefTableEntries(table);
- int i;
- for (i = 0; i < numEntries; ++i) {
+ for (int i = 0; i < numEntries; ++i) {
if (entry[i] != NULL && !isMarked(entry[i], ctx)) {
entry[i] = NULL;
}
@@ -1047,7 +1014,7 @@
* Process all the internal system structures that behave like
* weakly-held objects.
*/
-void dvmHeapSweepSystemWeaks(void)
+void dvmHeapSweepSystemWeaks()
{
dvmGcDetachDeadInternedStrings(isUnmarkedObject);
dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
@@ -1066,7 +1033,6 @@
SweepContext ctx;
HeapBitmap *prevLive, *prevMark;
size_t numHeaps, numSweepHeaps;
- size_t i;
numHeaps = dvmHeapSourceGetNumHeaps();
dvmHeapSourceGetRegions(base, max, NULL, numHeaps);
@@ -1080,7 +1046,7 @@
ctx.isConcurrent = isConcurrent;
prevLive = dvmHeapSourceGetMarkBits();
prevMark = dvmHeapSourceGetLiveBits();
- for (i = 0; i < numSweepHeaps; ++i) {
+ for (size_t i = 0; i < numSweepHeaps; ++i) {
dvmHeapBitmapSweepWalk(prevLive, prevMark, base[i], max[i],
sweepBitmapCallback, &ctx);
}
diff --git a/vm/alloc/MarkSweep.h b/vm/alloc/MarkSweep.h
index 94bf3ad..efad032 100644
--- a/vm/alloc/MarkSweep.h
+++ b/vm/alloc/MarkSweep.h
@@ -19,7 +19,7 @@
#include "alloc/HeapBitmap.h"
#include "alloc/HeapSource.h"
-typedef struct {
+struct GcMarkStack {
/* Highest address (exclusive)
*/
const Object **limit;
@@ -35,16 +35,16 @@
/* Maximum stack size, in bytes.
*/
size_t length;
-} GcMarkStack;
+};
/* This is declared publicly so that it can be included in gDvm.gcHeap.
*/
-typedef struct {
+struct GcMarkContext {
HeapBitmap *bitmap;
GcMarkStack stack;
const char *immuneLimit;
const void *finger; // only used while scanning/recursing.
-} GcMarkContext;
+};
bool dvmHeapBeginMarkStep(bool isPartial);
void dvmHeapMarkRootSet(void);
diff --git a/vm/alloc/Verify.c b/vm/alloc/Verify.cpp
similarity index 98%
rename from vm/alloc/Verify.c
rename to vm/alloc/Verify.cpp
index f36f44b..1a8307a 100644
--- a/vm/alloc/Verify.c
+++ b/vm/alloc/Verify.cpp
@@ -145,7 +145,7 @@
/*
* Verifies references in the roots.
*/
-void dvmVerifyRoots(void)
+void dvmVerifyRoots()
{
dvmVisitRoots(verifyRootReference, NULL);
}
diff --git a/vm/alloc/Visit.c b/vm/alloc/Visit.cpp
similarity index 93%
rename from vm/alloc/Visit.c
rename to vm/alloc/Visit.cpp
index 6ca1439..7f949f6 100644
--- a/vm/alloc/Visit.c
+++ b/vm/alloc/Visit.cpp
@@ -36,12 +36,10 @@
static void visitHashTable(RootVisitor *visitor, HashTable *table,
RootType type, void *arg)
{
- int i;
-
assert(visitor != NULL);
assert(table != NULL);
dvmHashTableLock(table);
- for (i = 0; i < table->tableSize; ++i) {
+ for (int i = 0; i < table->tableSize; ++i) {
HashEntry *entry = &table->pEntries[i];
if (entry->data != NULL && entry->data != HASH_TOMBSTONE) {
(*visitor)(&entry->data, 0, type, arg);
@@ -56,11 +54,9 @@
static void visitReferenceTable(RootVisitor *visitor, ReferenceTable *table,
u4 threadId, RootType type, void *arg)
{
- Object **entry;
-
assert(visitor != NULL);
assert(table != NULL);
- for (entry = table->table; entry < table->nextEntry; ++entry) {
+ for (Object **entry = table->table; entry < table->nextEntry; ++entry) {
assert(entry != NULL);
(*visitor)(entry, threadId, type, arg);
}
@@ -76,8 +72,7 @@
assert(table != NULL);
Object **entry = table->table;
int numEntries = dvmIndirectRefTableEntries(table);
- int i;
- for (i = 0; i < numEntries; ++i) {
+ for (int i = 0; i < numEntries; ++i) {
(*visitor)(&entry[i], threadId, type, arg);
}
}
@@ -88,23 +83,19 @@
*/
static void visitThreadStack(RootVisitor *visitor, Thread *thread, void *arg)
{
- const StackSaveArea *saveArea;
- u4 *fp;
- u4 threadId;
-
assert(visitor != NULL);
assert(thread != NULL);
- threadId = thread->threadId;
- fp = (u4 *)thread->curFrame;
- for (; fp != NULL; fp = (u4 *)saveArea->prevFrame) {
+ u4 threadId = thread->threadId;
+ const StackSaveArea *saveArea;
+ for (u4 *fp = (u4 *)thread->interpSave.curFrame;
+ fp != NULL;
+ fp = (u4 *)saveArea->prevFrame) {
Method *method;
saveArea = SAVEAREA_FROM_FP(fp);
method = (Method *)saveArea->method;
if (method != NULL && !dvmIsNativeMethod(method)) {
const RegisterMap* pMap = dvmGetExpandedRegisterMap(method);
const u1* regVector = NULL;
- size_t i;
-
if (pMap != NULL) {
/* found map, get registers for this address */
int addr = saveArea->xtra.currentPc - method->insns;
@@ -116,7 +107,7 @@
* info for the current PC. Perform a conservative
* scan.
*/
- for (i = 0; i < method->registersSize; ++i) {
+ for (size_t i = 0; i < method->registersSize; ++i) {
if (dvmIsValidObject((Object *)fp[i])) {
(*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg);
}
@@ -131,7 +122,7 @@
* A '1' bit indicates a live reference.
*/
u2 bits = 1 << 1;
- for (i = 0; i < method->registersSize; ++i) {
+ for (size_t i = 0; i < method->registersSize; ++i) {
bits >>= 1;
if (bits == 1) {
/* set bit 9 so we can tell when we're empty */
diff --git a/vm/alloc/Visit.h b/vm/alloc/Visit.h
index a66839d..f9016f3 100644
--- a/vm/alloc/Visit.h
+++ b/vm/alloc/Visit.h
@@ -19,7 +19,7 @@
#include "Dalvik.h"
-typedef enum {
+enum RootType {
ROOT_UNKNOWN = 0,
ROOT_JNI_GLOBAL,
ROOT_JNI_LOCAL,
@@ -33,7 +33,7 @@
ROOT_DEBUGGER,
ROOT_VM_INTERNAL,
ROOT_JNI_MONITOR,
-} RootType;
+};
/*
* Callback invoked with the address of a reference and a user
diff --git a/vm/alloc/VisitInlines.h b/vm/alloc/VisitInlines.h
index 7f90678..94b55bc 100644
--- a/vm/alloc/VisitInlines.h
+++ b/vm/alloc/VisitInlines.h
@@ -35,11 +35,11 @@
refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
}
} else {
- ClassObject *clazz;
- for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
+ for (ClassObject *clazz = obj->clazz;
+ clazz != NULL;
+ clazz = clazz->super) {
InstField *field = clazz->ifields;
- int i;
- for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
+ for (int i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
size_t offset = field->byteOffset;
Object **ref = (Object **)BYTE_OFFSET(obj, offset);
(*visitor)(ref, arg);
@@ -54,11 +54,9 @@
static void visitStaticFields(Visitor *visitor, ClassObject *clazz,
void *arg)
{
- int i;
-
assert(visitor != NULL);
assert(clazz != NULL);
- for (i = 0; i < clazz->sfieldCount; ++i) {
+ for (int i = 0; i < clazz->sfieldCount; ++i) {
char ch = clazz->sfields[i].field.signature[0];
if (ch == '[' || ch == 'L') {
(*visitor)(&clazz->sfields[i].value.l, arg);
@@ -72,11 +70,9 @@
static void visitInterfaces(Visitor *visitor, ClassObject *clazz,
void *arg)
{
- int i;
-
assert(visitor != NULL);
assert(clazz != NULL);
- for (i = 0; i < clazz->interfaceCount; ++i) {
+ for (int i = 0; i < clazz->interfaceCount; ++i) {
(*visitor)(&clazz->interfaces[i], arg);
}
}
@@ -120,9 +116,8 @@
(*visitor)(&obj->clazz, arg);
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
ArrayObject *array = (ArrayObject *)obj;
- Object **contents = (Object **)array->contents;
- size_t i;
- for (i = 0; i < array->length; ++i) {
+ Object **contents = (Object **)(void *)array->contents;
+ for (size_t i = 0; i < array->length; ++i) {
(*visitor)(&contents[i], arg);
}
}
@@ -164,7 +159,7 @@
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
- if (obj->clazz == gDvm.classJavaLangClass) {
+ if (dvmIsClassObject(obj)) {
visitClassObject(visitor, obj, arg);
} else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
visitArrayObject(visitor, obj, arg);
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.cpp
similarity index 99%
rename from vm/analysis/CodeVerify.c
rename to vm/analysis/CodeVerify.cpp
index 2d00ebd..931569f 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.cpp
@@ -37,11 +37,11 @@
* we either only need it at branch points (for verification) or GC points
* and branches (for verification + type-precise register analysis).
*/
-typedef enum RegisterTrackingMode {
+enum RegisterTrackingMode {
kTrackRegsBranches,
kTrackRegsGcPoints,
kTrackRegsAll
-} RegisterTrackingMode;
+};
/*
* Set this to enable dead code scanning. This is not required, but it's
@@ -105,7 +105,7 @@
/* fwd */
#ifndef NDEBUG
-static void checkMergeTab(void);
+static void checkMergeTab();
#endif
static bool isInitMethod(const Method* meth);
static RegType getInvocationThis(const RegisterLine* registerLine,\
@@ -218,7 +218,7 @@
/*
* Verify symmetry in the conversion table.
*/
-static void checkMergeTab(void)
+static void checkMergeTab()
{
int i, j;
@@ -737,6 +737,7 @@
DexParameterIterator iterator;
int actualArgs, expectedArgs, argStart;
VerifyError failure = VERIFY_ERROR_NONE;
+ const char* descriptor;
dexParameterIteratorInit(&iterator, &meth->prototype);
argStart = meth->registersSize - meth->insSize;
@@ -766,7 +767,7 @@
}
for (;;) {
- const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
+ descriptor = dexParameterIteratorNextDescriptor(&iterator);
if (descriptor == NULL) {
break;
@@ -843,7 +844,7 @@
goto bad_sig;
}
- const char* descriptor = dexProtoGetReturnType(&meth->prototype);
+ descriptor = dexProtoGetReturnType(&meth->prototype);
/*
* Validate return type. We don't do the type lookup; just want to make
@@ -1063,6 +1064,9 @@
{
Method* resMethod;
char* sigOriginal = NULL;
+ const char* sig;
+ int expectedArgs;
+ int actualArgs;
/*
* Resolve the method. This could be an abstract or concrete method
@@ -1162,9 +1166,9 @@
* have register count values).
*/
sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype);
- const char* sig = sigOriginal;
- int expectedArgs = pDecInsn->vA;
- int actualArgs = 0;
+ sig = sigOriginal;
+ expectedArgs = pDecInsn->vA;
+ actualArgs = 0;
/* caught by static verifier */
assert(isRange || expectedArgs <= 5);
@@ -1816,12 +1820,12 @@
* We treat object references separately, so we have "category1nr". We
* don't support jsr/ret, so there is no "returnAddress" type.
*/
-typedef enum TypeCategory {
+enum TypeCategory {
kTypeCategoryUnknown = 0,
kTypeCategory1nr, // boolean, byte, char, short, int, float
kTypeCategory2, // long, double
kTypeCategoryRef, // object reference
-} TypeCategory;
+};
/*
* See if "type" matches "cat". All we're really looking for here is that
@@ -3176,6 +3180,7 @@
{
VerifyErrorRefType refType;
u2* oldInsns = (u2*) meth->insns + insnIdx;
+ int width;
bool result = false;
if (gDvm.optimizing)
@@ -3290,7 +3295,7 @@
assert((dexGetFlagsFromOpcode(opcode) & kInstrCanThrow) != 0);
/* write a NOP over the third code unit, if necessary */
- int width = dvmInsnGetWidth(insnFlags, insnIdx);
+ width = dvmInsnGetWidth(insnFlags, insnIdx);
switch (width) {
case 2:
case 4:
@@ -3423,7 +3428,7 @@
/*
* One-time preparation.
*/
-static void verifyPrep(void)
+static void verifyPrep()
{
#ifndef NDEBUG
/* only need to do this if the table was updated */
diff --git a/vm/analysis/CodeVerify.h b/vm/analysis/CodeVerify.h
index 9369537..1eb27b9 100644
--- a/vm/analysis/CodeVerify.h
+++ b/vm/analysis/CodeVerify.h
@@ -23,7 +23,6 @@
#include "analysis/VerifySubs.h"
#include "analysis/VfyBasicBlock.h"
-
/*
* Enumeration for register type values. The "hi" piece of a 64-bit value
* MUST immediately follow the "lo" piece in the enumeration, so we can check
@@ -126,32 +125,32 @@
* track the liveness of the method result register (which is not visible
* to the GC).
*/
-typedef struct {
+struct RegisterLine {
RegType* regTypes;
MonitorEntries* monitorEntries;
u4* monitorStack;
unsigned int monitorStackTop;
BitVector* liveRegs;
-} RegisterLine;
+};
/*
* Table that maps uninitialized instances to classes, based on the
* address of the new-instance instruction. One per method.
*/
-typedef struct UninitInstanceMap {
+struct UninitInstanceMap {
int numEntries;
struct {
int addr; /* code offset, or -1 for method arg ("this") */
ClassObject* clazz; /* class created at this address */
} map[1];
-} UninitInstanceMap;
+};
#define kUninitThisArgAddr (-1)
#define kUninitThisArgSlot 0
/*
* Various bits of data used by the verifier and register map generator.
*/
-typedef struct VerifierData {
+struct VerifierData {
/*
* The method we're working on.
*/
@@ -200,7 +199,7 @@
* for liveness analysis.
*/
VfyBasicBlock** basicBlocks;
-} VerifierData;
+};
/* table with static merge logic for primitive types */
diff --git a/vm/analysis/DexPrepare.c b/vm/analysis/DexPrepare.cpp
similarity index 98%
rename from vm/analysis/DexPrepare.c
rename to vm/analysis/DexPrepare.cpp
index fce09e2..4337ffa 100644
--- a/vm/analysis/DexPrepare.c
+++ b/vm/analysis/DexPrepare.cpp
@@ -113,10 +113,9 @@
* working on it, we'll block here until they complete. Because
* we're waiting on an external resource, we go into VMWAIT mode.
*/
- int oldStatus;
LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n",
cacheFileName, fd, isBootstrap);
- oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
+ ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
cc = flock(fd, LOCK_EX | LOCK_NB);
if (cc != 0) {
LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName);
@@ -332,10 +331,10 @@
int bcpSize = dvmGetBootPathSize();
int argc = kFixedArgCount + bcpSize
+ (kValgrindArgCount * kUseValgrind);
- char* argv[argc+1]; // last entry is NULL
+ const char* argv[argc+1]; // last entry is NULL
char values[argc][kMaxIntLen];
char* execFile;
- char* androidRoot;
+ const char* androidRoot;
int flags;
/* change process groups, so we don't clash with ProcessManager */
@@ -419,9 +418,9 @@
argv[curArg] = NULL;
if (kUseValgrind)
- execv(kValgrinder, argv);
+ execv(kValgrinder, const_cast<char**>(argv));
else
- execv(execFile, argv);
+ execv(execFile, const_cast<char**>(argv));
LOGE("execv '%s'%s failed: %s\n", execFile,
kUseValgrind ? " [valgrind]" : "", strerror(errno));
@@ -430,13 +429,12 @@
LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid);
int status;
pid_t gotPid;
- int oldStatus;
/*
* Wait for the optimization process to finish. We go into VMWAIT
* mode here so GC suspension won't have to wait for us.
*/
- oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
+ ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
while (true) {
gotPid = waitpid(pid, &status, 0);
if (gotPid == -1 && errno == EINTR) {
@@ -750,6 +748,7 @@
u8 prepWhen, loadWhen, verifyOptWhen;
DvmDex* pDvmDex = NULL;
bool result = false;
+ const char* msgStr = "???";
/* if the DEX is in the wrong byte order, swap it now */
if (dexSwapAndVerify(addr, len) != 0)
@@ -815,7 +814,6 @@
verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt);
verifyOptWhen = dvmGetRelativeTimeUsec();
- const char* msgStr = "???";
if (doVerify && doOpt)
msgStr = "verify+opt";
else if (doVerify)
@@ -1174,15 +1172,17 @@
*
* The only thing we really can't handle is incorrect byte ordering.
*/
- const u4 matchMask = DEX_OPT_FLAG_BIG;
- u4 expectedFlags = 0;
+ {
+ const u4 matchMask = DEX_OPT_FLAG_BIG;
+ u4 expectedFlags = 0;
#if __BYTE_ORDER != __LITTLE_ENDIAN
- expectedFlags |= DEX_OPT_FLAG_BIG;
+ expectedFlags |= DEX_OPT_FLAG_BIG;
#endif
- if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
- LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
- expectedFlags, optHdr.flags, matchMask);
- goto bail;
+ if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
+ LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
+ expectedFlags, optHdr.flags, matchMask);
+ goto bail;
+ }
}
posn = lseek(fd, optHdr.depsOffset, SEEK_SET);
diff --git a/vm/analysis/DexPrepare.h b/vm/analysis/DexPrepare.h
index 0ee76e5..9e43f26 100644
--- a/vm/analysis/DexPrepare.h
+++ b/vm/analysis/DexPrepare.h
@@ -27,13 +27,13 @@
* Optimizing is performed ahead-of-time by dexopt and, in some cases, at
* load time by the VM.
*/
-typedef enum DexOptimizerMode {
+enum DexOptimizerMode {
OPTIMIZE_MODE_UNKNOWN = 0,
OPTIMIZE_MODE_NONE, /* never optimize (except "essential") */
OPTIMIZE_MODE_VERIFIED, /* only optimize verified classes (default) */
OPTIMIZE_MODE_ALL, /* optimize verified & unverified (risky) */
OPTIMIZE_MODE_FULL /* fully opt verified classes at load time */
-} DexOptimizerMode;
+};
/* some additional bit flags for dexopt */
enum DexoptFlags {
@@ -50,7 +50,7 @@
/*
* An enumeration of problems that can turn up during verification.
*/
-typedef enum VerifyError {
+enum VerifyError {
VERIFY_ERROR_NONE = 0, /* no error; must be zero */
VERIFY_ERROR_GENERIC, /* VerifyError */
@@ -62,7 +62,7 @@
VERIFY_ERROR_ACCESS_METHOD, /* IllegalAccessError */
VERIFY_ERROR_CLASS_CHANGE, /* IncompatibleClassChangeError */
VERIFY_ERROR_INSTANTIATION, /* InstantiationError */
-} VerifyError;
+};
/*
* Identifies the type of reference in the instruction that generated the
@@ -71,11 +71,11 @@
*
* This must fit in two bits.
*/
-typedef enum VerifyErrorRefType {
+enum VerifyErrorRefType {
VERIFY_ERROR_REF_CLASS = 0,
VERIFY_ERROR_REF_FIELD = 1,
VERIFY_ERROR_REF_METHOD = 2,
-} VerifyErrorRefType;
+};
#define kVerifyErrorRefTypeShift 6
diff --git a/vm/analysis/DexVerify.c b/vm/analysis/DexVerify.cpp
similarity index 100%
rename from vm/analysis/DexVerify.c
rename to vm/analysis/DexVerify.cpp
diff --git a/vm/analysis/DexVerify.h b/vm/analysis/DexVerify.h
index 90a724f..d98cee9 100644
--- a/vm/analysis/DexVerify.h
+++ b/vm/analysis/DexVerify.h
@@ -25,12 +25,25 @@
* to most. If we're using "exact GC", we may need to perform some of
* the verification steps anyway.
*/
-typedef enum {
+enum DexClassVerifyMode {
VERIFY_MODE_UNKNOWN = 0,
VERIFY_MODE_NONE,
VERIFY_MODE_REMOTE,
VERIFY_MODE_ALL
-} DexClassVerifyMode;
+};
+
+/* some verifier counters, for debugging */
+struct VerifierStats {
+ size_t methodsExamined; /* number of methods examined */
+ size_t monEnterMethods; /* number of methods with monitor-enter */
+ size_t instrsExamined; /* incr on first visit of instruction */
+ size_t instrsReexamined; /* incr on each repeat visit of instruction */
+ size_t copyRegCount; /* calls from updateRegisters->copyRegisters */
+ size_t mergeRegCount; /* calls from updateRegisters->merge */
+ size_t mergeRegChanged; /* calls from updateRegisters->merge, changed */
+ size_t uninitSearches; /* times we've had to search the uninit table */
+ size_t biggestAlloc; /* largest RegisterLine table alloc */
+};
/*
* Certain types of instructions can be GC points. To support precise
@@ -50,17 +63,4 @@
*/
void dvmFreeRegisterMap(RegisterMap* pMap);
-/* some verifier counters, for debugging */
-typedef struct {
- size_t methodsExamined; /* number of methods examined */
- size_t monEnterMethods; /* number of methods with monitor-enter */
- size_t instrsExamined; /* incr on first visit of instruction */
- size_t instrsReexamined; /* incr on each repeat visit of instruction */
- size_t copyRegCount; /* calls from updateRegisters->copyRegisters */
- size_t mergeRegCount; /* calls from updateRegisters->merge */
- size_t mergeRegChanged; /* calls from updateRegisters->merge, changed */
- size_t uninitSearches; /* times we've had to search the uninit table */
- size_t biggestAlloc; /* largest RegisterLine table alloc */
-} VerifierStats;
-
#endif /*_DALVIK_DEXVERIFY*/
diff --git a/vm/analysis/Liveness.c b/vm/analysis/Liveness.cpp
similarity index 98%
rename from vm/analysis/Liveness.c
rename to vm/analysis/Liveness.cpp
index 2f5173b..f659e89 100644
--- a/vm/analysis/Liveness.c
+++ b/vm/analysis/Liveness.cpp
@@ -44,9 +44,8 @@
if (widths == NULL)
return NULL;
- unsigned int idx;
u4 insnWidth = 0;
- for (idx = 0; idx < vdata->insnsSize; ) {
+ for (u4 idx = 0; idx < vdata->insnsSize; ) {
widths[idx] = insnWidth;
insnWidth = dvmInsnGetWidth(vdata->insnFlags, idx);
idx += insnWidth;
@@ -97,10 +96,8 @@
* TODO: consider creating a "dense" array of basic blocks to make
* the walking faster.
*/
- int iter = 0;
- while (true) {
+ for (int iter = 0;;) {
VfyBasicBlock* workBlock = NULL;
- unsigned int idx;
if (iter++ > 100000) {
LOG_VFY_METH(vdata->method, "oh dear");
@@ -121,7 +118,7 @@
assert(startGuess->changed);
workBlock = startGuess;
} else {
- for (idx = 0; idx < vdata->insnsSize; idx++) {
+ for (u4 idx = 0; idx < vdata->insnsSize; idx++) {
VfyBasicBlock* block = vdata->basicBlocks[idx];
if (block == NULL)
continue;
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.cpp
similarity index 99%
rename from vm/analysis/Optimize.c
rename to vm/analysis/Optimize.cpp
index be59471..8ac5e0e 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.cpp
@@ -20,6 +20,7 @@
*/
#include "Dalvik.h"
#include "libdex/InstrUtils.h"
+#include "Optimize.h"
#include <zlib.h>
@@ -61,7 +62,7 @@
* TODO: this is currently just a linear array. We will want to put this
* into a hash table as the list size increases.
*/
-bool dvmCreateInlineSubsTable(void)
+bool dvmCreateInlineSubsTable()
{
const InlineOperation* ops = dvmGetInlineOpsTable();
const int count = dvmGetInlineOpsTableLength();
@@ -105,7 +106,7 @@
/*
* Release inline sub data structure.
*/
-void dvmFreeInlineSubsTable(void)
+void dvmFreeInlineSubsTable()
{
free(gDvm.inlineSubs);
gDvm.inlineSubs = NULL;
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.cpp
similarity index 97%
rename from vm/analysis/RegisterMap.c
rename to vm/analysis/RegisterMap.cpp
index 8725ec0..37b2116 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.cpp
@@ -21,6 +21,7 @@
* interpreter thread stacks.
*/
#include "Dalvik.h"
+#include "UniquePtr.h"
#include "analysis/CodeVerify.h"
#include "analysis/RegisterMap.h"
#include "libdex/DexCatch.h"
@@ -57,7 +58,7 @@
#define kUpdatePosnMinRegs 24
#define kNumUpdatePosns 8
#define kMaxDiffBits 20
-typedef struct MapStats {
+struct MapStats {
/*
* Buckets measuring the distance between GC points. This tells us how
* many bits we need to encode the advancing program counter. We ignore
@@ -102,13 +103,13 @@
*/
int numExpandedMaps;
int totalExpandedMapSize;
-} MapStats;
+};
#endif
/*
* Prepare some things.
*/
-bool dvmRegisterMapStartup(void)
+bool dvmRegisterMapStartup()
{
#ifdef REGISTER_MAP_STATS
MapStats* pStats = calloc(1, sizeof(MapStats));
@@ -120,7 +121,7 @@
/*
* Clean up.
*/
-void dvmRegisterMapShutdown(void)
+void dvmRegisterMapShutdown()
{
#ifdef REGISTER_MAP_STATS
free(gDvm.registerMapStats);
@@ -130,7 +131,7 @@
/*
* Write stats to log file.
*/
-void dvmRegisterMapDumpStats(void)
+void dvmRegisterMapDumpStats()
{
#ifdef REGISTER_MAP_STATS
MapStats* pStats = (MapStats*) gDvm.registerMapStats;
@@ -310,7 +311,7 @@
}
/* verify succeeded */
- free(pUncompMap);
+ delete pUncompMap;
}
}
@@ -1443,7 +1444,6 @@
{
RegisterMap* pNewMap = NULL;
int origSize = computeRegisterMapSize(pMap);
- u1* tmpBuf = NULL;
u1* tmpPtr;
int addrWidth, regWidth, numEntries;
bool debug = false;
@@ -1465,7 +1465,7 @@
break;
default:
LOGE("ERROR: can't compress map with format=%d\n", format);
- goto bail;
+ return NULL;
}
regWidth = dvmRegisterMapGetRegWidth(pMap);
@@ -1480,7 +1480,7 @@
if (numEntries <= 1) {
LOGV("Can't compress map with 0 or 1 entries\n");
- goto bail;
+ return NULL;
}
/*
@@ -1500,11 +1500,11 @@
* or equal to the amount of space required when uncompressed -- large
* initial offsets are rejected.
*/
- tmpBuf = (u1*) malloc(origSize + (1 + 3 + regWidth));
- if (tmpBuf == NULL)
- goto bail;
+ UniquePtr<u1[]> tmpBuf(new u1[origSize + (1 + 3 + regWidth)]);
+ if (tmpBuf.get() == NULL)
+ return NULL;
- tmpPtr = tmpBuf;
+ tmpPtr = tmpBuf.get();
const u1* mapData = pMap->data;
const u1* prevBits;
@@ -1516,7 +1516,7 @@
if (addr >= 128) {
LOGV("Can't compress map with starting address >= 128\n");
- goto bail;
+ return NULL;
}
/*
@@ -1537,8 +1537,7 @@
/*
* Loop over all following entries.
*/
- int entry;
- for (entry = 1; entry < numEntries; entry++) {
+ for (int entry = 1; entry < numEntries; entry++) {
int addrDiff;
u1 key;
@@ -1627,13 +1626,13 @@
/*
* See if we've run past the original size.
*/
- if (tmpPtr - tmpBuf >= origSize) {
+ if (tmpPtr - tmpBuf.get() >= origSize) {
if (debug) {
LOGD("Compressed size >= original (%d vs %d): %s.%s\n",
- tmpPtr - tmpBuf, origSize,
+ tmpPtr - tmpBuf.get(), origSize,
meth->clazz->descriptor, meth->name);
}
- goto bail;
+ return NULL;
}
}
@@ -1644,7 +1643,7 @@
* get poorer compression but potentially use less native heap space.
*/
static const int kHeaderSize = offsetof(RegisterMap, data);
- int newDataSize = tmpPtr - tmpBuf;
+ int newDataSize = tmpPtr - tmpBuf.get();
int newMapSize;
newMapSize = kHeaderSize + unsignedLeb128Size(newDataSize) + newDataSize;
@@ -1653,12 +1652,12 @@
LOGD("Final comp size >= original (%d vs %d): %s.%s\n",
newMapSize, origSize, meth->clazz->descriptor, meth->name);
}
- goto bail;
+ return NULL;
}
pNewMap = (RegisterMap*) malloc(newMapSize);
if (pNewMap == NULL)
- goto bail;
+ return NULL;
dvmRegisterMapSetFormat(pNewMap, kRegMapFormatDifferential);
dvmRegisterMapSetOnHeap(pNewMap, true);
dvmRegisterMapSetRegWidth(pNewMap, regWidth);
@@ -1666,7 +1665,7 @@
tmpPtr = pNewMap->data;
tmpPtr = writeUnsignedLeb128(tmpPtr, newDataSize);
- memcpy(tmpPtr, tmpBuf, newDataSize);
+ memcpy(tmpPtr, tmpBuf.get(), newDataSize);
if (REGISTER_MAP_VERBOSE) {
LOGD("Compression successful (%d -> %d) from aw=%d rw=%d ne=%d\n",
@@ -1674,8 +1673,6 @@
addrWidth, regWidth, numEntries);
}
-bail:
- free(tmpBuf);
return pNewMap;
}
@@ -1697,7 +1694,6 @@
*/
static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap)
{
- RegisterMap* pNewMap = NULL;
static const int kHeaderSize = offsetof(RegisterMap, data);
u1 format = dvmRegisterMapGetFormat(pMap);
RegisterMapFormat newFormat;
@@ -1705,7 +1701,7 @@
if (format != kRegMapFormatDifferential) {
LOGE("Not differential (%d)\n", format);
- goto bail;
+ return NULL;
}
regWidth = dvmRegisterMapGetRegWidth(pMap);
@@ -1733,9 +1729,10 @@
newAddrWidth, regWidth, numEntries);
}
newMapSize = kHeaderSize + (newAddrWidth + regWidth) * numEntries;
- pNewMap = (RegisterMap*) malloc(newMapSize);
+ RegisterMap* pNewMap = (RegisterMap*) malloc(newMapSize);
+
if (pNewMap == NULL)
- goto bail;
+ return NULL;
dvmRegisterMapSetFormat(pNewMap, newFormat);
dvmRegisterMapSetOnHeap(pNewMap, true);
@@ -1816,13 +1813,15 @@
if (dstPtr - (u1*) pNewMap != newMapSize) {
LOGE("ERROR: output %d bytes, expected %d\n",
dstPtr - (u1*) pNewMap, newMapSize);
- goto bail;
+ free(pNewMap);
+ return NULL;
}
if (srcPtr - srcStart != expectedSrcLen) {
LOGE("ERROR: consumed %d bytes, expected %d\n",
srcPtr - srcStart, expectedSrcLen);
- goto bail;
+ free(pNewMap);
+ return NULL;
}
if (REGISTER_MAP_VERBOSE) {
@@ -1831,8 +1830,4 @@
}
return pNewMap;
-
-bail:
- free(pNewMap);
- return NULL;
}
diff --git a/vm/analysis/RegisterMap.h b/vm/analysis/RegisterMap.h
index 886d0b0..2f34c39 100644
--- a/vm/analysis/RegisterMap.h
+++ b/vm/analysis/RegisterMap.h
@@ -28,7 +28,7 @@
/*
* Format enumeration for RegisterMap data area.
*/
-typedef enum RegisterMapFormat {
+enum RegisterMapFormat {
kRegMapFormatUnknown = 0,
kRegMapFormatNone, /* indicates no map data follows */
kRegMapFormatCompact8, /* compact layout, 8-bit addresses */
@@ -36,7 +36,7 @@
kRegMapFormatDifferential, /* compressed, differential encoding */
kRegMapFormatOnHeap = 0x80, /* bit flag, indicates allocation on heap */
-} RegisterMapFormat;
+};
/*
* This is a single variable-size structure. It may be allocated on the
@@ -159,12 +159,12 @@
*
* These structures are 32-bit aligned.
*/
-typedef struct RegisterMapMethodPool {
+struct RegisterMapMethodPool {
u2 methodCount; /* chiefly used as a sanity check */
/* stream of per-method data starts here */
u4 methodData[1];
-} RegisterMapMethodPool;
+};
/*
* Header for the memory-mapped RegisterMap pool in the DEX file.
@@ -177,12 +177,12 @@
*
* These structures are 32-bit aligned.
*/
-typedef struct RegisterMapClassPool {
+struct RegisterMapClassPool {
u4 numClasses;
/* offset table starts here, 32-bit aligned; offset==0 means no data */
u4 classDataOffset[1];
-} RegisterMapClassPool;
+};
/*
* Find the register maps for this class. (Used during class loading.)
@@ -209,14 +209,14 @@
* In particular, it keeps track of our temporary mmap region so we can
* free it later.
*/
-typedef struct RegisterMapBuilder {
+struct RegisterMapBuilder {
/* public */
void* data;
size_t size;
/* private */
MemMapping memMap;
-} RegisterMapBuilder;
+};
/*
* Generate a register map set for all verified classes in "pDvmDex".
diff --git a/vm/analysis/VerifySubs.c b/vm/analysis/VerifySubs.cpp
similarity index 100%
rename from vm/analysis/VerifySubs.c
rename to vm/analysis/VerifySubs.cpp
diff --git a/vm/analysis/VfyBasicBlock.c b/vm/analysis/VfyBasicBlock.cpp
similarity index 99%
rename from vm/analysis/VfyBasicBlock.c
rename to vm/analysis/VfyBasicBlock.cpp
index 7500ba0..7a6b672 100644
--- a/vm/analysis/VfyBasicBlock.c
+++ b/vm/analysis/VfyBasicBlock.cpp
@@ -326,7 +326,7 @@
vdata->basicBlocks =
(VfyBasicBlock**) calloc(insnsSize, sizeof(VfyBasicBlock*));
if (vdata->basicBlocks == NULL)
- goto bail;
+ return false;
/*
* The "tries" list is a series of non-overlapping regions with a list
diff --git a/vm/analysis/VfyBasicBlock.h b/vm/analysis/VfyBasicBlock.h
index ff2c680..6d1d76f 100644
--- a/vm/analysis/VfyBasicBlock.h
+++ b/vm/analysis/VfyBasicBlock.h
@@ -39,14 +39,14 @@
* the RegisterLine for the last instruction in the block (which reflects
* the state *before* the instruction has executed).
*/
-typedef struct {
+struct VfyBasicBlock {
u4 firstAddr; /* address of first instruction */
u4 lastAddr; /* address of last instruction */
PointerSet* predecessors; /* set of basic blocks that can flow here */
BitVector* liveRegs; /* liveness for each register */
bool changed; /* input set has changed, must re-eval */
bool visited; /* block has been visited at least once */
-} VfyBasicBlock;
+};
/*
* Generate a list of basic blocks.
diff --git a/vm/arch/arm/HintsEABI.c b/vm/arch/arm/HintsEABI.cpp
similarity index 100%
rename from vm/arch/arm/HintsEABI.c
rename to vm/arch/arm/HintsEABI.cpp
diff --git a/vm/arch/generic/Call.c b/vm/arch/generic/Call.cpp
similarity index 100%
rename from vm/arch/generic/Call.c
rename to vm/arch/generic/Call.cpp
diff --git a/vm/arch/generic/Hints.c b/vm/arch/generic/Hints.cpp
similarity index 100%
rename from vm/arch/generic/Hints.c
rename to vm/arch/generic/Hints.cpp
diff --git a/vm/arch/x86-atom/Hints386ABI.c b/vm/arch/x86-atom/Hints386ABI.cpp
similarity index 100%
rename from vm/arch/x86-atom/Hints386ABI.c
rename to vm/arch/x86-atom/Hints386ABI.cpp
diff --git a/vm/arch/x86/Hints386ABI.c b/vm/arch/x86/Hints386ABI.cpp
similarity index 100%
rename from vm/arch/x86/Hints386ABI.c
rename to vm/arch/x86/Hints386ABI.cpp
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.cpp
similarity index 98%
rename from vm/compiler/Compiler.c
rename to vm/compiler/Compiler.cpp
index 4f2261b..99533b7 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.cpp
@@ -22,6 +22,9 @@
#include "interp/Jit.h"
#include "CompilerInternals.h"
+extern "C" void dvmCompilerTemplateStart(void);
+extern "C" void dmvCompilerTemplateEnd(void);
+
static inline bool workQueueLength(void)
{
return gDvmJit.compilerQueueLength;
@@ -99,8 +102,8 @@
*/
if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE ||
gDvmJit.codeCacheFull == true) {
- result = false;
- goto unlockAndExit;
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ return false;
}
for (numWork = gDvmJit.compilerQueueLength,
@@ -108,8 +111,10 @@
numWork > 0;
numWork--) {
/* Already enqueued */
- if (gDvmJit.compilerWorkQueue[i++].pc == pc)
- goto unlockAndExit;
+ if (gDvmJit.compilerWorkQueue[i++].pc == pc) {
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ return true;
+ }
/* Wrap around */
if (i == COMPILER_WORK_QUEUE_SIZE)
i = 0;
@@ -134,7 +139,6 @@
cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
assert(cc == 0);
-unlockAndExit:
dvmUnlockMutex(&gDvmJit.compilerLock);
return result;
}
@@ -146,7 +150,7 @@
dvmLockMutex(&gDvmJit.compilerLock);
while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
- self->interpBreak.ctl.suspendCount == 0) {
+ self->suspendCount == 0) {
/*
* Use timed wait here - more than one mutator threads may be blocked
* but the compiler thread will only signal once when the queue is
@@ -160,8 +164,6 @@
bool dvmCompilerSetupCodeCache(void)
{
- extern void dvmCompilerTemplateStart(void);
- extern void dmvCompilerTemplateEnd(void);
int fd;
/* Allocate the code cache */
@@ -220,7 +222,7 @@
static void crawlDalvikStack(Thread *thread, bool print)
{
- void *fp = thread->curFrame;
+ void *fp = thread->interpSave.curFrame;
StackSaveArea* saveArea = NULL;
int stackLevel = 0;
@@ -280,8 +282,7 @@
inJit++;
}
/* Cancel any ongoing trace selection */
- dvmUpdateInterpBreak(thread, kInterpJitBreak, kSubModeJitTraceBuild,
- false /* clear */);
+ dvmDisableSubMode(thread, kSubModeJitTraceBuild);
}
dvmUnlockThreadList();
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 35d34b3..2cf2935 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include <Thread.h>
-#include <setjmp.h>
-
#ifndef _DALVIK_VM_COMPILER
#define _DALVIK_VM_COMPILER
+#include <setjmp.h>
+#include "Thread.h"
+
/*
* Uncomment the following to enable JIT signature breakpoint
* #define SIGNATURE_BREAKPOINT
@@ -223,7 +223,7 @@
bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
struct BasicBlock *bb);
char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
- char *note);
+ const char *note);
char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit,
const struct MIR *mir);
char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
@@ -237,8 +237,9 @@
void dvmCompilerUpdateGlobalState(void);
JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
const struct JitEntry *desc);
-void *dvmCompilerGetInterpretTemplate();
+extern "C" void *dvmCompilerGetInterpretTemplate();
JitInstructionSetType dvmCompilerGetInterpretTemplateSet();
u8 dvmGetRegResourceMask(int reg);
void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix);
+
#endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index bdb69ce..bec052a 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -42,7 +42,7 @@
} RegLocation;
#define INVALID_SREG (-1)
-#define INVALID_REG (-1)
+#define INVALID_REG (0x3F)
typedef enum BBType {
/* For coding convenience reasons chaining cell types should appear first */
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.cpp
similarity index 98%
rename from vm/compiler/Dataflow.c
rename to vm/compiler/Dataflow.cpp
index c3355e9..28bed68 100644
--- a/vm/compiler/Dataflow.c
+++ b/vm/compiler/Dataflow.cpp
@@ -1587,17 +1587,17 @@
* ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
*/
char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
- char *note)
+ const char *note)
{
char buffer[256];
- int opcode = insn->opcode;
+ Opcode opcode = insn->opcode;
int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
int flags;
char *ret;
buffer[0] = 0;
- if (opcode >= kMirOpFirst) {
- if (opcode == kMirOpPhi) {
+ if ((int)opcode >= (int)kMirOpFirst) {
+ if ((int)opcode == (int)kMirOpPhi) {
strcpy(buffer, "PHI");
}
else {
@@ -1658,13 +1658,13 @@
if (dfAttributes & DF_B_IS_REG) {
snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vB);
}
- else if (opcode < kMirOpFirst) {
+ else if ((int)opcode < (int)kMirOpFirst) {
snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vB);
}
if (dfAttributes & DF_C_IS_REG) {
snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vC);
}
- else if (opcode < kMirOpFirst) {
+ else if ((int)opcode < (int)kMirOpFirst) {
snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vC);
}
}
@@ -1696,6 +1696,7 @@
int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
char *ret;
int length;
+ OpcodeFlags flags;
buffer[0] = 0;
if (opcode >= kMirOpFirst) {
@@ -1715,10 +1716,10 @@
}
goto done;
} else {
- strcpy(buffer, dexGetOpcodeName(opcode));
+ strcpy(buffer, dexGetOpcodeName((Opcode)opcode));
}
- int flags = dexGetFlagsFromOpcode(opcode);
+ flags = dexGetFlagsFromOpcode((Opcode)opcode);
/* For branches, decode the instructions to print out the branch targets */
if (flags & kInstrCanBranch) {
InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
@@ -1774,7 +1775,8 @@
}
}
if (opcode < kMirOpFirst) {
- InstructionFormat dalvikFormat = dexGetFormatFromOpcode(opcode);
+ InstructionFormat dalvikFormat =
+ dexGetFormatFromOpcode((Opcode)opcode);
switch (dalvikFormat) {
case kFmt11n: // op vA, #+B
case kFmt21s: // op vAA, #+BBBB
@@ -2196,7 +2198,7 @@
/* If the bb doesn't have a phi it cannot contain an induction variable */
if (bb->firstMIRInsn == NULL ||
- bb->firstMIRInsn->dalvikInsn.opcode != kMirOpPhi) {
+ (int)bb->firstMIRInsn->dalvikInsn.opcode != (int)kMirOpPhi) {
return false;
}
@@ -2215,7 +2217,7 @@
*/
MIR *phi;
for (phi = bb->firstMIRInsn; phi; phi = phi->next) {
- if (phi->dalvikInsn.opcode != kMirOpPhi) break;
+ if ((int)phi->dalvikInsn.opcode != (int)kMirOpPhi) break;
if (phi->ssaRep->defs[0] == mir->ssaRep->uses[0] &&
phi->ssaRep->uses[1] == mir->ssaRep->defs[0]) {
diff --git a/vm/compiler/Dataflow.h b/vm/compiler/Dataflow.h
index f3d3984..e573d8b 100644
--- a/vm/compiler/Dataflow.h
+++ b/vm/compiler/Dataflow.h
@@ -102,12 +102,16 @@
bool *fpDef;
} SSARepresentation;
+/*
+ * An induction variable is represented by "m*i + c", where i is a basic
+ * induction variable.
+ */
typedef struct InductionVariableInfo {
int ssaReg;
int basicSSAReg;
- int m;
- int c;
- int inc;
+ int m; // multiplier
+ int c; // constant
+ int inc; // loop incriment
} InductionVariableInfo;
typedef struct ArrayAccessInfo {
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.cpp
similarity index 99%
rename from vm/compiler/Frontend.c
rename to vm/compiler/Frontend.cpp
index f8cd2f1..75be703 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.cpp
@@ -23,7 +23,7 @@
static inline bool contentIsInsn(const u2 *codePtr) {
u2 instr = *codePtr;
- Opcode opcode = instr & 0xff;
+ Opcode opcode = (Opcode)(instr & 0xff);
/*
* Since the low 8-bit in metadata may look like OP_NOP, we need to check
@@ -392,7 +392,7 @@
static bool filterMethodByCallGraph(Thread *thread, const char *curMethodName)
{
/* Crawl the Dalvik stack frames and compare the method name*/
- StackSaveArea *ssaPtr = ((StackSaveArea *) thread->curFrame) - 1;
+ StackSaveArea *ssaPtr = ((StackSaveArea *) thread->interpSave.curFrame) - 1;
while (ssaPtr != ((StackSaveArea *) NULL) - 1) {
const Method *method = ssaPtr->method;
if (method) {
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.cpp
similarity index 97%
rename from vm/compiler/InlineTransformation.c
rename to vm/compiler/InlineTransformation.cpp
index 6cf2d43..387dd61 100644
--- a/vm/compiler/InlineTransformation.c
+++ b/vm/compiler/InlineTransformation.cpp
@@ -102,7 +102,7 @@
if (isPredicted) {
MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
*invokeMIRSlow = *invokeMIR;
- invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
+ invokeMIR->dalvikInsn.opcode = (Opcode)kMirOpCheckInlinePrediction;
/* Use vC to denote the first argument (ie this) */
if (!isRange) {
@@ -181,7 +181,7 @@
if (isPredicted) {
MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
*invokeMIRSlow = *invokeMIR;
- invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
+ invokeMIR->dalvikInsn.opcode = (Opcode)kMirOpCheckInlinePrediction;
/* Use vC to denote the first argument (ie this) */
if (!isRange) {
@@ -249,7 +249,7 @@
{
MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
*invokeMIRSlow = *invokeMIR;
- invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
+ invokeMIR->dalvikInsn.opcode = (Opcode)kMirOpCheckInlinePrediction;
dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, invokeMIRSlow);
invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED;
@@ -300,8 +300,8 @@
if (bb->blockType != kDalvikByteCode)
continue;
MIR *lastMIRInsn = bb->lastMIRInsn;
- int opcode = lastMIRInsn->dalvikInsn.opcode;
- int flags = dexGetFlagsFromOpcode(opcode);
+ Opcode opcode = lastMIRInsn->dalvikInsn.opcode;
+ int flags = (int)dexGetFlagsFromOpcode(opcode);
/* No invoke - continue */
if ((flags & kInstrInvoke) == 0)
diff --git a/vm/compiler/IntermediateRep.c b/vm/compiler/IntermediateRep.cpp
similarity index 100%
rename from vm/compiler/IntermediateRep.c
rename to vm/compiler/IntermediateRep.cpp
diff --git a/vm/compiler/Loop.c b/vm/compiler/Loop.cpp
similarity index 83%
rename from vm/compiler/Loop.c
rename to vm/compiler/Loop.cpp
index b99da7e..90c97d7 100644
--- a/vm/compiler/Loop.c
+++ b/vm/compiler/Loop.cpp
@@ -118,20 +118,59 @@
}
}
+/* Used for normalized loop exit condition checks */
+static Opcode negateOpcode(Opcode opcode)
+{
+ switch (opcode) {
+ /* reg/reg cmp */
+ case OP_IF_EQ:
+ return OP_IF_NE;
+ case OP_IF_NE:
+ return OP_IF_EQ;
+ case OP_IF_LT:
+ return OP_IF_GE;
+ case OP_IF_GE:
+ return OP_IF_LT;
+ case OP_IF_GT:
+ return OP_IF_LE;
+ case OP_IF_LE:
+ return OP_IF_GT;
+ /* reg/zero cmp */
+ case OP_IF_EQZ:
+ return OP_IF_NEZ;
+ case OP_IF_NEZ:
+ return OP_IF_EQZ;
+ case OP_IF_LTZ:
+ return OP_IF_GEZ;
+ case OP_IF_GEZ:
+ return OP_IF_LTZ;
+ case OP_IF_GTZ:
+ return OP_IF_LEZ;
+ case OP_IF_LEZ:
+ return OP_IF_GTZ;
+ default:
+ LOGE("opcode %d cannot be negated", opcode);
+ dvmAbort();
+ break;
+ }
+ return (Opcode)-1; // unreached
+}
+
/*
* A loop is considered optimizable if:
- * 1) It has one basic induction variable
- * 2) The loop back branch compares the BIV with a constant
- * 3) If it is a count-up loop, the condition is GE/GT, or LE/LT/LEZ/LTZ for
- * a count-down loop.
+ * 1) It has one basic induction variable.
+ * 2) The loop back branch compares the BIV with a constant.
+ * 3) We need to normalize the loop exit condition so that the loop is exited
+ * via the taken path.
+ * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is
+ * LE/LT/LEZ/LTZ for a count-down loop.
*
- * Return false if the loop is not optimizable.
+ * Return false for loops that fail the above tests.
*/
static bool isSimpleCountedLoop(CompilationUnit *cUnit)
{
unsigned int i;
- BasicBlock *loopBranch = findPredecessorBlock(cUnit,
- cUnit->entryBlock->fallThrough);
+ BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough;
LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
if (loopAnalysis->numBasicIV != 1) return false;
@@ -150,67 +189,104 @@
}
}
- MIR *branch = loopBranch->lastMIRInsn;
+ /* Find the block that ends with a branch to exit the loop */
+ while (true) {
+ loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock);
+ /* Loop structure not recognized as counted blocks */
+ if (loopBackBlock == NULL) {
+ return false;
+ }
+ /* Unconditional goto - continue to trace up the predecessor chain */
+ if (loopBackBlock->taken == NULL) {
+ continue;
+ }
+ break;
+ }
+
+ MIR *branch = loopBackBlock->lastMIRInsn;
Opcode opcode = branch->dalvikInsn.opcode;
- /*
- * If the instruction is not accessing the IV as the first operand, return
- * false.
- */
- if (branch->ssaRep->numUses == 0 || branch->ssaRep->numDefs != 0) {
+ /* Last instruction is not a conditional branch - bail */
+ if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) {
return false;
}
- /*
- * If the first operand of the comparison is not the basic induction
- * variable, return false.
- */
- if (branch->ssaRep->uses[0] != loopAnalysis->ssaBIV) {
+ int endSSAReg;
+ int endDalvikReg;
+
+ /* reg/reg comparison */
+ if (branch->ssaRep->numUses == 2) {
+ if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
+ endSSAReg = branch->ssaRep->uses[1];
+ } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) {
+ endSSAReg = branch->ssaRep->uses[0];
+ opcode = negateOpcode(opcode);
+ } else {
+ return false;
+ }
+ endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg);
+ /*
+ * If the comparison is not between the BIV and a loop invariant,
+ * return false. endDalvikReg is loop invariant if one of the
+ * following is true:
+ * - It is not defined in the loop (ie DECODE_SUB returns 0)
+ * - It is reloaded with a constant
+ */
+ if ((DECODE_SUB(endDalvikReg) != 0) &&
+ !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) {
+ return false;
+ }
+ /* Compare against zero */
+ } else if (branch->ssaRep->numUses == 1) {
+ if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
+ /* Keep the compiler happy */
+ endDalvikReg = -1;
+ } else {
+ return false;
+ }
+ } else {
return false;
}
+ /* Normalize the loop exit check as "if (iv op end) exit;" */
+ if (loopBackBlock->taken->blockType == kDalvikByteCode) {
+ opcode = negateOpcode(opcode);
+ }
+
if (loopAnalysis->isCountUpLoop) {
/*
- * If the condition op is not > or >=, this is not an optimization
- * candidate.
+ * If the normalized condition op is not > or >=, this is not an
+ * optimization candidate.
*/
- if (opcode != OP_IF_GT && opcode != OP_IF_GE) {
- return false;
+ switch (opcode) {
+ case OP_IF_GT:
+ case OP_IF_GE:
+ break;
+ default:
+ return false;
}
- /*
- * If the comparison is not between the BIV and a loop invariant,
- * return false. endReg is loop invariant if one of the following is
- * true:
- * - It is not defined in the loop (ie DECODE_SUB returns 0)
- * - It is reloaded with a constant
- */
- int endReg = dvmConvertSSARegToDalvik(cUnit, branch->ssaRep->uses[1]);
- if (DECODE_SUB(endReg) != 0 &&
- !dvmIsBitSet(cUnit->isConstantV, branch->ssaRep->uses[1])) {
- return false;
- }
- loopAnalysis->endConditionReg = DECODE_REG(endReg);
+ loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
} else {
/*
- * If the condition op is not < or <=, this is not an optimization
- * candidate.
+ * If the normalized condition op is not < or <=, this is not an
+ * optimization candidate.
*/
- if (opcode == OP_IF_LT || opcode == OP_IF_LE) {
- /*
- * If the comparison is not between the BIV and a loop invariant,
- * return false.
- */
- int endReg = dvmConvertSSARegToDalvik(cUnit,
- branch->ssaRep->uses[1]);
-
- if (DECODE_SUB(endReg) != 0) {
+ switch (opcode) {
+ case OP_IF_LT:
+ case OP_IF_LE:
+ loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
+ break;
+ case OP_IF_LTZ:
+ case OP_IF_LEZ:
+ break;
+ default:
return false;
- }
- loopAnalysis->endConditionReg = DECODE_REG(endReg);
- } else if (opcode != OP_IF_LTZ && opcode != OP_IF_LEZ) {
- return false;
}
}
+ /*
+ * Remember the normalized opcode, which will be used to determine the end
+ * value used for the yanked range checks.
+ */
loopAnalysis->loopBranchOpcode = opcode;
return true;
}
@@ -371,7 +447,7 @@
MIR *rangeCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true);
rangeCheckMIR->dalvikInsn.opcode = (loopAnalysis->isCountUpLoop) ?
- kMirOpNullNRangeUpCheck : kMirOpNullNRangeDownCheck;
+ (Opcode)kMirOpNullNRangeUpCheck : (Opcode)kMirOpNullNRangeDownCheck;
rangeCheckMIR->dalvikInsn.vA = arrayReg;
rangeCheckMIR->dalvikInsn.vB = idxReg;
rangeCheckMIR->dalvikInsn.vC = loopAnalysis->endConditionReg;
@@ -390,7 +466,7 @@
if (loopAnalysis->arrayAccessInfo->numUsed != 0) {
if (loopAnalysis->isCountUpLoop) {
MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true);
- boundCheckMIR->dalvikInsn.opcode = kMirOpLowerBound;
+ boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpLowerBound;
boundCheckMIR->dalvikInsn.vA = idxReg;
boundCheckMIR->dalvikInsn.vB = globalMinC;
dvmCompilerAppendMIR(entry, boundCheckMIR);
@@ -398,7 +474,7 @@
if (loopAnalysis->loopBranchOpcode == OP_IF_LT ||
loopAnalysis->loopBranchOpcode == OP_IF_LE) {
MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true);
- boundCheckMIR->dalvikInsn.opcode = kMirOpLowerBound;
+ boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpLowerBound;
boundCheckMIR->dalvikInsn.vA = loopAnalysis->endConditionReg;
boundCheckMIR->dalvikInsn.vB = globalMinC;
/*
@@ -416,7 +492,7 @@
if (globalMinC < 0) {
MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR),
true);
- boundCheckMIR->dalvikInsn.opcode = kMirOpPunt;
+ boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpPunt;
dvmCompilerAppendMIR(entry, boundCheckMIR);
}
} else if (loopAnalysis->loopBranchOpcode == OP_IF_LEZ) {
@@ -424,7 +500,7 @@
if (globalMinC < -1) {
MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR),
true);
- boundCheckMIR->dalvikInsn.opcode = kMirOpPunt;
+ boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpPunt;
dvmCompilerAppendMIR(entry, boundCheckMIR);
}
} else {
@@ -432,7 +508,6 @@
dvmCompilerAbort(cUnit);
}
}
-
}
}
diff --git a/vm/compiler/Ralloc.c b/vm/compiler/Ralloc.cpp
similarity index 100%
rename from vm/compiler/Ralloc.c
rename to vm/compiler/Ralloc.cpp
diff --git a/vm/compiler/SSATransformation.c b/vm/compiler/SSATransformation.cpp
similarity index 98%
rename from vm/compiler/SSATransformation.c
rename to vm/compiler/SSATransformation.cpp
index 6d7dd23..091ed13 100644
--- a/vm/compiler/SSATransformation.c
+++ b/vm/compiler/SSATransformation.cpp
@@ -486,7 +486,7 @@
/* Variable will be clobbered before being used - no need for phi */
if (!dvmIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
MIR *phi = (MIR *) dvmCompilerNew(sizeof(MIR), true);
- phi->dalvikInsn.opcode = kMirOpPhi;
+ phi->dalvikInsn.opcode = (Opcode)kMirOpPhi;
phi->dalvikInsn.vA = dalvikReg;
phi->offset = phiBB->startOffset;
dvmCompilerPrependMIR(phiBB, phi);
@@ -507,7 +507,8 @@
/* Phi nodes are at the beginning of each block */
for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
- if (mir->dalvikInsn.opcode != kMirOpPhi) return true;
+ if (mir->dalvikInsn.opcode != (Opcode)kMirOpPhi)
+ return true;
int ssaReg = mir->ssaRep->defs[0];
int encodedDalvikValue =
(int) dvmGrowableListGetElement(cUnit->ssaToDalvikMap, ssaReg);
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.cpp
similarity index 99%
rename from vm/compiler/Utility.c
rename to vm/compiler/Utility.cpp
index 2599e0a..c75e5fe 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.cpp
@@ -157,7 +157,7 @@
void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit)
{
BasicBlock *bb;
- char *blockTypeNames[] = {
+ const char *blockTypeNames[] = {
"Normal Chaining Cell",
"Hot Chaining Cell",
"Singleton Chaining Cell",
diff --git a/vm/compiler/codegen/CodegenFactory.c b/vm/compiler/codegen/CodegenFactory.cpp
similarity index 100%
rename from vm/compiler/codegen/CodegenFactory.c
rename to vm/compiler/codegen/CodegenFactory.cpp
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index efa913f..2e3b107 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -34,6 +34,9 @@
/* Assemble LIR into machine code */
void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info);
+/* Perform translation chain operation. */
+extern "C" void* dvmJitChain(void* tgtAddr, u4* branchAddr);
+
/* Install class objects in the literal pool */
void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit,
char *codeAddress);
diff --git a/vm/compiler/codegen/Optimizer.h b/vm/compiler/codegen/Optimizer.h
index 2b05476..dd8e788 100644
--- a/vm/compiler/codegen/Optimizer.h
+++ b/vm/compiler/codegen/Optimizer.h
@@ -23,14 +23,14 @@
* If the corresponding bit is set in gDvmJit.disableOpt, the selected
* optimization will be suppressed.
*/
-typedef enum optControlVector {
+enum optControlVector {
kLoadStoreElimination = 0,
kLoadHoisting,
kTrackLiveTemps,
kSuppressLoads,
kMethodInlining,
kMethodJit,
-} optControlVector;
+};
/* Forward declarations */
struct CompilationUnit;
diff --git a/vm/compiler/codegen/RallocUtil.c b/vm/compiler/codegen/RallocUtil.cpp
similarity index 100%
rename from vm/compiler/codegen/RallocUtil.c
rename to vm/compiler/codegen/RallocUtil.cpp
diff --git a/vm/compiler/codegen/arm/ArchFactory.c b/vm/compiler/codegen/arm/ArchFactory.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/ArchFactory.c
rename to vm/compiler/codegen/arm/ArchFactory.cpp
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.cpp
similarity index 98%
rename from vm/compiler/codegen/arm/ArchUtility.c
rename to vm/compiler/codegen/arm/ArchUtility.cpp
index edcbf86..f3a2a4b 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.cpp
@@ -18,7 +18,7 @@
#include "libdex/DexOpcodes.h"
#include "ArmLIR.h"
-static char *shiftNames[4] = {
+static const char *shiftNames[4] = {
"lsl",
"lsr",
"asr",
@@ -73,14 +73,14 @@
* Interpret a format string and build a string no longer than size
* See format key in Assemble.c.
*/
-static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
+static void buildInsnString(const char *fmt, ArmLIR *lir, char* buf,
unsigned char *baseAddr, int size)
{
int i;
char *bufEnd = &buf[size-1];
- char *fmtEnd = &fmt[strlen(fmt)];
+ const char *fmtEnd = &fmt[strlen(fmt)];
char tbuf[256];
- char *name;
+ const char *name;
char nc;
while (fmt < fmtEnd) {
int operand;
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index a187cfa..46316ff 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -734,8 +734,8 @@
} fieldLoc[4];
ArmOpcode opcode;
int flags;
- char *name;
- char* fmt;
+ const char* name;
+ const char* fmt;
int size;
} ArmEncodingMap;
diff --git a/vm/compiler/codegen/arm/ArmRallocUtil.c b/vm/compiler/codegen/arm/ArmRallocUtil.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/ArmRallocUtil.c
rename to vm/compiler/codegen/arm/ArmRallocUtil.cpp
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.cpp
similarity index 99%
rename from vm/compiler/codegen/arm/Assemble.c
rename to vm/compiler/codegen/arm/Assemble.cpp
index 7c22de7..a433c31 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.cpp
@@ -1758,6 +1758,8 @@
newRechainCount = PREDICTED_CHAIN_COUNTER_AVOID;
goto done;
#else
+ PredictedChainingCell newCell;
+ int baseAddr, branchOffset, tgtAddr;
if (dvmIsNativeMethod(method)) {
UNPROTECT_CODE_CACHE(cell, sizeof(*cell));
@@ -1772,7 +1774,7 @@
PROTECT_CODE_CACHE(cell, sizeof(*cell));
goto done;
}
- int tgtAddr = (int) dvmJitGetTraceAddr(method->insns);
+ tgtAddr = (int) dvmJitGetTraceAddr(method->insns);
/*
* Compilation not made yet for the callee. Reset the counter to a small
@@ -1786,14 +1788,12 @@
goto done;
}
- PredictedChainingCell newCell;
-
if (cell->clazz == NULL) {
newRechainCount = self->icRechainCount;
}
- int baseAddr = (int) cell + 4; // PC is cur_addr + 4
- int branchOffset = tgtAddr - baseAddr;
+ baseAddr = (int) cell + 4; // PC is cur_addr + 4
+ branchOffset = tgtAddr - baseAddr;
newCell.branch = assembleChainingBranch(branchOffset, true);
newCell.clazz = clazz;
diff --git a/vm/compiler/codegen/arm/CalloutHelper.h b/vm/compiler/codegen/arm/CalloutHelper.h
index 931cf0f..2660108 100644
--- a/vm/compiler/codegen/arm/CalloutHelper.h
+++ b/vm/compiler/codegen/arm/CalloutHelper.h
@@ -31,37 +31,37 @@
#define LOAD_FUNC_ADDR(cUnit, reg, addr) loadConstant(cUnit, reg, addr)
/* Conversions */
-float __aeabi_i2f(int op1); // OP_INT_TO_FLOAT
-int __aeabi_f2iz(float op1); // OP_FLOAT_TO_INT
-float __aeabi_d2f(double op1); // OP_DOUBLE_TO_FLOAT
-double __aeabi_f2d(float op1); // OP_FLOAT_TO_DOUBLE
-double __aeabi_i2d(int op1); // OP_INT_TO_DOUBLE
-int __aeabi_d2iz(double op1); // OP_DOUBLE_TO_INT
-float __aeabi_l2f(long op1); // OP_LONG_TO_FLOAT
-double __aeabi_l2d(long op1); // OP_LONG_TO_DOUBLE
+extern "C" float __aeabi_i2f(int op1); // OP_INT_TO_FLOAT
+extern "C" int __aeabi_f2iz(float op1); // OP_FLOAT_TO_INT
+extern "C" float __aeabi_d2f(double op1); // OP_DOUBLE_TO_FLOAT
+extern "C" double __aeabi_f2d(float op1); // OP_FLOAT_TO_DOUBLE
+extern "C" double __aeabi_i2d(int op1); // OP_INT_TO_DOUBLE
+extern "C" int __aeabi_d2iz(double op1); // OP_DOUBLE_TO_INT
+extern "C" float __aeabi_l2f(long op1); // OP_LONG_TO_FLOAT
+extern "C" double __aeabi_l2d(long op1); // OP_LONG_TO_DOUBLE
s8 dvmJitf2l(float op1); // OP_FLOAT_TO_LONG
s8 dvmJitd2l(double op1); // OP_DOUBLE_TO_LONG
/* Single-precision FP arithmetics */
-float __aeabi_fadd(float a, float b); // OP_ADD_FLOAT[_2ADDR]
-float __aeabi_fsub(float a, float b); // OP_SUB_FLOAT[_2ADDR]
-float __aeabi_fdiv(float a, float b); // OP_DIV_FLOAT[_2ADDR]
-float __aeabi_fmul(float a, float b); // OP_MUL_FLOAT[_2ADDR]
-float fmodf(float a, float b); // OP_REM_FLOAT[_2ADDR]
+extern "C" float __aeabi_fadd(float a, float b); // OP_ADD_FLOAT[_2ADDR]
+extern "C" float __aeabi_fsub(float a, float b); // OP_SUB_FLOAT[_2ADDR]
+extern "C" float __aeabi_fdiv(float a, float b); // OP_DIV_FLOAT[_2ADDR]
+extern "C" float __aeabi_fmul(float a, float b); // OP_MUL_FLOAT[_2ADDR]
+extern "C" float fmodf(float a, float b); // OP_REM_FLOAT[_2ADDR]
/* Double-precision FP arithmetics */
-double __aeabi_dadd(double a, double b); // OP_ADD_DOUBLE[_2ADDR]
-double __aeabi_dsub(double a, double b); // OP_SUB_DOUBLE[_2ADDR]
-double __aeabi_ddiv(double a, double b); // OP_DIV_DOUBLE[_2ADDR]
-double __aeabi_dmul(double a, double b); // OP_MUL_DOUBLE[_2ADDR]
-double fmod(double a, double b); // OP_REM_DOUBLE[_2ADDR]
+extern "C" double __aeabi_dadd(double a, double b); // OP_ADD_DOUBLE[_2ADDR]
+extern "C" double __aeabi_dsub(double a, double b); // OP_SUB_DOUBLE[_2ADDR]
+extern "C" double __aeabi_ddiv(double a, double b); // OP_DIV_DOUBLE[_2ADDR]
+extern "C" double __aeabi_dmul(double a, double b); // OP_MUL_DOUBLE[_2ADDR]
+extern "C" double fmod(double a, double b); // OP_REM_DOUBLE[_2ADDR]
/* Integer arithmetics */
-int __aeabi_idivmod(int op1, int op2); // OP_REM_INT[_2ADDR|_LIT8|_LIT16]
-int __aeabi_idiv(int op1, int op2); // OP_DIV_INT[_2ADDR|_LIT8|_LIT16]
+extern "C" int __aeabi_idivmod(int op1, int op2); // OP_REM_INT[_2ADDR|_LIT8|_LIT16]
+extern "C" int __aeabi_idiv(int op1, int op2); // OP_DIV_INT[_2ADDR|_LIT8|_LIT16]
/* Long long arithmetics - OP_REM_LONG[_2ADDR] & OP_DIV_LONG[_2ADDR] */
-long long __aeabi_ldivmod(long long op1, long long op2);
+extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
/* Originally declared in Sync.h */
bool dvmUnlockObject(struct Thread* self, struct Object* obj); //OP_MONITOR_EXIT
@@ -110,7 +110,7 @@
* Functions declared in gDvmInlineOpsTable[] are used for
* OP_EXECUTE_INLINE & OP_EXECUTE_INLINE_RANGE.
*/
-double sqrt(double x); // INLINE_MATH_SQRT
+extern "C" double sqrt(double x); // INLINE_MATH_SQRT
/*
* The following functions are invoked through the compiler templates (declared
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
index 330619b..e67f3d8 100644
--- a/vm/compiler/codegen/arm/Codegen.h
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -56,7 +56,7 @@
#if defined(WITH_SELF_VERIFICATION)
/* Self Verification memory instruction decoder */
-void dvmSelfVerificationMemOpDecode(int lr, int* sp);
+extern "C" void dvmSelfVerificationMemOpDecode(int lr, int* sp);
#endif
extern void dvmCompilerSetupResourceMasks(ArmLIR *lir);
diff --git a/vm/compiler/codegen/arm/CodegenCommon.c b/vm/compiler/codegen/arm/CodegenCommon.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/CodegenCommon.c
rename to vm/compiler/codegen/arm/CodegenCommon.cpp
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.cpp
similarity index 98%
rename from vm/compiler/codegen/arm/CodegenDriver.c
rename to vm/compiler/codegen/arm/CodegenDriver.cpp
index e94fc11..1a8ac42 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.cpp
@@ -404,8 +404,8 @@
RegLocation rlDest, int scale)
{
RegisterClass regClass = dvmCompilerRegClassBySize(size);
- int lenOffset = offsetof(ArrayObject, length);
- int dataOffset = offsetof(ArrayObject, contents);
+ int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
+ int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
RegLocation rlResult;
rlArray = loadValue(cUnit, rlArray, kCoreReg);
rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
@@ -473,8 +473,8 @@
RegLocation rlSrc, int scale)
{
RegisterClass regClass = dvmCompilerRegClassBySize(size);
- int lenOffset = offsetof(ArrayObject, length);
- int dataOffset = offsetof(ArrayObject, contents);
+ int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
+ int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
int regPtr;
rlArray = loadValue(cUnit, rlArray, kCoreReg);
@@ -547,8 +547,8 @@
RegLocation rlArray, RegLocation rlIndex,
RegLocation rlSrc, int scale)
{
- int lenOffset = offsetof(ArrayObject, length);
- int dataOffset = offsetof(ArrayObject, contents);
+ int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
+ int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents);
dvmCompilerFlushAllRegs(cUnit);
@@ -769,7 +769,7 @@
bool checkZero = false;
bool unary = false;
int retReg = r0;
- void *callTgt;
+ int (*callTgt)(int, int);
RegLocation rlResult;
bool shiftOp = false;
@@ -2076,7 +2076,7 @@
storeValue(cUnit, rlDest, rlResult);
break;
case OP_ARRAY_LENGTH: {
- int lenOffset = offsetof(ArrayObject, length);
+ int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
mir->offset, NULL);
@@ -2155,7 +2155,7 @@
cond = kArmCondLe;
break;
default:
- cond = 0;
+ cond = (ArmConditionCode)0;
LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpcode);
dvmCompilerAbort(cUnit);
}
@@ -2294,7 +2294,7 @@
RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
RegLocation rlResult;
int lit = mir->dalvikInsn.vC;
- OpKind op = 0; /* Make gcc happy */
+ OpKind op = (OpKind)0; /* Make gcc happy */
int shiftOp = false;
bool isDiv = false;
@@ -2700,7 +2700,7 @@
cond = kArmCondLe;
break;
default:
- cond = 0;
+ cond = (ArmConditionCode)0;
LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpcode);
dvmCompilerAbort(cUnit);
}
@@ -3576,7 +3576,7 @@
static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
{
- int contents = offsetof(ArrayObject, contents);
+ int contents = OFFSETOF_MEMBER(ArrayObject, contents);
RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
RegLocation rlIdx = dvmCompilerGetSrc(cUnit, mir, 1);
RegLocation rlDest = inlinedTarget(cUnit, mir, false);
@@ -3913,7 +3913,7 @@
}
}
-static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
+static const char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
"kMirOpPhi",
"kMirOpNullNRangeUpCheck",
"kMirOpNullNRangeDownCheck",
@@ -3939,7 +3939,7 @@
* ssa name.
*/
DecodedInstruction *dInsn = &mir->dalvikInsn;
- const int lenOffset = offsetof(ArrayObject, length);
+ const int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
const int maxC = dInsn->arg[0];
int regLength;
RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
@@ -3986,7 +3986,7 @@
static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
{
DecodedInstruction *dInsn = &mir->dalvikInsn;
- const int lenOffset = offsetof(ArrayObject, length);
+ const int lenOffset = OFFSETOF_MEMBER(ArrayObject, length);
const int regLength = dvmCompilerAllocTemp(cUnit);
const int maxC = dInsn->arg[0];
RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
@@ -4144,7 +4144,7 @@
strcpy(msg, extendedMIROpNames[opOffset]);
newLIR1(cUnit, kArmPseudoExtended, (int) msg);
- switch (mir->dalvikInsn.opcode) {
+ switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
case kMirOpPhi: {
char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
@@ -4247,6 +4247,7 @@
/* Used to hold the labels of each block */
ArmLIR *labelList =
(ArmLIR *) dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
+ ArmLIR *headLIR = NULL;
GrowableList chainingListByType[kChainingCellGap];
int i;
@@ -4374,15 +4375,12 @@
continue;
}
- ArmLIR *headLIR = NULL;
- BasicBlock *nextBB = bb;
-
/*
* Try to build a longer optimization unit. Currently if the previous
* block ends with a goto, we continue adding instructions and don't
* reset the register allocation pool.
*/
- for (; nextBB != NULL; nextBB = cUnit->nextCodegenBlock) {
+ for (BasicBlock *nextBB = bb; nextBB != NULL; nextBB = cUnit->nextCodegenBlock) {
bb = nextBB;
bb->visited = true;
cUnit->nextCodegenBlock = NULL;
@@ -4398,16 +4396,15 @@
dvmCompilerResetDefTracking(cUnit);
}
- if (mir->dalvikInsn.opcode >= kMirOpFirst) {
+ if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
handleExtendedMIR(cUnit, mir);
continue;
}
-
Opcode dalvikOpcode = mir->dalvikInsn.opcode;
InstructionFormat dalvikFormat =
dexGetFormatFromOpcode(dalvikOpcode);
- char *note;
+ const char *note;
if (mir->OptimizationFlags & MIR_INLINED) {
note = " (I)";
} else if (mir->OptimizationFlags & MIR_INLINED_PRED) {
@@ -4701,7 +4698,7 @@
break;
}
case kWorkOrderProfileMode:
- dvmJitChangeProfileMode((TraceProfilingModes)work->info);
+ dvmJitChangeProfileMode((TraceProfilingModes)(int)work->info);
isCompile = false;
break;
default:
diff --git a/vm/compiler/codegen/arm/FP/Thumb2VFP.c b/vm/compiler/codegen/arm/FP/Thumb2VFP.cpp
similarity index 95%
rename from vm/compiler/codegen/arm/FP/Thumb2VFP.c
rename to vm/compiler/codegen/arm/FP/Thumb2VFP.cpp
index 61698c2..aed4950 100644
--- a/vm/compiler/codegen/arm/FP/Thumb2VFP.c
+++ b/vm/compiler/codegen/arm/FP/Thumb2VFP.cpp
@@ -54,7 +54,8 @@
rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR3(cUnit, op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
+ newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg,
+ rlSrc2.lowReg);
storeValue(cUnit, rlDest, rlResult);
return false;
}
@@ -100,7 +101,7 @@
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
assert(rlDest.wide);
assert(rlResult.wide);
- newLIR3(cUnit, op, S2D(rlResult.lowReg, rlResult.highReg),
+ newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
S2D(rlSrc1.lowReg, rlSrc1.highReg),
S2D(rlSrc2.lowReg, rlSrc2.highReg));
storeValueWide(cUnit, rlDest, rlResult);
@@ -169,12 +170,13 @@
if (longDest) {
rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, op, S2D(rlResult.lowReg, rlResult.highReg), srcReg);
+ newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
+ srcReg);
storeValueWide(cUnit, rlDest, rlResult);
} else {
rlDest = dvmCompilerGetDest(cUnit, mir, 0);
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, op, rlResult.lowReg, srcReg);
+ newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
storeValue(cUnit, rlDest, rlResult);
}
return false;
diff --git a/vm/compiler/codegen/arm/FP/ThumbPortableFP.c b/vm/compiler/codegen/arm/FP/ThumbPortableFP.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/FP/ThumbPortableFP.c
rename to vm/compiler/codegen/arm/FP/ThumbPortableFP.cpp
diff --git a/vm/compiler/codegen/arm/FP/ThumbVFP.c b/vm/compiler/codegen/arm/FP/ThumbVFP.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/FP/ThumbVFP.c
rename to vm/compiler/codegen/arm/FP/ThumbVFP.cpp
diff --git a/vm/compiler/codegen/arm/GlobalOptimizations.c b/vm/compiler/codegen/arm/GlobalOptimizations.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/GlobalOptimizations.c
rename to vm/compiler/codegen/arm/GlobalOptimizations.cpp
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/LocalOptimizations.c
rename to vm/compiler/codegen/arm/LocalOptimizations.cpp
diff --git a/vm/compiler/codegen/arm/README.txt b/vm/compiler/codegen/arm/README.txt
index a49eef8..1bb4603 100644
--- a/vm/compiler/codegen/arm/README.txt
+++ b/vm/compiler/codegen/arm/README.txt
@@ -8,26 +8,26 @@
--
/* Architectural independent building blocks */
-#include "../CodegenCommon.c"
+#include "../CodegenCommon.cpp"
/* Thumb2-specific factory utilities */
-#include "../Thumb2/Factory.c"
+#include "../Thumb2/Factory.cpp"
/* Factory utilities dependent on arch-specific features */
-#include "../CodegenFactory.c"
+#include "../CodegenFactory.cpp"
/* Thumb2-specific codegen routines */
-#include "../Thumb2/Gen.c"
+#include "../Thumb2/Gen.cpp"
/* Thumb2+VFP codegen routines */
-#include "../FP/Thumb2VFP.c"
+#include "../FP/Thumb2VFP.cpp"
/* Thumb2-specific register allocation */
-#include "../Thumb2/Ralloc.c"
+#include "../Thumb2/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
--
diff --git a/vm/compiler/codegen/arm/Thumb/Factory.c b/vm/compiler/codegen/arm/Thumb/Factory.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/Thumb/Factory.c
rename to vm/compiler/codegen/arm/Thumb/Factory.cpp
diff --git a/vm/compiler/codegen/arm/Thumb/Gen.c b/vm/compiler/codegen/arm/Thumb/Gen.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/Thumb/Gen.c
rename to vm/compiler/codegen/arm/Thumb/Gen.cpp
diff --git a/vm/compiler/codegen/arm/Thumb/Ralloc.c b/vm/compiler/codegen/arm/Thumb/Ralloc.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/Thumb/Ralloc.c
rename to vm/compiler/codegen/arm/Thumb/Ralloc.cpp
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/Thumb2/Factory.c
rename to vm/compiler/codegen/arm/Thumb2/Factory.cpp
diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.cpp
similarity index 99%
rename from vm/compiler/codegen/arm/Thumb2/Gen.c
rename to vm/compiler/codegen/arm/Thumb2/Gen.cpp
index f54b7eb..fcf0fe3 100644
--- a/vm/compiler/codegen/arm/Thumb2/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb2/Gen.cpp
@@ -165,7 +165,7 @@
* is not met.
*/
static ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code,
- char *guide)
+ const char *guide)
{
int mask;
int condBit = code & 1;
diff --git a/vm/compiler/codegen/arm/Thumb2/Ralloc.c b/vm/compiler/codegen/arm/Thumb2/Ralloc.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/Thumb2/Ralloc.c
rename to vm/compiler/codegen/arm/Thumb2/Ralloc.cpp
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp
similarity index 94%
rename from vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
rename to vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp
index 3d85052..8ab956e 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+extern "C" void dvmCompilerTemplateStart(void);
+
/*
* This file is included by Codegen-armv5te-vfp.c, and implements architecture
* variant-specific code.
@@ -28,16 +30,15 @@
return DALVIK_JIT_THUMB;
}
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern "C" void dvmCompiler_TEMPLATE_##X();
#include "../../../template/armv5te-vfp/TemplateOpList.h"
#undef JIT_TEMPLATE
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchVariantInit(void)
+{
int i = 0;
- extern void dvmCompilerTemplateStart(void);
/*
* Then, populate the templateEntryOffsets array with the offsets from the
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h
index fa01210..452f2a5 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h
@@ -19,7 +19,7 @@
/* Create the TemplateOpcode enum */
#define JIT_TEMPLATE(X) TEMPLATE_##X,
-typedef enum {
+enum TemplateOpcode {
#include "../../../template/armv5te-vfp/TemplateOpList.h"
/*
* For example,
@@ -28,7 +28,7 @@
* ...
*/
TEMPLATE_LAST_MARK,
-} TemplateOpcode;
+};
#undef JIT_TEMPLATE
#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/Codegen.c b/vm/compiler/codegen/arm/armv5te-vfp/Codegen.cpp
similarity index 81%
rename from vm/compiler/codegen/arm/armv5te-vfp/Codegen.c
rename to vm/compiler/codegen/arm/armv5te-vfp/Codegen.cpp
index a2d77ea..55321bb 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/Codegen.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/Codegen.cpp
@@ -29,28 +29,28 @@
#include "ArchVariant.h"
/* Arm codegen building blocks */
-#include "../CodegenCommon.c"
+#include "../CodegenCommon.cpp"
/* Thumb-specific factory utilities */
-#include "../Thumb/Factory.c"
+#include "../Thumb/Factory.cpp"
/* Target independent factory utilities */
-#include "../../CodegenFactory.c"
+#include "../../CodegenFactory.cpp"
/* Arm-specific factory utilities */
-#include "../ArchFactory.c"
+#include "../ArchFactory.cpp"
/* Thumb-specific codegen routines */
-#include "../Thumb/Gen.c"
+#include "../Thumb/Gen.cpp"
/* Thumb+VFP codegen routines */
-#include "../FP/ThumbVFP.c"
+#include "../FP/ThumbVFP.cpp"
/* Thumb-specific register allocation */
-#include "../Thumb/Ralloc.c"
+#include "../Thumb/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Dummy driver for method-based JIT */
-#include "../armv5te/MethodCodegenDriver.c"
+#include "../armv5te/MethodCodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp
similarity index 89%
rename from vm/compiler/codegen/arm/armv5te/ArchVariant.c
rename to vm/compiler/codegen/arm/armv5te/ArchVariant.cpp
index 57a8c8a..3e13af5 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+extern "C" void dvmCompilerTemplateStart(void);
+
/*
* This file is included by Codegen-armv5te.c, and implements architecture
* variant-specific code.
@@ -28,16 +30,15 @@
return DALVIK_JIT_THUMB;
}
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern "C" void dvmCompiler_TEMPLATE_##X();
#include "../../../template/armv5te/TemplateOpList.h"
#undef JIT_TEMPLATE
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchVariantInit(void)
+{
int i = 0;
- extern void dvmCompilerTemplateStart(void);
/*
* Then, populate the templateEntryOffsets array with the offsets from the
@@ -63,9 +64,9 @@
/* Codegen-specific assumptions */
assert(offsetof(ClassObject, vtable) < 128 &&
(offsetof(ClassObject, vtable) & 0x3) == 0);
- assert(offsetof(ArrayObject, length) < 128 &&
- (offsetof(ArrayObject, length) & 0x3) == 0);
- assert(offsetof(ArrayObject, contents) < 256);
+ assert(OFFSETOF_MEMBER(ArrayObject, length) < 128 &&
+ (OFFSETOF_MEMBER(ArrayObject, length) & 0x3) == 0);
+ assert(OFFSETOF_MEMBER(ArrayObject, contents) < 256);
/* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
assert(sizeof(StackSaveArea) < 236);
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.h b/vm/compiler/codegen/arm/armv5te/ArchVariant.h
index 4cc4fa6..07a1c8c 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.h
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.h
@@ -19,7 +19,7 @@
/* Create the TemplateOpcode enum */
#define JIT_TEMPLATE(X) TEMPLATE_##X,
-typedef enum {
+enum TemplateOpcode {
#include "../../../template/armv5te/TemplateOpList.h"
/*
* For example,
@@ -28,7 +28,7 @@
* ...
*/
TEMPLATE_LAST_MARK,
-} TemplateOpcode;
+};
#undef JIT_TEMPLATE
#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/arm/armv5te/Codegen.c b/vm/compiler/codegen/arm/armv5te/Codegen.cpp
similarity index 81%
rename from vm/compiler/codegen/arm/armv5te/Codegen.c
rename to vm/compiler/codegen/arm/armv5te/Codegen.cpp
index f74d968..a379c2a 100644
--- a/vm/compiler/codegen/arm/armv5te/Codegen.c
+++ b/vm/compiler/codegen/arm/armv5te/Codegen.cpp
@@ -29,28 +29,28 @@
#include "ArchVariant.h"
/* Arm codegen building blocks */
-#include "../CodegenCommon.c"
+#include "../CodegenCommon.cpp"
/* Thumb-specific building blocks */
-#include "../Thumb/Factory.c"
+#include "../Thumb/Factory.cpp"
/* Target independent factory utilities */
-#include "../../CodegenFactory.c"
+#include "../../CodegenFactory.cpp"
/* Arm-specific factory utilities */
-#include "../ArchFactory.c"
+#include "../ArchFactory.cpp"
/* Thumb-specific codegen routines */
-#include "../Thumb/Gen.c"
+#include "../Thumb/Gen.cpp"
/* Thumb+Portable FP codegen routines */
-#include "../FP/ThumbPortableFP.c"
+#include "../FP/ThumbPortableFP.cpp"
/* Thumb-specific register allocation */
-#include "../Thumb/Ralloc.c"
+#include "../Thumb/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Dummy driver for method-based JIT */
-#include "MethodCodegenDriver.c"
+#include "MethodCodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
diff --git a/vm/compiler/codegen/arm/armv5te/MethodCodegenDriver.c b/vm/compiler/codegen/arm/armv5te/MethodCodegenDriver.cpp
similarity index 100%
rename from vm/compiler/codegen/arm/armv5te/MethodCodegenDriver.c
rename to vm/compiler/codegen/arm/armv5te/MethodCodegenDriver.cpp
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp
similarity index 88%
rename from vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
rename to vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp
index 59d7c95..d68d150 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+extern "C" void dvmCompilerTemplateStart(void);
+
/*
* Determine the initial instruction set to be used for this trace.
* Later components may decide to change this.
@@ -23,16 +25,15 @@
return DALVIK_JIT_THUMB2;
}
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern "C" void dvmCompiler_TEMPLATE_##X();
#include "../../../template/armv5te-vfp/TemplateOpList.h"
#undef JIT_TEMPLATE
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchVariantInit(void)
+{
int i = 0;
- extern void dvmCompilerTemplateStart(void);
/*
* Then, populate the templateEntryOffsets array with the offsets from the
@@ -58,9 +59,9 @@
/* Codegen-specific assumptions */
assert(offsetof(ClassObject, vtable) < 128 &&
(offsetof(ClassObject, vtable) & 0x3) == 0);
- assert(offsetof(ArrayObject, length) < 128 &&
- (offsetof(ArrayObject, length) & 0x3) == 0);
- assert(offsetof(ArrayObject, contents) < 256);
+ assert(OFFSETOF_MEMBER(ArrayObject, length) < 128 &&
+ (OFFSETOF_MEMBER(ArrayObject, length) & 0x3) == 0);
+ assert(OFFSETOF_MEMBER(ArrayObject, contents) < 256);
/* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
assert(sizeof(StackSaveArea) < 236);
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/Codegen.c b/vm/compiler/codegen/arm/armv7-a-neon/Codegen.cpp
similarity index 81%
rename from vm/compiler/codegen/arm/armv7-a-neon/Codegen.c
rename to vm/compiler/codegen/arm/armv7-a-neon/Codegen.cpp
index 439add5..8f15174 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/Codegen.c
+++ b/vm/compiler/codegen/arm/armv7-a-neon/Codegen.cpp
@@ -29,28 +29,28 @@
#include "ArchVariant.h"
/* Arm codegen building blocks */
-#include "../CodegenCommon.c"
+#include "../CodegenCommon.cpp"
/* Thumb2-specific factory utilities */
-#include "../Thumb2/Factory.c"
+#include "../Thumb2/Factory.cpp"
/* Target indepedent factory utilities */
-#include "../../CodegenFactory.c"
+#include "../../CodegenFactory.cpp"
/* Arm-specific factory utilities */
-#include "../ArchFactory.c"
+#include "../ArchFactory.cpp"
/* Thumb2-specific codegen routines */
-#include "../Thumb2/Gen.c"
+#include "../Thumb2/Gen.cpp"
/* Thumb2+VFP codegen routines */
-#include "../FP/Thumb2VFP.c"
+#include "../FP/Thumb2VFP.cpp"
/* Thumb2-specific register allocation */
-#include "../Thumb2/Ralloc.c"
+#include "../Thumb2/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Driver for method-based JIT */
-#include "MethodCodegenDriver.c"
+#include "MethodCodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
similarity index 98%
rename from vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c
rename to vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
index 98d97d8..32065ae 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.c
+++ b/vm/compiler/codegen/arm/armv7-a-neon/MethodCodegenDriver.cpp
@@ -86,8 +86,8 @@
storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, method), method);
/* thread->method = method */
storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, method), method);
- /* thread->curFrame = current FP */
- storeWordDisp(cUnit, r6SELF, offsetof(Thread, curFrame), r5FP);
+ /* thread->interpSave.curFrame = current FP */
+ storeWordDisp(cUnit, r6SELF, offsetof(Thread, interpSave.curFrame), r5FP);
/* thread->methodClassDex = pDvmDex */
storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, methodClassDex),
pDvmDex);
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
deleted file mode 100644
index 59d7c95..0000000
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-/*
- * Determine the initial instruction set to be used for this trace.
- * Later components may decide to change this.
- */
-JitInstructionSetType dvmCompilerInstructionSet(void)
-{
- return DALVIK_JIT_THUMB2;
-}
-
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
-#include "../../../template/armv5te-vfp/TemplateOpList.h"
-#undef JIT_TEMPLATE
-
- int i = 0;
- extern void dvmCompilerTemplateStart(void);
-
- /*
- * Then, populate the templateEntryOffsets array with the offsets from the
- * the dvmCompilerTemplateStart symbol for each template.
- */
-#define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
- (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
-#include "../../../template/armv5te-vfp/TemplateOpList.h"
-#undef JIT_TEMPLATE
-
- /* Target-specific configuration */
- gDvmJit.jitTableSize = 1 << 12; // 4096
- gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
- gDvmJit.threshold = 40;
- gDvmJit.codeCacheSize = 1024*1024;
-
-#if defined(WITH_SELF_VERIFICATION)
- /* Force into blocking */
- gDvmJit.blockingMode = true;
- gDvm.nativeDebuggerActive = true;
-#endif
-
- /* Codegen-specific assumptions */
- assert(offsetof(ClassObject, vtable) < 128 &&
- (offsetof(ClassObject, vtable) & 0x3) == 0);
- assert(offsetof(ArrayObject, length) < 128 &&
- (offsetof(ArrayObject, length) & 0x3) == 0);
- assert(offsetof(ArrayObject, contents) < 256);
-
- /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
- assert(sizeof(StackSaveArea) < 236);
-
- /*
- * EA is calculated by doing "Rn + imm5 << 2". Make sure that the last
- * offset from the struct is less than 128.
- */
- if ((offsetof(Thread, jitToInterpEntries) +
- sizeof(struct JitToInterpEntries)) >= 128) {
- LOGE("Thread.jitToInterpEntries size overflow");
- dvmAbort();
- }
-
- /* FIXME - comment out the following to enable method-based JIT */
- gDvmJit.disableOpt |= (1 << kMethodJit);
-
- // Make sure all threads have current values
- dvmJitUpdateThreadStateAll();
-
- return true;
-}
-
-int dvmCompilerTargetOptHint(int key)
-{
- int res;
- switch (key) {
- case kMaxHoistDistance:
- res = 7;
- break;
- default:
- LOGE("Unknown target optimization hint key: %d",key);
- res = 0;
- }
- return res;
-}
-
-void dvmCompilerGenMemBarrier(CompilationUnit *cUnit, int barrierKind)
-{
-#if ANDROID_SMP != 0
- ArmLIR *dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
- dmb->defMask = ENCODE_ALL;
-#endif
-}
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp
similarity index 88%
copy from vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
copy to vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp
index 59d7c95..d68d150 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+extern "C" void dvmCompilerTemplateStart(void);
+
/*
* Determine the initial instruction set to be used for this trace.
* Later components may decide to change this.
@@ -23,16 +25,15 @@
return DALVIK_JIT_THUMB2;
}
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern "C" void dvmCompiler_TEMPLATE_##X();
#include "../../../template/armv5te-vfp/TemplateOpList.h"
#undef JIT_TEMPLATE
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchVariantInit(void)
+{
int i = 0;
- extern void dvmCompilerTemplateStart(void);
/*
* Then, populate the templateEntryOffsets array with the offsets from the
@@ -58,9 +59,9 @@
/* Codegen-specific assumptions */
assert(offsetof(ClassObject, vtable) < 128 &&
(offsetof(ClassObject, vtable) & 0x3) == 0);
- assert(offsetof(ArrayObject, length) < 128 &&
- (offsetof(ArrayObject, length) & 0x3) == 0);
- assert(offsetof(ArrayObject, contents) < 256);
+ assert(OFFSETOF_MEMBER(ArrayObject, length) < 128 &&
+ (OFFSETOF_MEMBER(ArrayObject, length) & 0x3) == 0);
+ assert(OFFSETOF_MEMBER(ArrayObject, contents) < 256);
/* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
assert(sizeof(StackSaveArea) < 236);
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.h b/vm/compiler/codegen/arm/armv7-a/ArchVariant.h
index fa01210..66e236b 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.h
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.h
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#ifndef _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
-#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
+#ifndef _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV7_A_ARCHVARIANT_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV7_A_ARCHVARIANT_H
/* Create the TemplateOpcode enum */
#define JIT_TEMPLATE(X) TEMPLATE_##X,
-typedef enum {
+enum TemplateOpcode {
#include "../../../template/armv5te-vfp/TemplateOpList.h"
/*
* For example,
@@ -28,7 +28,7 @@
* ...
*/
TEMPLATE_LAST_MARK,
-} TemplateOpcode;
+};
#undef JIT_TEMPLATE
-#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H */
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV7_A_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/arm/armv7-a/Codegen.c b/vm/compiler/codegen/arm/armv7-a/Codegen.cpp
similarity index 80%
rename from vm/compiler/codegen/arm/armv7-a/Codegen.c
rename to vm/compiler/codegen/arm/armv7-a/Codegen.cpp
index 36771ef..e1b0ee9 100644
--- a/vm/compiler/codegen/arm/armv7-a/Codegen.c
+++ b/vm/compiler/codegen/arm/armv7-a/Codegen.cpp
@@ -29,28 +29,28 @@
#include "ArchVariant.h"
/* Arm codegen building blocks */
-#include "../CodegenCommon.c"
+#include "../CodegenCommon.cpp"
/* Thumb2-specific factory utilities */
-#include "../Thumb2/Factory.c"
+#include "../Thumb2/Factory.cpp"
/* Target independent factory utilities */
-#include "../../CodegenFactory.c"
+#include "../../CodegenFactory.cpp"
/* Arm-specific factory utilities */
-#include "../ArchFactory.c"
+#include "../ArchFactory.cpp"
/* Thumb2-specific codegen routines */
-#include "../Thumb2/Gen.c"
+#include "../Thumb2/Gen.cpp"
/* Thumb2+VFP codegen routines */
-#include "../FP/Thumb2VFP.c"
+#include "../FP/Thumb2VFP.cpp"
/* Thumb2-specific register allocation */
-#include "../Thumb2/Ralloc.c"
+#include "../Thumb2/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Driver for method-based JIT */
-#include "../armv7-a-neon/MethodCodegenDriver.c"
+#include "../armv7-a-neon/MethodCodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
diff --git a/vm/compiler/codegen/x86/ArchUtility.c b/vm/compiler/codegen/x86/ArchUtility.cpp
similarity index 100%
rename from vm/compiler/codegen/x86/ArchUtility.c
rename to vm/compiler/codegen/x86/ArchUtility.cpp
diff --git a/vm/compiler/codegen/x86/Assemble.c b/vm/compiler/codegen/x86/Assemble.cpp
similarity index 100%
rename from vm/compiler/codegen/x86/Assemble.c
rename to vm/compiler/codegen/x86/Assemble.cpp
diff --git a/vm/compiler/codegen/x86/CalloutHelper.h b/vm/compiler/codegen/x86/CalloutHelper.h
index a64f017..52c030f 100644
--- a/vm/compiler/codegen/x86/CalloutHelper.h
+++ b/vm/compiler/codegen/x86/CalloutHelper.h
@@ -54,6 +54,6 @@
* Functions declared in gDvmInlineOpsTable[] are used for
* OP_EXECUTE_INLINE & OP_EXECUTE_INLINE_RANGE.
*/
-double sqrt(double x); // INLINE_MATH_SQRT
+extern "C" double sqrt(double x); // INLINE_MATH_SQRT
#endif /* _DALVIK_VM_COMPILER_CODEGEN_X86_CALLOUT_HELPER_H */
diff --git a/vm/compiler/codegen/x86/CodegenDriver.c b/vm/compiler/codegen/x86/CodegenDriver.cpp
similarity index 100%
rename from vm/compiler/codegen/x86/CodegenDriver.c
rename to vm/compiler/codegen/x86/CodegenDriver.cpp
diff --git a/vm/compiler/codegen/x86/ia32/ArchVariant.c b/vm/compiler/codegen/x86/ia32/ArchVariant.cpp
similarity index 88%
rename from vm/compiler/codegen/x86/ia32/ArchVariant.c
rename to vm/compiler/codegen/x86/ia32/ArchVariant.cpp
index 90f14a3..5ccd26d 100644
--- a/vm/compiler/codegen/x86/ia32/ArchVariant.c
+++ b/vm/compiler/codegen/x86/ia32/ArchVariant.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+extern "C" void dvmCompilerTemplateStart(void);
+
/*
* This file is included by Codegen-x86.c, and implements architecture
* variant-specific code.
@@ -28,16 +30,15 @@
return DALVIK_JIT_IA32;
}
-/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchVariantInit(void)
-{
- /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
-#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern "C" void dvmCompiler_TEMPLATE_##X();
#include "../../../template/ia32/TemplateOpList.h"
#undef JIT_TEMPLATE
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchVariantInit(void)
+{
int i = 0;
- extern void dvmCompilerTemplateStart(void);
/*
* Then, populate the templateEntryOffsets array with the offsets from the
@@ -63,9 +64,9 @@
/* Codegen-specific assumptions */
assert(offsetof(ClassObject, vtable) < 128 &&
(offsetof(ClassObject, vtable) & 0x3) == 0);
- assert(offsetof(ArrayObject, length) < 128 &&
- (offsetof(ArrayObject, length) & 0x3) == 0);
- assert(offsetof(ArrayObject, contents) < 256);
+ assert(OFFSETOF_MEMBER(ArrayObject, length) < 128 &&
+ (OFFSETOF_MEMBER(ArrayObject, length) & 0x3) == 0);
+ assert(OFFSETOF_MEMBER(ArrayObject, contents) < 256);
/* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
assert(sizeof(StackSaveArea) < 236);
diff --git a/vm/compiler/codegen/x86/ia32/ArchVariant.h b/vm/compiler/codegen/x86/ia32/ArchVariant.h
index e4eebf3..c5ce38e 100644
--- a/vm/compiler/codegen/x86/ia32/ArchVariant.h
+++ b/vm/compiler/codegen/x86/ia32/ArchVariant.h
@@ -19,7 +19,7 @@
/* Create the TemplateOpcode enum */
#define JIT_TEMPLATE(X) TEMPLATE_##X,
-typedef enum {
+enum TemplateOpcode {
#include "../../../template/ia32/TemplateOpList.h"
/*
* For example,
@@ -28,7 +28,7 @@
* ...
*/
TEMPLATE_LAST_MARK,
-} TemplateOpcode;
+};
#undef JIT_TEMPLATE
#endif /* _DALVIK_VM_COMPILER_CODEGEN_X86_IA32_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/x86/ia32/Codegen.c b/vm/compiler/codegen/x86/ia32/Codegen.cpp
similarity index 86%
rename from vm/compiler/codegen/x86/ia32/Codegen.c
rename to vm/compiler/codegen/x86/ia32/Codegen.cpp
index 4c2a759..ae55cd1 100644
--- a/vm/compiler/codegen/x86/ia32/Codegen.c
+++ b/vm/compiler/codegen/x86/ia32/Codegen.cpp
@@ -28,18 +28,18 @@
#include "ArchVariant.h"
/* Architectural independent building blocks */
-//#include "../CodegenCommon.c"
+//#include "../CodegenCommon.cpp"
/* Architectural independent building blocks */
-//#include "../Thumb/Factory.c"
+//#include "../Thumb/Factory.cpp"
/* Factory utilities dependent on arch-specific features */
-//#include "../CodegenFactory.c"
+//#include "../CodegenFactory.cpp"
/* ia32 register allocation */
-//#include "../ia32/Ralloc.c"
+//#include "../ia32/Ralloc.cpp"
/* MIR2LIR dispatcher and architectural independent codegen routines */
-#include "../CodegenDriver.c"
+#include "../CodegenDriver.cpp"
/* Architecture manifest */
-#include "ArchVariant.c"
+#include "ArchVariant.cpp"
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
index e76b766..03b97a4 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
@@ -36,7 +36,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
index 38ade41..2a73c22 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -27,7 +27,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -62,7 +62,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
index c88e1f2..a7a0961 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -43,7 +43,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
index e87f335..d074c9e 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -36,7 +36,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -49,6 +49,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 5195d0b..16660ae 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -12,10 +12,10 @@
mov r2, #0
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
@@ -50,7 +50,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 58c3ebf..331d902 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -197,7 +197,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -210,6 +210,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -265,7 +267,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -323,7 +325,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -434,7 +436,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -469,7 +471,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1533,7 +1535,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -1546,6 +1548,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -1605,7 +1609,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -1667,7 +1671,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -1786,7 +1790,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -1821,7 +1825,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1859,10 +1863,10 @@
mov r2, #0
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
@@ -1897,7 +1901,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 1021481..044843e 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -197,7 +197,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -210,6 +210,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -265,7 +267,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -323,7 +325,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -434,7 +436,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -469,7 +471,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1264,7 +1266,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -1277,6 +1279,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -1336,7 +1340,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -1398,7 +1402,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -1517,7 +1521,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -1552,7 +1556,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1590,10 +1594,10 @@
mov r2, #0
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
@@ -1628,7 +1632,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
index 804b471..ba798e0 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
@@ -197,7 +197,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -210,6 +210,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -265,7 +267,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -323,7 +325,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -434,7 +436,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -469,7 +471,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1533,7 +1535,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -1546,6 +1548,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -1605,7 +1609,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -1667,7 +1671,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -1786,7 +1790,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -1821,7 +1825,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1859,10 +1863,10 @@
mov r2, #0
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
@@ -1897,7 +1901,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index d8713d9..825ac40 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -197,7 +197,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -210,6 +210,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -265,7 +267,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -323,7 +325,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -434,7 +436,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -469,7 +471,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1533,7 +1535,7 @@
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
str r0, [rSELF, #offThread_methodClassDex]
cmp r8, #0 @ check the break flags
@@ -1546,6 +1548,8 @@
#endif
mov pc, r1 @ callsite is interpreted
1:
+ mov r0, #0
+ str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
ldr r2, .LdvmMterpStdBail @ defined in footer.S
mov r0, rSELF @ Expecting rSELF in r0
@@ -1605,7 +1609,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@@ -1667,7 +1671,7 @@
str r0, [rSELF, #offThread_method] @ self->method = methodToCall
str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
mov rFP, r1 @ fp = newFp
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@@ -1786,7 +1790,7 @@
@ go ahead and transfer control to the native code
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
mov r2, #0
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
@@ -1821,7 +1825,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
@@ -1859,10 +1863,10 @@
mov r2, #0
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
@@ -1897,7 +1901,7 @@
ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
diff --git a/vm/hprof/Hprof.c b/vm/hprof/Hprof.cpp
similarity index 100%
rename from vm/hprof/Hprof.c
rename to vm/hprof/Hprof.cpp
diff --git a/vm/hprof/Hprof.h b/vm/hprof/Hprof.h
index c62dd9c..e31ccc3 100644
--- a/vm/hprof/Hprof.h
+++ b/vm/hprof/Hprof.h
@@ -32,7 +32,7 @@
typedef hprof_id hprof_object_id;
typedef hprof_id hprof_class_object_id;
-typedef enum hprof_basic_type {
+enum hprof_basic_type {
hprof_basic_object = 2,
hprof_basic_boolean = 4,
hprof_basic_char = 5,
@@ -42,9 +42,9 @@
hprof_basic_short = 9,
hprof_basic_int = 10,
hprof_basic_long = 11,
-} hprof_basic_type;
+};
-typedef enum hprof_tag_t {
+enum hprof_tag_t {
HPROF_TAG_STRING = 0x01,
HPROF_TAG_LOAD_CLASS = 0x02,
HPROF_TAG_UNLOAD_CLASS = 0x03,
@@ -59,13 +59,13 @@
HPROF_TAG_HEAP_DUMP_END = 0x2C,
HPROF_TAG_CPU_SAMPLES = 0x0D,
HPROF_TAG_CONTROL_SETTINGS = 0x0E,
-} hprof_tag_t;
+};
/* Values for the first byte of
* HEAP_DUMP and HEAP_DUMP_SEGMENT
* records:
*/
-typedef enum hprof_heap_tag_t {
+enum hprof_heap_tag_t {
/* standard */
HPROF_ROOT_UNKNOWN = 0xFF,
HPROF_ROOT_JNI_GLOBAL = 0x01,
@@ -91,7 +91,7 @@
HPROF_ROOT_JNI_MONITOR = 0x8e,
HPROF_UNREACHABLE = 0x90, /* obsolete */
HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,
-} hprof_heap_tag_t;
+};
/* Represents a top-level hprof record, whose serialized
* format is:
@@ -102,22 +102,22 @@
* and belong to this record
* [u1]* BODY: as many bytes as specified in the above u4 field
*/
-typedef struct hprof_record_t {
+struct hprof_record_t {
unsigned char *body;
u4 time;
u4 length;
size_t allocLen;
u1 tag;
bool dirty;
-} hprof_record_t;
+};
-typedef enum {
+enum HprofHeapId {
HPROF_HEAP_DEFAULT = 0,
HPROF_HEAP_ZYGOTE = 'Z',
HPROF_HEAP_APP = 'A'
-} HprofHeapId;
+};
-typedef struct hprof_context_t {
+struct hprof_context_t {
/* curRec *must* be first so that we
* can cast from a context to a record.
*/
@@ -140,11 +140,11 @@
size_t fileDataSize; // for open_memstream
FILE *memFp;
int fd;
-} hprof_context_t;
+};
/*
- * HprofString.c functions
+ * HprofString.cpp functions
*/
hprof_string_id hprofLookupStringId(const char *str);
@@ -156,7 +156,7 @@
/*
- * HprofClass.c functions
+ * HprofClass.cpp functions
*/
hprof_class_object_id hprofLookupClassId(const ClassObject *clazz);
@@ -168,7 +168,7 @@
/*
- * HprofHeap.c functions
+ * HprofHeap.cpp functions
*/
int hprofStartHeapDump(hprof_context_t *ctx);
@@ -182,7 +182,7 @@
int hprofDumpHeapObject(hprof_context_t *ctx, const Object *obj);
/*
- * HprofOutput.c functions
+ * HprofOutput.cpp functions
*/
void hprofContextInit(hprof_context_t *ctx, char *fileName, int fd,
@@ -215,18 +215,13 @@
hprofAddU4ListToRecord((rec), (const u4 *)(values), (numValues))
/*
- * Hprof.c functions
+ * Hprof.cpp functions
*/
hprof_context_t* hprofStartup(const char *outputFileName, int fd,
bool directToDdms);
bool hprofShutdown(hprof_context_t *ctx);
void hprofFreeContext(hprof_context_t *ctx);
-
-/*
- * HprofVisit.c functions
- */
-
int hprofDumpHeap(const char* fileName, int fd, bool directToDdms);
#endif // _DALVIK_HPROF_HPROF
diff --git a/vm/hprof/HprofClass.c b/vm/hprof/HprofClass.cpp
similarity index 100%
rename from vm/hprof/HprofClass.c
rename to vm/hprof/HprofClass.cpp
diff --git a/vm/hprof/HprofHeap.c b/vm/hprof/HprofHeap.cpp
similarity index 94%
rename from vm/hprof/HprofHeap.c
rename to vm/hprof/HprofHeap.cpp
index ee24a7a..8e9cd9d 100644
--- a/vm/hprof/HprofHeap.c
+++ b/vm/hprof/HprofHeap.cpp
@@ -129,7 +129,7 @@
{
hprof_record_t *rec = &ctx->curRec;
int err;
- hprof_heap_tag_t heapTag = ctx->gcScanState;
+ hprof_heap_tag_t heapTag = (hprof_heap_tag_t)ctx->gcScanState;
if (heapTag == 0) {
return 0;
@@ -276,16 +276,11 @@
* allocated which hasn't been initialized yet.
*/
} else {
- hprof_class_object_id clazzId;
-
- clazzId = hprofLookupClassId(clazz);
-
- if (clazz == gDvm.classJavaLangClass) {
+ if (dvmIsClassObject(obj)) {
const ClassObject *thisClass = (const ClassObject *)obj;
- int i, sFieldCount, iFieldCount;
/* obj is a ClassObject.
*/
- sFieldCount = thisClass->sfieldCount;
+ int sFieldCount = thisClass->sfieldCount;
if (sFieldCount != 0) {
int byteLength = sFieldCount*sizeof(StaticField);
/* Create a byte array to reflect the allocation of the
@@ -296,7 +291,7 @@
hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
hprofAddU4ToRecord(rec, byteLength);
hprofAddU1ToRecord(rec, hprof_basic_byte);
- for (i = 0; i < byteLength; i++) {
+ for (int i = 0; i < byteLength; i++) {
hprofAddU1ToRecord(rec, 0);
}
}
@@ -331,7 +326,7 @@
hprofLookupStringId(STATIC_OVERHEAD_NAME));
hprofAddU1ToRecord(rec, hprof_basic_object);
hprofAddIdToRecord(rec, CLASS_STATICS_ID(obj));
- for (i = 0; i < sFieldCount; i++) {
+ for (int i = 0; i < sFieldCount; i++) {
hprof_basic_type t;
size_t size;
const StaticField *f = &thisClass->sfields[i];
@@ -355,9 +350,9 @@
/* Instance fields for this class (no superclass fields)
*/
- iFieldCount = thisClass->ifieldCount;
+ int iFieldCount = thisClass->ifieldCount;
hprofAddU2ToRecord(rec, (u2)iFieldCount);
- for (i = 0; i < iFieldCount; i++) {
+ for (int i = 0; i < iFieldCount; i++) {
const InstField *f = &thisClass->ifields[i];
hprof_basic_type t;
@@ -382,7 +377,7 @@
/* Dump the elements, which are always objects or NULL.
*/
hprofAddIdListToRecord(rec,
- (const hprof_object_id *)aobj->contents, length);
+ (const hprof_object_id *)(void *)aobj->contents, length);
} else {
hprof_basic_type t;
size_t size;
@@ -410,10 +405,10 @@
hprofAddU1ListToRecord(rec, (const u1 *)aobj->contents,
length);
} else if (size == 2) {
- hprofAddU2ListToRecord(rec, (const u2 *)aobj->contents,
+ hprofAddU2ListToRecord(rec, (const u2 *)(void *)aobj->contents,
length);
} else if (size == 4) {
- hprofAddU4ListToRecord(rec, (const u4 *)aobj->contents,
+ hprofAddU4ListToRecord(rec, (const u4 *)(void *)aobj->contents,
length);
} else if (size == 8) {
hprofAddU8ListToRecord(rec, (const u8 *)aobj->contents,
@@ -444,10 +439,8 @@
*/
sclass = clazz;
while (sclass != NULL) {
- int i, ifieldCount;
-
- ifieldCount = sclass->ifieldCount;
- for (i = 0; i < ifieldCount; i++) {
+ int ifieldCount = sclass->ifieldCount;
+ for (int i = 0; i < ifieldCount; i++) {
const InstField *f = &sclass->ifields[i];
hprof_basic_type t;
size_t size;
diff --git a/vm/hprof/HprofOutput.c b/vm/hprof/HprofOutput.cpp
similarity index 93%
rename from vm/hprof/HprofOutput.c
rename to vm/hprof/HprofOutput.cpp
index b84b298..1543233 100644
--- a/vm/hprof/HprofOutput.c
+++ b/vm/hprof/HprofOutput.cpp
@@ -251,19 +251,15 @@
int
hprofAddU2ListToRecord(hprof_record_t *rec, const u2 *values, size_t numValues)
{
- unsigned char *insert;
- size_t i;
- int err;
-
- err = guaranteeRecordAppend(rec, numValues * 2);
+ int err = guaranteeRecordAppend(rec, numValues * 2);
if (err != 0) {
return err;
}
//xxx this can be way smarter
//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- insert = rec->body + rec->length;
- for (i = 0; i < numValues; i++) {
+ unsigned char *insert = rec->body + rec->length;
+ for (size_t i = 0; i < numValues; i++) {
U2_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
@@ -281,19 +277,15 @@
int
hprofAddU4ListToRecord(hprof_record_t *rec, const u4 *values, size_t numValues)
{
- unsigned char *insert;
- size_t i;
- int err;
-
- err = guaranteeRecordAppend(rec, numValues * 4);
+ int err = guaranteeRecordAppend(rec, numValues * 4);
if (err != 0) {
return err;
}
//xxx this can be way smarter
//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- insert = rec->body + rec->length;
- for (i = 0; i < numValues; i++) {
+ unsigned char *insert = rec->body + rec->length;
+ for (size_t i = 0; i < numValues; i++) {
U4_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
@@ -311,19 +303,15 @@
int
hprofAddU8ListToRecord(hprof_record_t *rec, const u8 *values, size_t numValues)
{
- unsigned char *insert;
- size_t i;
- int err;
-
- err = guaranteeRecordAppend(rec, numValues * 8);
+ int err = guaranteeRecordAppend(rec, numValues * 8);
if (err != 0) {
return err;
}
//xxx this can be way smarter
//xxx also, don't do this bytewise if aligned and on a matching-endian arch
- insert = rec->body + rec->length;
- for (i = 0; i < numValues; i++) {
+ unsigned char *insert = rec->body + rec->length;
+ for (size_t i = 0; i < numValues; i++) {
U8_TO_BUF_BE(insert, 0, *values++);
insert += sizeof(*values);
}
diff --git a/vm/hprof/HprofString.c b/vm/hprof/HprofString.cpp
similarity index 100%
rename from vm/hprof/HprofString.c
rename to vm/hprof/HprofString.cpp
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.cpp
similarity index 92%
rename from vm/interp/Interp.c
rename to vm/interp/Interp.cpp
index 092df32..11e9408 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.cpp
@@ -37,13 +37,28 @@
*/
// fwd
-static BreakpointSet* dvmBreakpointSetAlloc(void);
+static BreakpointSet* dvmBreakpointSetAlloc();
static void dvmBreakpointSetFree(BreakpointSet* pSet);
+#if defined(WITH_JIT)
+/* Target-specific save/restore */
+extern "C" void dvmJitCalleeSave(double *saveArea);
+extern "C" void dvmJitCalleeRestore(double *saveArea);
+/* Interpreter entry points from compiled code */
+extern "C" void dvmJitToInterpNormal();
+extern "C" void dvmJitToInterpNoChain();
+extern "C" void dvmJitToInterpPunt();
+extern "C" void dvmJitToInterpSingleStep();
+extern "C" void dvmJitToInterpTraceSelect();
+#if defined(WITH_SELF_VERIFICATION)
+extern "C" void dvmJitToInterpBackwardBranch();
+#endif
+#endif
+
/*
* Initialize global breakpoint structures.
*/
-bool dvmBreakpointStartup(void)
+bool dvmBreakpointStartup()
{
gDvm.breakpointSet = dvmBreakpointSetAlloc();
return (gDvm.breakpointSet != NULL);
@@ -52,7 +67,7 @@
/*
* Free resources.
*/
-void dvmBreakpointShutdown(void)
+void dvmBreakpointShutdown()
{
dvmBreakpointSetFree(gDvm.breakpointSet);
}
@@ -64,12 +79,12 @@
* The debugger may ask us to create the same breakpoint multiple times.
* We only remove the breakpoint when the last instance is cleared.
*/
-typedef struct {
+struct Breakpoint {
Method* method; /* method we're associated with */
u2* addr; /* absolute memory address */
u1 originalOpcode; /* original 8-bit opcode value */
int setCount; /* #of times this breakpoint was set */
-} Breakpoint;
+};
/*
* Set of breakpoints.
@@ -87,7 +102,7 @@
/*
* Initialize a BreakpointSet. Initially empty.
*/
-static BreakpointSet* dvmBreakpointSetAlloc(void)
+static BreakpointSet* dvmBreakpointSetAlloc()
{
BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
@@ -375,7 +390,7 @@
/*
* Do any debugger-attach-time initialization.
*/
-void dvmInitBreakpoints(void)
+void dvmInitBreakpoints()
{
/* quick sanity check */
BreakpointSet* pSet = gDvm.breakpointSet;
@@ -504,8 +519,8 @@
*/
}
- pCtrl->size = size;
- pCtrl->depth = depth;
+ pCtrl->size = static_cast<JdwpStepSize>(size);
+ pCtrl->depth = static_cast<JdwpStepDepth>(depth);
pCtrl->thread = thread;
/*
@@ -522,10 +537,11 @@
* on by PushLocalFrame, we want to use the topmost native method.
*/
const StackSaveArea* saveArea;
- void* fp;
- void* prevFp = NULL;
+ u4* fp;
+ u4* prevFp = NULL;
- for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
+ for (fp = thread->interpSave.curFrame; fp != NULL;
+ fp = saveArea->prevFrame) {
const Method* method;
saveArea = SAVEAREA_FROM_FP(fp);
@@ -572,7 +588,8 @@
pCtrl->pAddressSet
= dvmAddressSetForLine(saveArea->method, pCtrl->line);
}
- pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
+ pCtrl->frameDepth =
+ dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame);
pCtrl->active = true;
LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
@@ -615,7 +632,7 @@
int offset = self->interpSave.pc - curMethod->insns;
int catchRelPc = dvmFindCatchBlock(self, offset, exception,
true, &catchFrame);
- dvmDbgPostException(self->interpSave.fp, offset, catchFrame,
+ dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame,
catchRelPc, exception);
}
}
@@ -634,10 +651,10 @@
* The interpreter is preparing to do a native invoke. Handle any
* special subMode requirements. NOTE: for a native invoke,
* dvmReportInvoke() and dvmReportPreNativeInvoke() will both
- * be called prior to the invoke. All interpSave state must
- * be valid on entry.
+ * be called prior to the invoke. fp is the Dalvik FP of the calling
+ * method.
*/
-void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self)
+void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
{
#if defined(WITH_JIT)
/*
@@ -649,8 +666,7 @@
}
#endif
if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
- Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
- self->interpSave.fp);
+ Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
}
@@ -658,14 +674,13 @@
/*
* The interpreter has returned from a native invoke. Handle any
- * special subMode requirements. All interpSave state must be
- * valid on entry.
+ * special subMode requirements. fp is the Dalvik FP of the calling
+ * method.
*/
-void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self)
+void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
{
if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
- Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
- self->interpSave.fp);
+ Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
}
@@ -682,7 +697,7 @@
{
TRACE_METHOD_EXIT(self, self->interpSave.method);
#if defined(WITH_JIT)
- if (dvmIsBreakFrame(self->interpSave.fp) &&
+ if (dvmIsBreakFrame(self->interpSave.curFrame) &&
(self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
dvmCheckJit(self->interpSave.pc, self);
}
@@ -1419,9 +1434,10 @@
*/
void dvmThrowVerificationError(const Method* method, int kind, int ref)
{
- const int typeMask = 0xff << kVerifyErrorRefTypeShift;
- VerifyError errorKind = kind & ~typeMask;
- VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
+ int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift);
+ int errorRefPart = kind >> kVerifyErrorRefTypeShift;
+ VerifyError errorKind = static_cast<VerifyError>(errorPart);
+ VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart);
ClassObject* exceptionClass = gDvm.exVerifyError;
char* msg = NULL;
@@ -1479,27 +1495,22 @@
}
/*
- * Update interpBreak. If there is an active break when
- * we're done, set altHandlerTable. Otherwise, revert to
- * the non-breaking table base.
+ * Update interpBreak for a single thread.
*/
-void dvmUpdateInterpBreak(Thread* thread, int newBreak, int newMode,
- bool enable)
+void updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable)
{
InterpBreak oldValue, newValue;
-
- // Do not use this routine for suspend updates. See below.
- assert((newBreak & kInterpSuspendBreak) == 0);
-
do {
oldValue = newValue = thread->interpBreak;
- if (enable) {
- newValue.ctl.breakFlags |= newBreak;
- newValue.ctl.subMode |= newMode;
- } else {
- newValue.ctl.breakFlags &= ~newBreak;
- newValue.ctl.subMode &= ~newMode;
- }
+ newValue.ctl.breakFlags = kInterpNoBreak; // Assume full reset
+ if (enable)
+ newValue.ctl.subMode |= subMode;
+ else
+ newValue.ctl.subMode &= ~subMode;
+ if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK)
+ newValue.ctl.breakFlags |= kInterpSingleStep;
+ if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK)
+ newValue.ctl.breakFlags |= kInterpSafePoint;
newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
thread->altHandlerTable : thread->mainHandlerTable;
} while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
@@ -1507,55 +1518,61 @@
}
/*
- * Update the normal and debugger suspend counts for a thread.
- * threadSuspendCount must be acquired before calling this to
- * ensure a clean update of suspendCount, dbgSuspendCount and
- * sumThreadSuspendCount. suspendCount & dbgSuspendCount must
- * use the atomic update to avoid conflict with writes to the
- * other fields in interpBreak.
- *
- * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
- * Move under WITH_JIT ifdefs.
-*/
-void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
-{
- InterpBreak oldValue, newValue;
-
- do {
- oldValue = newValue = thread->interpBreak;
- newValue.ctl.suspendCount += delta;
- newValue.ctl.dbgSuspendCount += dbgDelta;
- assert(newValue.ctl.suspendCount >= newValue.ctl.dbgSuspendCount);
- if (newValue.ctl.suspendCount > 0) {
- newValue.ctl.breakFlags |= kInterpSuspendBreak;
- } else {
- newValue.ctl.breakFlags &= ~kInterpSuspendBreak;
- }
- newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
- thread->altHandlerTable : thread->mainHandlerTable;
- } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
- &thread->interpBreak.all) != 0);
-
- // Update the global suspend count total
- gDvm.sumThreadSuspendCount += delta;
-}
-
-/*
* Update interpBreak for all threads.
*/
-void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable)
+void updateAllInterpBreak(ExecutionSubModes subMode, bool enable)
{
Thread* self = dvmThreadSelf();
Thread* thread;
dvmLockThreadList(self);
for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
- dvmUpdateInterpBreak(thread, newBreak, newMode, enable);
+ updateInterpBreak(thread, subMode, enable);
}
dvmUnlockThreadList();
}
/*
+ * Update the normal and debugger suspend counts for a thread.
+ * threadSuspendCount must be acquired before calling this to
+ * ensure a clean update of suspendCount, dbgSuspendCount and
+ * sumThreadSuspendCount.
+ *
+ * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
+ * Move under WITH_JIT ifdefs.
+*/
+void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
+{
+ thread->suspendCount += delta;
+ thread->dbgSuspendCount += dbgDelta;
+ updateInterpBreak(thread, kSubModeSuspendPending,
+ (thread->suspendCount != 0));
+ // Update the global suspend count total
+ gDvm.sumThreadSuspendCount += delta;
+}
+
+
+void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode)
+{
+ updateInterpBreak(thread, subMode, false);
+}
+
+void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode)
+{
+ updateInterpBreak(thread, subMode, true);
+}
+
+void dvmEnableAllSubMode(ExecutionSubModes subMode)
+{
+ updateAllInterpBreak(subMode, true);
+}
+
+void dvmDisableAllSubMode(ExecutionSubModes subMode)
+{
+ updateAllInterpBreak(subMode, false);
+}
+
+/*
* Do a sanity check on interpreter state saved to Thread.
* A failure here doesn't necessarily mean that something is wrong,
* so this code should only be used during development to suggest
@@ -1617,8 +1634,11 @@
if ((funct == NULL) || (thread->callback == NULL)) {
thread->callback = funct;
thread->callbackArg = arg;
- dvmUpdateInterpBreak(thread, kInterpSafePointCallback,
- kSubModeNormal, (funct != NULL));
+ if (funct != NULL) {
+ dvmEnableSubMode(thread, kSubModeCallbackPending);
+ } else {
+ dvmDisableSubMode(thread, kSubModeCallbackPending);
+ }
} else {
// Already armed. Different?
if ((funct != thread->callback) ||
@@ -1639,15 +1659,6 @@
void dvmInitInterpreterState(Thread* self)
{
#if defined(WITH_JIT)
- /* Interpreter entry points from compiled code */
- extern void dvmJitToInterpNormal();
- extern void dvmJitToInterpNoChain();
- extern void dvmJitToInterpPunt();
- extern void dvmJitToInterpSingleStep();
- extern void dvmJitToInterpTraceSelect();
-#if defined(WITH_SELF_VERIFICATION)
- extern void dvmJitToInterpBackwardBranch();
-#endif
/*
* Reserve a static entity here to quickly setup runtime contents as
* gcc will issue block copy instructions.
@@ -1676,6 +1687,7 @@
// Jit state that can change
dvmJitUpdateThreadStateSingle(self);
#endif
+ dvmInitializeInterpBreak(self);
}
/*
@@ -1685,21 +1697,22 @@
*/
void dvmInitializeInterpBreak(Thread* thread)
{
- u1 flags = 0;
- u1 subModes = 0;
-
if (gDvm.instructionCountEnableCount > 0) {
- flags |= kInterpInstCountBreak;
- subModes |= kSubModeInstCounting;
+ dvmEnableSubMode(thread, kSubModeInstCounting);
}
if (dvmIsMethodTraceActive()) {
- subModes |= kSubModeMethodTrace;
+ dvmEnableSubMode(thread, kSubModeMethodTrace);
+ }
+ if (gDvm.emulatorTraceEnableCount > 0) {
+ dvmEnableSubMode(thread, kSubModeEmulatorTrace);
}
if (gDvm.debuggerActive) {
- flags |= kInterpDebugBreak;
- subModes |= kSubModeDebuggerActive;
+ dvmEnableSubMode(thread, kSubModeDebuggerActive);
}
- dvmUpdateInterpBreak(thread, flags, subModes, true);
+#if 0
+ // Debugging stress mode - force checkBefore
+ dvmEnableSubMode(thread, kSubModeCheckAlways);
+#endif
}
/*
@@ -1742,14 +1755,14 @@
#endif
/* Safe point handling */
- if (self->interpBreak.ctl.suspendCount ||
- (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback)) {
+ if (self->suspendCount ||
+ (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) {
// Are we are a safe point?
int flags;
flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
if (flags & VERIFY_GC_INST_MASK) {
// Yes, at a safe point. Pending callback?
- if (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback) {
+ if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) {
SafePointCallback callback;
void* arg;
// Get consistent funct/arg pair
@@ -1759,7 +1772,7 @@
dvmUnlockMutex(&self->callbackMutex);
// Update Thread structure
self->interpSave.pc = pc;
- self->interpSave.fp = fp;
+ self->interpSave.curFrame = fp;
if (callback != NULL) {
// Do the callback
if (!callback(self,arg)) {
@@ -1769,7 +1782,7 @@
}
}
// Need to suspend?
- if (self->interpBreak.ctl.suspendCount) {
+ if (self->suspendCount) {
dvmExportPC(pc, fp);
dvmCheckSuspendPending(self);
}
@@ -1798,7 +1811,8 @@
#if defined(WITH_JIT)
// Does the JIT need anything done now?
- if (self->interpBreak.ctl.breakFlags & kInterpJitBreak) {
+ if (self->interpBreak.ctl.subMode &
+ (kSubModeJitTraceBuild | kSubModeJitSV)) {
// Are we building a trace?
if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
dvmCheckJit(pc, self);
@@ -1820,8 +1834,7 @@
if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
if (self->singleStepCount == 0) {
// We've exhausted our single step count
- dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
- false /* remove */);
+ dvmDisableSubMode(self, kSubModeCountedStep);
#if defined(WITH_JIT)
#if 0
/*
@@ -1888,13 +1901,10 @@
void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
{
InterpSaveState interpSaveState;
- int savedBreakFlags;
- int savedSubModes;
+ ExecutionSubModes savedSubModes;
#if defined(WITH_JIT)
/* Target-specific save/restore */
- extern void dvmJitCalleeSave(double *saveArea);
- extern void dvmJitCalleeRestore(double *saveArea);
double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
/*
* If the previous VM left the code cache through single-stepping the
@@ -1915,11 +1925,10 @@
* Strip out and save any flags that should not be inherited by
* nested interpreter activation.
*/
- savedBreakFlags = self->interpBreak.ctl.breakFlags & LOCAL_BREAKFLAGS;
- savedSubModes = self->interpBreak.ctl.subMode & LOCAL_SUBMODE;
- if (savedBreakFlags | savedSubModes) {
- dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
- false /*disable*/);
+ savedSubModes = (ExecutionSubModes)(
+ self->interpBreak.ctl.subMode & LOCAL_SUBMODE);
+ if (savedSubModes != kSubModeNormal) {
+ dvmDisableSubMode(self, savedSubModes);
}
#if defined(WITH_JIT)
dvmJitCalleeSave(calleeSave);
@@ -1943,7 +1952,7 @@
* No need to initialize "retval".
*/
self->interpSave.method = method;
- self->interpSave.fp = (u4*) self->curFrame;
+ self->interpSave.curFrame = (u4*) self->interpSave.curFrame;
self->interpSave.pc = method->insns;
assert(!dvmIsNativeMethod(method));
@@ -1982,8 +1991,7 @@
#if defined(WITH_JIT)
dvmJitCalleeRestore(calleeSave);
#endif
- if (savedBreakFlags | savedSubModes) {
- dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
- true /*enable*/);
+ if (savedSubModes != kSubModeNormal) {
+ dvmEnableSubMode(self, savedSubModes);
}
}
diff --git a/vm/interp/Interp.h b/vm/interp/Interp.h
index 91e2262..0667a2e 100644
--- a/vm/interp/Interp.h
+++ b/vm/interp/Interp.h
@@ -46,7 +46,8 @@
* This is called from the handler for the throw-verification-error
* instruction. "method" is the method currently being executed.
*/
-void dvmThrowVerificationError(const Method* method, int kind, int ref);
+extern "C" void dvmThrowVerificationError(const Method* method,
+ int kind, int ref);
/*
* One-time initialization and shutdown.
@@ -67,7 +68,7 @@
/*
* Recover the opcode that was replaced by a breakpoint.
*/
-u1 dvmGetOriginalOpcode(const u2* addr);
+extern "C" u1 dvmGetOriginalOpcode(const u2* addr);
/*
* Flush any breakpoints associated with methods in "clazz".
@@ -77,28 +78,25 @@
/*
* Debugger support
*/
-void dvmCheckBefore(const u2 *dPC, u4 *fp, Thread* self);
-void dvmReportExceptionThrow(Thread* self, Object* exception);
-void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self);
-void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self);
-void dvmReportInvoke(Thread* self, const Method* methodToCall);
-void dvmReportReturn(Thread* self);
+extern "C" void dvmCheckBefore(const u2 *dPC, u4 *fp, Thread* self);
+extern "C" void dvmReportExceptionThrow(Thread* self, Object* exception);
+extern "C" void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp);
+extern "C" void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp);
+extern "C" void dvmReportInvoke(Thread* self, const Method* methodToCall);
+extern "C" void dvmReportReturn(Thread* self);
/*
- * Update interpBreak
+ * InterpBreak & subMode control
*/
-void dvmUpdateInterpBreak(Thread* thread, int newBreak, int newMode,
- bool enable);
+void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode);
+extern "C" void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode);
+void dvmDisableAllSubMode(ExecutionSubModes subMode);
+void dvmEnableAllSubMode(ExecutionSubModes subMode);
void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta);
void dvmCheckInterpStateConsistency();
void dvmInitializeInterpBreak(Thread* thread);
/*
- * Update interpBreak for all threads
- */
-void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable);
-
-/*
* Register a callback to occur at the next safe point for a single thread.
* If funct is NULL, the previous registration is cancelled.
*
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index d39a6b8..f362442 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -59,13 +59,13 @@
/*
* Process switch statement.
*/
-s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
-s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
+extern "C" s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
+extern "C" s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
/*
* Process fill-array-data.
*/
-bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
+extern "C" bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
const u2* arrayData);
/*
diff --git a/vm/interp/InterpState.h b/vm/interp/InterpState.h
index 6f86476..b782275 100644
--- a/vm/interp/InterpState.h
+++ b/vm/interp/InterpState.h
@@ -27,14 +27,14 @@
/*
* Execution mode, e.g. interpreter vs. JIT.
*/
-typedef enum ExecutionMode {
+enum ExecutionMode {
kExecutionModeUnknown = 0,
kExecutionModeInterpPortable,
kExecutionModeInterpFast,
#if defined(WITH_JIT)
kExecutionModeJit,
#endif
-} ExecutionMode;
+};
/*
* Execution sub modes, e.g. debugging, profiling, etc.
@@ -42,21 +42,23 @@
* by assembly code in the mterp interpeter and may also be used by
* code generated by the JIT. Take care when changing.
*/
-typedef enum ExecutionSubModes {
- kSubModeNormal = 0x00,
- kSubModeMethodTrace = 0x01,
- kSubModeEmulatorTrace = 0x02,
- kSubModeInstCounting = 0x04,
- kSubModeDebuggerActive = 0x08,
-#if defined(WITH_JIT)
- kSubModeJitTraceBuild = 0x10,
- kSubModeJitSV = 0x20,
-#endif
+enum ExecutionSubModes {
+ kSubModeNormal = 0x0000, /* No active subMode */
+ kSubModeMethodTrace = 0x0001,
+ kSubModeEmulatorTrace = 0x0002,
+ kSubModeInstCounting = 0x0004,
+ kSubModeDebuggerActive = 0x0008,
+ kSubModeSuspendPending = 0x0010,
+ kSubModeCallbackPending = 0x0020,
+ kSubModeCountedStep = 0x0040,
+ kSubModeCheckAlways = 0x0080,
+ kSubModeJitTraceBuild = 0x4000,
+ kSubModeJitSV = 0x8000,
kSubModeDebugProfile = (kSubModeMethodTrace |
kSubModeEmulatorTrace |
kSubModeInstCounting |
kSubModeDebuggerActive)
-} ExecutionSubModes;
+};
/*
* Interpreter break flags. When set, causes the interpreter to
@@ -64,18 +66,25 @@
* handler.
*/
-typedef enum InterpBreakFlags {
- kInterpNoBreak = 0x00,
- kInterpSuspendBreak = 0x01,
- kInterpInstCountBreak = 0x02,
- kInterpDebugBreak = 0x04,
- kInterpEmulatorTraceBreak = 0x08,
- kInterpSingleStep = 0x10,
- kInterpSafePointCallback = 0x20,
-#if defined(WITH_JIT)
- kInterpJitBreak = 0x40,
-#endif
-} InterpBreakFlags;
+enum InterpBreakFlags {
+ kInterpNoBreak = 0x00, /* Don't check */
+ kInterpSingleStep = 0x01, /* Check between each inst */
+ kInterpSafePoint = 0x02, /* Check at safe points */
+};
+
+/*
+ * Mapping between subModes and required check intervals. Note: in
+ * the future we might want to make this mapping target-dependent.
+ */
+#define SINGLESTEP_BREAK_MASK ( kSubModeInstCounting | \
+ kSubModeDebuggerActive | \
+ kSubModeCountedStep | \
+ kSubModeCheckAlways | \
+ kSubModeJitSV | \
+ kSubModeJitTraceBuild )
+
+#define SAFEPOINT_BREAK_MASK ( kSubModeSuspendPending | \
+ kSubModeCallbackPending )
typedef bool (*SafePointCallback)(struct Thread* thread, void* arg);
@@ -83,30 +92,11 @@
* Identify which break and submode flags should be local
* to an interpreter activation.
*/
-#if defined(WITH_JIT)
#define LOCAL_SUBMODE (kSubModeJitTraceBuild)
-#define LOCAL_BREAKFLAGS (kInterpJitBreak | kInterpSingleStep)
-#else
-#define LOCAL_SUBMODE (0)
-#define LOCAL_BREAKFLAGS (0)
-#endif
-
-/*
- * Specify the starting point when switching between interpreters.
- */
-typedef enum InterpEntry {
- kInterpEntryInstr = 0, // continue to next instruction
- kInterpEntryReturn = 1, // jump to method return
- kInterpEntryThrow = 2, // jump to exception throw
-#if defined(WITH_JIT)
- kInterpEntryResume = 3, // Resume after single-step
-#endif
-} InterpEntry;
-
-typedef struct InterpSaveState {
+struct InterpSaveState {
const u2* pc; // Dalvik PC
- u4* fp; // Dalvik frame pointer
+ u4* curFrame; // Dalvik frame pointer
const Method *method; // Method being executed
DvmDex* methodClassDex;
void* bailPtr;
@@ -116,7 +106,7 @@
int unused; // Keep struct size constant
#endif
struct InterpSaveState* prev; // To follow nested activations
-} InterpSaveState;
+};
#ifdef WITH_JIT
/*
@@ -145,20 +135,20 @@
* destination Dalvik PC is included by the trace itself.
*/
struct JitToInterpEntries {
- void *dvmJitToInterpNormal;
- void *dvmJitToInterpNoChain;
- void *dvmJitToInterpPunt;
- void *dvmJitToInterpSingleStep;
- void *dvmJitToInterpTraceSelect;
+ void (*dvmJitToInterpNormal)(void);
+ void (*dvmJitToInterpNoChain)(void);
+ void (*dvmJitToInterpPunt)(void);
+ void (*dvmJitToInterpSingleStep)(void);
+ void (*dvmJitToInterpTraceSelect)(void);
#if defined(WITH_SELF_VERIFICATION)
- void *dvmJitToInterpBackwardBranch;
+ void (*dvmJitToInterpBackwardBranch)(void);
#else
- void *unused; // Keep structure size constant
+ void (*unused)(void); // Keep structure size constant
#endif
};
/* States of the interpreter when serving a JIT-related request */
-typedef enum JitState {
+enum JitState {
/* Entering states in the debug interpreter */
kJitNot = 0, // Non-JIT related reasons */
kJitTSelectRequest = 1, // Request a trace (subject to filtering)
@@ -169,10 +159,10 @@
kJitTSelect = 4, // Actively selecting a trace
kJitTSelectEnd = 5, // Done with the trace - wrap it up
kJitDone = 6, // No further JIT actions for interpBreak
-} JitState;
+};
#if defined(WITH_SELF_VERIFICATION)
-typedef enum SelfVerificationState {
+enum SelfVerificationState {
kSVSIdle = 0, // Idle
kSVSStart = 1, // Shadow space set up, running compiled code
kSVSPunt = 2, // Exiting compiled code by punting
@@ -183,7 +173,7 @@
kSVSNoChain = 7, // Exiting compiled code by no chain
kSVSBackwardBranch = 8, // Exiting compiled code with backward branch trace
kSVSDebugInterp = 9, // Normal state restored, running debug interpreter
-} SelfVerificationState;
+};
#endif
/* Number of entries in the 2nd level JIT profiler filter cache */
@@ -192,23 +182,23 @@
#define JIT_TRACE_THRESH_FILTER_PC_BITS 4
#define MAX_JIT_RUN_LEN 64
-typedef enum JitHint {
+enum JitHint {
kJitHintNone = 0,
kJitHintTaken = 1, // Last inst in run was taken branch
kJitHintNotTaken = 2, // Last inst in run was not taken branch
kJitHintNoBias = 3, // Last inst in run was unbiased branch
-} jitHint;
+};
/*
* Element of a Jit trace description. If the isCode bit is set, it describes
* a contiguous sequence of Dalvik byte codes.
*/
-typedef struct {
+struct JitCodeDesc {
unsigned numInsts:8; // Number of Byte codes in run
unsigned runEnd:1; // Run ends with last byte code
- jitHint hint:7; // Hint to apply to final code of run
- u2 startOffset; // Starting offset for trace run
-} JitCodeDesc;
+ JitHint hint:7; // Hint to apply to final code of run
+ u2 startOffset; // Starting offset for trace run
+};
/*
* A complete list of trace runs passed to the compiler looks like the
@@ -232,14 +222,14 @@
* descriptor/loader of "this" and the currently resolved method pointer are
* three instances of meta information stored there.
*/
-typedef struct {
+struct JitTraceRun {
union {
JitCodeDesc frag;
void* meta;
} info;
u4 isCode:1;
u4 unused:31;
-} JitTraceRun;
+};
#endif
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.cpp
similarity index 96%
rename from vm/interp/Jit.c
rename to vm/interp/Jit.cpp
index faf5880..3434a2c 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.cpp
@@ -109,9 +109,8 @@
shadowSpace->shadowFP = shadowSpace->registerSpace +
shadowSpace->registerSpaceSize - postBytes/4;
- self->interpSave.fp = (u4*)shadowSpace->shadowFP;
+ self->interpSave.curFrame = (u4*)shadowSpace->shadowFP;
self->interpStackEnd = (u1*)shadowSpace->registerSpace;
- self->curFrame = self->interpSave.fp;
// Create a copy of the stack
memcpy(((char*)shadowSpace->shadowFP)-preBytes, ((char*)fp)-preBytes,
@@ -163,8 +162,7 @@
/* Restore state before returning */
self->interpSave.pc = shadowSpace->startPC;
- self->interpSave.fp = shadowSpace->fp;
- self->curFrame = self->interpSave.fp;
+ self->interpSave.curFrame = shadowSpace->fp;
self->interpSave.method = shadowSpace->method;
self->interpSave.methodClassDex = shadowSpace->methodClassDex;
self->retval = shadowSpace->retval;
@@ -187,16 +185,17 @@
static void selfVerificationDumpState(const u2* pc, Thread* self)
{
ShadowSpace* shadowSpace = self->shadowSpace;
- StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->interpSave.curFrame);
int frameBytes = (int) shadowSpace->registerSpace +
shadowSpace->registerSpaceSize*4 -
(int) shadowSpace->shadowFP;
int localRegs = 0;
int frameBytes2 = 0;
- if ((uintptr_t)self->curFrame < (uintptr_t)shadowSpace->fp) {
+ if ((uintptr_t)self->interpSave.curFrame < (uintptr_t)shadowSpace->fp) {
localRegs = (stackSave->method->registersSize -
stackSave->method->insSize)*4;
- frameBytes2 = (int) shadowSpace->fp - (int) self->curFrame - localRegs;
+ frameBytes2 = (int) shadowSpace->fp -
+ (int)self->interpSave.curFrame - localRegs;
}
LOGD("********** SHADOW STATE DUMP **********");
LOGD("CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
@@ -206,7 +205,7 @@
LOGD("Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
(int)shadowSpace->endPC);
LOGD("Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
- (int)self->curFrame);
+ (int)self->interpSave.curFrame);
LOGD("Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
(int)shadowSpace->endShadowFP);
LOGD("Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
@@ -219,7 +218,7 @@
static void selfVerificationDumpTrace(const u2* pc, Thread* self)
{
ShadowSpace* shadowSpace = self->shadowSpace;
- StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->interpSave.curFrame);
int i, addr, offset;
DecodedInstruction *decInsn;
@@ -326,13 +325,14 @@
selfVerificationSpinLoop(shadowSpace);
}
/* Check new frame if it exists (invokes only) */
- if ((uintptr_t)self->curFrame < (uintptr_t)shadowSpace->fp) {
- StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ if ((uintptr_t)self->interpSave.curFrame < (uintptr_t)shadowSpace->fp) {
+ StackSaveArea* stackSave =
+ SAVEAREA_FROM_FP(self->interpSave.curFrame);
int localRegs = (stackSave->method->registersSize -
stackSave->method->insSize)*4;
int frameBytes2 = (int) shadowSpace->fp -
- (int) self->curFrame - localRegs;
- if (memcmp(((char*)self->curFrame)+localRegs,
+ (int) self->interpSave.curFrame - localRegs;
+ if (memcmp(((char*)self->interpSave.curFrame)+localRegs,
((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
if (state == kSVSBackwardBranch) {
/*
@@ -347,14 +347,14 @@
selfVerificationDumpState(pc, self);
selfVerificationDumpTrace(pc, self);
LOGD("*** Interp Registers: addr: 0x%x l: %d bytes: %d",
- (int)self->curFrame, localRegs, frameBytes2);
- selfVerificationPrintRegisters((int*)self->curFrame,
+ (int)self->interpSave.curFrame, localRegs, frameBytes2);
+ selfVerificationPrintRegisters((int*)self->interpSave.curFrame,
(int*)shadowSpace->endShadowFP,
(frameBytes2+localRegs)/4);
LOGD("*** Shadow Registers: addr: 0x%x l: %d bytes: %d",
(int)shadowSpace->endShadowFP, localRegs, frameBytes2);
selfVerificationPrintRegisters((int*)shadowSpace->endShadowFP,
- (int*)self->curFrame,
+ (int*)self->interpSave.curFrame,
(frameBytes2+localRegs)/4);
selfVerificationSpinLoop(shadowSpace);
}
@@ -395,16 +395,15 @@
assert(self->jitResumeNPC != NULL);
assert(self->singleStepCount == 0);
self->singleStepCount = 1;
- dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
- true /* enable */);
+ dvmEnableSubMode(self, kSubModeCountedStep);
}
/*
* Switch off shadow replay mode. The next shadowed trace
* execution will turn it back on.
*/
- dvmUpdateInterpBreak(self, kInterpJitBreak, kSubModeJitSV,
- false /* disable */);
+ dvmDisableSubMode(self, kSubModeJitSV);
+
self->jitState = kJitDone;
return;
}
@@ -840,12 +839,14 @@
* If the last instruction is an invoke, we will try to sneak in
* the move-result* (if existent) into a separate trace run.
*/
- int needReservedRun = (flags & kInstrInvoke) ? 1 : 0;
+ {
+ int needReservedRun = (flags & kInstrInvoke) ? 1 : 0;
- /* Will probably never hit this with the current trace buildier */
- if (self->currTraceRun ==
- (MAX_JIT_RUN_LEN - 1 - needReservedRun)) {
+ /* Will probably never hit this with the current trace builder */
+ if (self->currTraceRun ==
+ (MAX_JIT_RUN_LEN - 1 - needReservedRun)) {
self->jitState = kJitTSelectEnd;
+ }
}
if (!dexIsGoto(flags) &&
@@ -974,14 +975,12 @@
* If we're done with trace selection, switch off the control flags.
*/
if (allDone) {
- dvmUpdateInterpBreak(self, kInterpJitBreak,
- kSubModeJitTraceBuild, false);
+ dvmDisableSubMode(self, kSubModeJitTraceBuild);
if (stayOneMoreInst) {
// Keep going in single-step mode for at least one more inst
assert(self->jitResumeNPC == NULL);
self->singleStepCount = MIN(1, self->singleStepCount);
- dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
- true /* enable */);
+ dvmEnableSubMode(self, kSubModeCountedStep);
}
}
return;
@@ -1274,8 +1273,7 @@
self->trace[0].isCode = true;
self->lastPC = 0;
/* Turn on trace selection mode */
- dvmUpdateInterpBreak(self, kInterpJitBreak,
- kSubModeJitTraceBuild, true);
+ dvmEnableSubMode(self, kSubModeJitTraceBuild);
#if defined(SHOW_TRACE)
LOGD("Starting trace for %s at 0x%x",
self->interpSave.method->name, (int)self->interpSave.pc);
@@ -1372,7 +1370,7 @@
/*
* Reset the JitTable to the initial clean state.
*/
-void dvmJitResetTable(void)
+void dvmJitResetTable()
{
JitEntry *jitEntry = gDvmJit.pJitEntryTable;
unsigned int size = gDvmJit.jitTableSize;
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index 7dbe9ac..89256ca 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -29,17 +29,17 @@
#define REG_SPACE 256 /* default size of shadow space */
#define HEAP_SPACE JIT_MAX_TRACE_LEN /* default size of heap space */
-typedef struct ShadowHeap {
+struct ShadowHeap {
int addr;
int data;
-} ShadowHeap;
+};
-typedef struct InstructionTrace {
+struct InstructionTrace {
int addr;
DecodedInstruction decInsn;
-} InstructionTrace;
+};
-typedef struct ShadowSpace {
+struct ShadowSpace {
const u2* startPC; /* starting pc of jitted region */
u4* fp; /* starting fp of jitted region */
const Method *method;
@@ -57,11 +57,12 @@
const void* endShadowFP; /* ending fp in shadow space */
InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */
int traceLength; /* counter for current trace length */
-} ShadowSpace;
+};
/*
* Self verification functions.
*/
+extern "C" {
void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
void dvmSelfVerificationShadowSpaceFree(Thread* self);
void* dvmSelfVerificationSaveState(const u2* pc, u4* fp,
@@ -71,6 +72,7 @@
SelfVerificationState exitPoint,
Thread *self);
void dvmCheckSelfVerification(const u2* pc, Thread* self);
+}
#endif
/*
@@ -111,10 +113,10 @@
typedef s4 JitTraceCounter_t;
-typedef struct JitTraceProfCounters {
+struct JitTraceProfCounters {
unsigned int next;
JitTraceCounter_t *buckets[JIT_PROF_BLOCK_BUCKETS];
-} JitTraceProfCounters;
+};
/*
* Entries in the JIT's address lookup hash table.
@@ -122,7 +124,7 @@
* single 32-bit word to allow use of atomic update.
*/
-typedef struct JitEntryInfo {
+struct JitEntryInfo {
unsigned int isMethodEntry:1;
unsigned int inlineCandidate:1;
unsigned int profileEnabled:1;
@@ -130,28 +132,36 @@
unsigned int profileOffset:5;
unsigned int unused:5;
u2 chain; /* Index of next in chain */
-} JitEntryInfo;
+};
-typedef union JitEntryInfoUnion {
+union JitEntryInfoUnion {
JitEntryInfo info;
volatile int infoWord;
-} JitEntryInfoUnion;
+};
-typedef struct JitEntry {
+struct JitEntry {
JitEntryInfoUnion u;
const u2* dPC; /* Dalvik code address */
void* codeAddress; /* Code address of native translation */
-} JitEntry;
+};
+extern "C" {
void dvmCheckJit(const u2* pc, Thread* self);
void* dvmJitGetTraceAddr(const u2* dPC);
void* dvmJitGetMethodAddr(const u2* dPC);
+void* dvmJitGetTraceAddrThread(const u2* dPC, Thread* self);
+void* dvmJitGetMethodAddrThread(const u2* dPC, Thread* self);
void dvmJitCheckTraceRequest(Thread* self);
void dvmJitStopTranslationRequests(void);
+#if defined(WITH_JIT_TUNING)
+void dvmBumpNoChain(int from);
+void dvmBumpNormal(void);
+void dvmBumpPunt(int from);
+#endif
void dvmJitStats(void);
bool dvmJitResizeJitTable(unsigned int size);
void dvmJitResetTable(void);
-struct JitEntry *dvmJitFindEntry(const u2* pc, bool isMethodEntry);
+JitEntry *dvmJitFindEntry(const u2* pc, bool isMethodEntry);
s8 dvmJitd2l(double d);
s8 dvmJitf2l(float f);
void dvmJitSetCodeAddr(const u2* dPC, void *nPC, JitInstructionSetType set,
@@ -165,5 +175,6 @@
void dvmJitUpdateThreadStateSingle(Thread* threead);
void dvmJitUpdateThreadStateAll(void);
void dvmJitResumeTranslation(Thread* self, const u2* pc, const u4* fp);
+}
#endif /*_DALVIK_INTERP_JIT*/
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.cpp
similarity index 88%
rename from vm/interp/Stack.c
rename to vm/interp/Stack.cpp
index db06866..c65a78e 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.cpp
@@ -35,7 +35,7 @@
{
assert(thread->interpStackStart != NULL);
- assert(thread->curFrame == NULL);
+ assert(thread->interpSave.curFrame == NULL);
return true;
}
@@ -70,8 +70,8 @@
+ sizeof(StackSaveArea) * 2 // break frame + regular frame
+ method->outsSize * 4; // args to other methods
- if (self->curFrame != NULL)
- stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
+ if (self->interpSave.curFrame != NULL)
+ stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
else
stackPtr = self->interpStackStart;
@@ -79,7 +79,7 @@
/* not enough space */
LOGW("Stack overflow on call to interp "
"(req=%d top=%p cur=%p size=%d %s.%s)\n",
- stackReq, self->interpStackStart, self->curFrame,
+ stackReq, self->interpStackStart, self->interpSave.curFrame,
self->interpStackSize, method->clazz->descriptor, method->name);
dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
@@ -100,11 +100,12 @@
memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
#endif
#ifdef EASY_GDB
- breakSaveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
+ breakSaveBlock->prevSave =
+ (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
saveBlock->prevSave = breakSaveBlock;
#endif
- breakSaveBlock->prevFrame = self->curFrame;
+ breakSaveBlock->prevFrame = self->interpSave.curFrame;
breakSaveBlock->savedPc = NULL; // not required
breakSaveBlock->xtra.localRefCookie = 0; // not required
breakSaveBlock->method = NULL;
@@ -114,10 +115,10 @@
saveBlock->method = method;
LOGVV("PUSH frame: old=%p new=%p (size=%d)\n",
- self->curFrame, FP_FROM_SAVEAREA(saveBlock),
- (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
+ self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
+ (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
- self->curFrame = FP_FROM_SAVEAREA(saveBlock);
+ self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
return true;
}
@@ -143,8 +144,8 @@
stackReq = method->registersSize * 4 // params only
+ sizeof(StackSaveArea) * 2; // break frame + regular frame
- if (self->curFrame != NULL)
- stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
+ if (self->interpSave.curFrame != NULL)
+ stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
else
stackPtr = self->interpStackStart;
@@ -152,7 +153,7 @@
/* not enough space */
LOGW("Stack overflow on call to native "
"(req=%d top=%p cur=%p size=%d '%s')\n",
- stackReq, self->interpStackStart, self->curFrame,
+ stackReq, self->interpStackStart, self->interpSave.curFrame,
self->interpStackSize, method->name);
dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
@@ -174,16 +175,16 @@
memset(stackPtr, 0xaf, stackReq);
#endif
#ifdef EASY_GDB
- if (self->curFrame == NULL)
+ if (self->interpSave.curFrame == NULL)
breakSaveBlock->prevSave = NULL;
else {
- void* fp = FP_FROM_SAVEAREA(self->curFrame);
+ void* fp = FP_FROM_SAVEAREA(self->interpSave.curFrame);
breakSaveBlock->prevSave = (StackSaveArea*)fp;
}
saveBlock->prevSave = breakSaveBlock;
#endif
- breakSaveBlock->prevFrame = self->curFrame;
+ breakSaveBlock->prevFrame = self->interpSave.curFrame;
breakSaveBlock->savedPc = NULL; // not required
breakSaveBlock->xtra.localRefCookie = 0; // not required
breakSaveBlock->method = NULL;
@@ -193,10 +194,10 @@
saveBlock->method = method;
LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
- self->curFrame, FP_FROM_SAVEAREA(saveBlock),
- (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
+ self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
+ (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
- self->curFrame = FP_FROM_SAVEAREA(saveBlock);
+ self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
return true;
}
@@ -217,14 +218,14 @@
stackReq = sizeof(StackSaveArea); // regular frame
- assert(self->curFrame != NULL);
- stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
+ assert(self->interpSave.curFrame != NULL);
+ stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
if (stackPtr - stackReq < self->interpStackEnd) {
/* not enough space; let JNI throw the exception */
LOGW("Stack overflow on PushLocal "
"(req=%d top=%p cur=%p size=%d '%s')\n",
- stackReq, self->interpStackStart, self->curFrame,
+ stackReq, self->interpStackStart, self->interpSave.curFrame,
self->interpStackSize, method->name);
dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
@@ -243,19 +244,20 @@
memset(stackPtr, 0xaf, stackReq);
#endif
#ifdef EASY_GDB
- saveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
+ saveBlock->prevSave =
+ (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
#endif
- saveBlock->prevFrame = self->curFrame;
+ saveBlock->prevFrame = self->interpSave.curFrame;
saveBlock->savedPc = NULL; // not required
saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
saveBlock->method = method;
LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
- self->curFrame, FP_FROM_SAVEAREA(saveBlock),
- (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
+ self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
+ (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
- self->curFrame = FP_FROM_SAVEAREA(saveBlock);
+ self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
return true;
}
@@ -268,9 +270,9 @@
*/
bool dvmPopLocalFrame(Thread* self)
{
- StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
- assert(!dvmIsBreakFrame((u4*)self->curFrame));
+ assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
/*
* The previous frame doesn't have the same method pointer -- we've
@@ -286,7 +288,7 @@
saveBlock->method->name,
SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
dvmPopJniLocals(self, saveBlock);
- self->curFrame = saveBlock->prevFrame;
+ self->interpSave.curFrame = saveBlock->prevFrame;
return true;
}
@@ -304,11 +306,11 @@
{
StackSaveArea* saveBlock;
- if (self->curFrame == NULL)
+ if (self->interpSave.curFrame == NULL)
return false;
- saveBlock = SAVEAREA_FROM_FP(self->curFrame);
- assert(!dvmIsBreakFrame((u4*)self->curFrame));
+ saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
+ assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
/*
* Remove everything up to the break frame. If this was a call into
@@ -335,16 +337,16 @@
}
LOGVV("POP frame: cur=%p new=%p\n",
- self->curFrame, saveBlock->prevFrame);
+ self->interpSave.curFrame, saveBlock->prevFrame);
- self->curFrame = saveBlock->prevFrame;
+ self->interpSave.curFrame = saveBlock->prevFrame;
return true;
}
/*
* Common code for dvmCallMethodV/A and dvmInvokeMethod.
*
- * Pushes a call frame on, advancing self->curFrame.
+ * Pushes a call frame on, advancing self->interpSave.curFrame.
*/
static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
bool checkAccess)
@@ -376,7 +378,7 @@
if (checkAccess) {
/* needed for java.lang.reflect.Method.invoke */
- if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame),
+ if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame),
method))
{
/* note this throws IAException, not IAError */
@@ -389,7 +391,7 @@
* Push a call frame on. If there isn't enough room for ins, locals,
* outs, and the saved state, it will throw an exception.
*
- * This updates self->curFrame.
+ * This updates self->interpSave.curFrame.
*/
if (dvmIsNativeMethod(method)) {
/* native code calling native code the hard way */
@@ -446,9 +448,10 @@
return;
/* "ins" for new frame start at frame pointer plus locals */
- ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
+ ins = ((u4*)self->interpSave.curFrame) +
+ (method->registersSize - method->insSize);
- //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins);
+ //LOGD(" FP is %p, INs live at >= %p\n", self->interpSave.curFrame, ins);
/* put "this" pointer into in0 if appropriate */
if (!dvmIsStaticMethod(method)) {
@@ -477,8 +480,9 @@
break;
}
case 'L': { /* 'shorty' descr uses L for all refs, incl array */
- void* argObj = va_arg(args, void*);
+ void* arg = va_arg(args, void*);
assert(obj == NULL || dvmIsValidObject(obj));
+ jobject argObj = reinterpret_cast<jobject>(arg);
if (fromJni)
*ins++ = (u4) dvmDecodeIndirectRef(env, argObj);
else
@@ -512,7 +516,8 @@
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
+ (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
+ method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, pResult);
@@ -550,7 +555,8 @@
return;
/* "ins" for new frame start at frame pointer plus locals */
- ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
+ ins = ((u4*)self->interpSave.curFrame) +
+ (method->registersSize - method->insSize);
/* put "this" pointer into in0 if appropriate */
if (!dvmIsStaticMethod(method)) {
@@ -616,7 +622,8 @@
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
+ (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
+ method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, pResult);
@@ -631,7 +638,7 @@
{
char* expectedClassName = dvmHumanReadableDescriptor(expected->descriptor);
char* actualClassName = (arg != NULL)
- ? dvmHumanReadableDescriptor(arg->obj.clazz->descriptor)
+ ? dvmHumanReadableDescriptor(arg->clazz->descriptor)
: strdup("null");
dvmThrowExceptionFmt(gDvm.exIllegalArgumentException,
"argument %d should have type %s, got %s",
@@ -681,10 +688,11 @@
needPop = true;
/* "ins" for new frame start at frame pointer plus locals */
- ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
+ ins = ((s4*)self->interpSave.curFrame) +
+ (method->registersSize - method->insSize);
verifyCount = 0;
- //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins);
+ //LOGD(" FP is %p, INs live at >= %p\n", self->interpSave.curFrame, ins);
/* put "this" pointer into in0 if appropriate */
if (!dvmIsStaticMethod(method)) {
@@ -697,16 +705,10 @@
* Copy the args onto the stack. Primitive types are converted when
* necessary, and object types are verified.
*/
- DataObject** args;
- ClassObject** types;
- int i;
-
- args = (DataObject**) argList->contents;
- types = (ClassObject**) params->contents;
- for (i = 0; i < argListLength; i++) {
- int width;
-
- width = dvmConvertArgument(*args++, *types++, ins);
+ DataObject** args = (DataObject**)(void*)argList->contents;
+ ClassObject** types = (ClassObject**)(void*)params->contents;
+ for (int i = 0; i < argListLength; i++) {
+ int width = dvmConvertArgument(*args++, *types++, ins);
if (width < 0) {
dvmPopFrame(self); // throw wants to pull PC out of stack
needPop = false;
@@ -733,7 +735,8 @@
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)((u4*)self->curFrame, &retval, method, self);
+ (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval,
+ method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, &retval);
@@ -777,10 +780,10 @@
return retObj;
}
-typedef struct LineNumFromPcContext {
+struct LineNumFromPcContext {
u4 address;
u4 lineNum;
-} LineNumFromPcContext;
+};
static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
{
@@ -930,7 +933,8 @@
void* callerCaller;
/* at the top? */
- if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
+ if (dvmIsBreakFrame((u4*)caller) &&
+ SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
return NULL;
/* go one more */
@@ -953,7 +957,8 @@
int i;
/* at the top? */
- if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
+ if (dvmIsBreakFrame((u4*)caller) &&
+ SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
return NULL;
/* Walk up two frames if possible. */
@@ -967,37 +972,24 @@
}
/*
- * Create a flat array of methods that comprise the current interpreter
- * stack trace. Pass in the current frame ptr.
- *
- * Allocates a new array and fills it with method pointers. Break frames
- * are skipped, but reflection invocations are not. The caller must free
- * "*pArray".
+ * Fill a flat array of methods that comprise the current interpreter
+ * stack trace. Pass in the current frame ptr. Break frames are
+ * skipped, but reflection invocations are not.
*
* The current frame will be in element 0.
- *
- * Returns "true" on success, "false" on failure (e.g. malloc failed).
*/
-bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
- int* pLength)
+void dvmFillStackTraceArray(const void* fp, const Method** array, size_t length)
{
- const Method** array;
- int idx, depth;
-
- depth = dvmComputeExactFrameDepth(fp);
- array = (const Method**) malloc(depth * sizeof(Method*));
- if (array == NULL)
- return false;
-
- for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
- if (!dvmIsBreakFrame((u4*)fp))
- array[idx++] = SAVEAREA_FROM_FP(fp)->method;
+ assert(fp != NULL);
+ assert(array != NULL);
+ size_t i = 0;
+ while (fp != NULL) {
+ if (!dvmIsBreakFrame((u4*)fp)) {
+ assert(i < length);
+ array[i++] = SAVEAREA_FROM_FP(fp)->method;
+ }
+ fp = SAVEAREA_FROM_FP(fp)->prevFrame;
}
- assert(idx == depth);
-
- *pArray = array;
- *pLength = depth;
- return true;
}
/*
@@ -1030,7 +1022,7 @@
LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n",
self->threadId,
method->clazz->descriptor, method->name, method->shorty);
- StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n",
method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
(method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
@@ -1072,9 +1064,9 @@
newStackEnd = (self->interpStackStart - self->interpStackSize)
+ STACK_OVERFLOW_RESERVE;
- if ((u1*)self->curFrame <= newStackEnd) {
+ if ((u1*)self->interpSave.curFrame <= newStackEnd) {
LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n",
- self->interpStackEnd, self->curFrame);
+ self->interpStackEnd, self->interpSave.curFrame);
dvmDumpThread(self, false);
dvmAbort();
}
@@ -1083,7 +1075,7 @@
self->stackOverflowed = false;
LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd,
- self->curFrame);
+ self->interpSave.curFrame);
}
@@ -1102,7 +1094,7 @@
static bool extractMonitorEnterObject(Thread* thread, Object** pLockObj,
Thread** pOwner)
{
- void* framePtr = thread->curFrame;
+ void* framePtr = thread->interpSave.curFrame;
if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
return false;
@@ -1219,7 +1211,8 @@
else
relPc = -1;
- char* className = dvmHumanReadableDescriptor(method->clazz->descriptor);
+ char* className =
+ dvmHumanReadableDescriptor(method->clazz->descriptor);
if (dvmIsNativeMethod(method))
dvmPrintDebugMessage(target,
" at %s.%s(Native Method)\n", className, method->name);
@@ -1246,7 +1239,8 @@
Object* obj = dvmGetMonitorObject(mon);
if (obj != NULL) {
Thread* joinThread = NULL;
- className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
+ className =
+ dvmHumanReadableDescriptor(obj->clazz->descriptor);
if (strcmp(className, "java.lang.VMThread") == 0) {
joinThread = dvmGetThreadFromThreadObject(obj);
}
@@ -1264,7 +1258,8 @@
Object* obj;
Thread* owner;
if (extractMonitorEnterObject(thread, &obj, &owner)) {
- className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
+ className =
+ dvmHumanReadableDescriptor(obj->clazz->descriptor);
if (owner != NULL) {
char* threadName = dvmGetThreadName(owner);
dvmPrintDebugMessage(target,
@@ -1320,7 +1315,7 @@
*/
void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
{
- dumpFrames(target, thread->curFrame, thread);
+ dumpFrames(target, thread->interpSave.curFrame, thread);
}
/*
@@ -1343,7 +1338,7 @@
void* fp;
int depthLimit = 200;
- if (thread == NULL || thread->curFrame == NULL) {
+ if (thread == NULL || thread->interpSave.curFrame == NULL) {
dvmPrintDebugMessage(target,
"DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
thread, (thread != NULL) ? thread->threadId : 0);
@@ -1357,13 +1352,14 @@
origSize = thread->interpStackSize;
origStack = (const u1*) thread->interpStackStart - origSize;
stackCopy = (u1*) malloc(origSize);
- fpOffset = (u1*) thread->curFrame - origStack;
+ fpOffset = (u1*) thread->interpSave.curFrame - origStack;
memcpy(stackCopy, origStack, origSize);
/*
* Run through the stack and rewrite the "prev" pointers.
*/
- //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame);
+ //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack,
+ // thread->interpSave.curFrame);
fp = stackCopy + fpOffset;
while (true) {
int prevOffset;
@@ -1386,7 +1382,7 @@
break;
}
- saveArea->prevFrame = stackCopy + prevOffset;
+ saveArea->prevFrame = (u4*)(stackCopy + prevOffset);
fp = saveArea->prevFrame;
}
diff --git a/vm/interp/Stack.h b/vm/interp/Stack.h
index 10c04a0..4e806b7 100644
--- a/vm/interp/Stack.h
+++ b/vm/interp/Stack.h
@@ -23,7 +23,6 @@
#include "jni.h"
#include <stdarg.h>
-
/*
Stack layout
@@ -108,7 +107,6 @@
struct StackSaveArea;
-typedef struct StackSaveArea StackSaveArea;
//#define PAD_SAVE_AREA /* help debug stack trampling */
@@ -130,7 +128,7 @@
#endif
/* saved frame pointer for previous frame, or NULL if this is at bottom */
- void* prevFrame;
+ u4* prevFrame;
/* saved program counter (from method in caller's frame) */
const u2* savedPc;
@@ -156,7 +154,7 @@
/* move between the stack save area and the frame pointer */
#define SAVEAREA_FROM_FP(_fp) ((StackSaveArea*)(_fp) -1)
-#define FP_FROM_SAVEAREA(_save) ((void*) ((StackSaveArea*)(_save) +1))
+#define FP_FROM_SAVEAREA(_save) ((u4*) ((StackSaveArea*)(_save) +1))
/* when calling a function, get a pointer to outs[0] */
#define OUTS_FROM_FP(_fp, _argCount) \
@@ -263,17 +261,16 @@
ClassObject* dvmGetCaller3Class(const void* curFrame);
/*
- * Allocate and fill an array of method pointers representing the current
- * stack trace (element 0 is current frame).
+ * Fill an array of method pointers representing the current stack
+ * trace (element 0 is current frame).
*/
-bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
- int* pLength);
+void dvmFillStackTraceArray(const void* fp, const Method** array, size_t length);
/*
* Common handling for stack overflow.
*/
-void dvmHandleStackOverflow(Thread* self, const Method* method);
-void dvmCleanupStackOverflow(Thread* self, const Object* exception);
+extern "C" void dvmHandleStackOverflow(Thread* self, const Method* method);
+extern "C" void dvmCleanupStackOverflow(Thread* self, const Object* exception);
/* debugging; dvmDumpThread() is probably a better starting point */
void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread);
diff --git a/vm/jdwp/ExpandBuf.c b/vm/jdwp/ExpandBuf.cpp
similarity index 98%
rename from vm/jdwp/ExpandBuf.c
rename to vm/jdwp/ExpandBuf.cpp
index cb3386b..8162128 100644
--- a/vm/jdwp/ExpandBuf.c
+++ b/vm/jdwp/ExpandBuf.cpp
@@ -38,7 +38,7 @@
/*
* Allocate a JdwpBuf and some initial storage.
*/
-ExpandBuf* expandBufAlloc(void)
+ExpandBuf* expandBufAlloc()
{
ExpandBuf* newBuf;
diff --git a/vm/jdwp/ExpandBuf.h b/vm/jdwp/ExpandBuf.h
index 8bdc8a7..6bdab0f 100644
--- a/vm/jdwp/ExpandBuf.h
+++ b/vm/jdwp/ExpandBuf.h
@@ -22,7 +22,6 @@
#include "Common.h" // need u1/u2/u4/u8 types
struct ExpandBuf; /* private */
-typedef struct ExpandBuf ExpandBuf;
/* create a new struct */
ExpandBuf* expandBufAlloc(void);
diff --git a/vm/jdwp/Jdwp.h b/vm/jdwp/Jdwp.h
index 7313579..9199a1e 100644
--- a/vm/jdwp/Jdwp.h
+++ b/vm/jdwp/Jdwp.h
@@ -31,7 +31,6 @@
#include <pthread.h>
struct JdwpState; /* opaque */
-typedef struct JdwpState JdwpState;
/*
* Fundamental types.
@@ -78,34 +77,33 @@
/*
* Holds a JDWP "location".
*/
-typedef struct JdwpLocation {
+struct JdwpLocation {
u1 typeTag; /* class or interface? */
RefTypeId classId; /* method->clazz */
MethodId methodId; /* method in which "idx" resides */
u8 idx; /* relative index into code block */
-} JdwpLocation;
-//#define kJDWPLocationSize (25)
+};
/*
* How we talk to the debugger.
*/
-typedef enum JdwpTransportType {
+enum JdwpTransportType {
kJdwpTransportUnknown = 0,
kJdwpTransportSocket, /* transport=dt_socket */
kJdwpTransportAndroidAdb, /* transport=dt_android_adb */
-} JdwpTransportType;
+};
/*
* Holds collection of JDWP initialization parameters.
*/
-typedef struct JdwpStartupParams {
+struct JdwpStartupParams {
JdwpTransportType transport;
bool server;
bool suspend;
char host[64];
short port;
/* more will be here someday */
-} JdwpStartupParams;
+};
/*
* Perform one-time initialization.
diff --git a/vm/jdwp/JdwpAdb.c b/vm/jdwp/JdwpAdb.cpp
similarity index 98%
rename from vm/jdwp/JdwpAdb.c
rename to vm/jdwp/JdwpAdb.cpp
index e73814d..9a57baa 100644
--- a/vm/jdwp/JdwpAdb.c
+++ b/vm/jdwp/JdwpAdb.cpp
@@ -89,8 +89,7 @@
}
-static JdwpNetState*
-adbStateAlloc(void)
+static JdwpNetState* adbStateAlloc()
{
JdwpNetState* netState = (JdwpNetState*) calloc(sizeof(*netState),1);
@@ -163,7 +162,7 @@
cmsg->cmsg_len = msg.msg_controllen;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
- ((int*)CMSG_DATA(cmsg))[0] = -1;
+ ((int*)(void*)CMSG_DATA(cmsg))[0] = -1;
do {
ret = recvmsg(netState->controlSock, &msg, 0);
@@ -181,7 +180,7 @@
return -1;
}
- return ((int*)CMSG_DATA(cmsg))[0];
+ return ((int*)(void*)CMSG_DATA(cmsg))[0];
}
/*
@@ -343,7 +342,7 @@
if (netState->wakeFds[1] >= 0) {
LOGV("+++ writing to wakePipe\n");
- (void) write(netState->wakeFds[1], "", 1);
+ write(netState->wakeFds[1], "", 1);
}
}
@@ -755,7 +754,7 @@
/*
* Return our set.
*/
-const JdwpTransport* dvmJdwpAndroidAdbTransport(void)
+const JdwpTransport* dvmJdwpAndroidAdbTransport()
{
return &socketTransport;
}
diff --git a/vm/jdwp/JdwpConstants.c b/vm/jdwp/JdwpConstants.cpp
similarity index 94%
rename from vm/jdwp/JdwpConstants.c
rename to vm/jdwp/JdwpConstants.cpp
index 4b1418b..ab9d872 100644
--- a/vm/jdwp/JdwpConstants.c
+++ b/vm/jdwp/JdwpConstants.cpp
@@ -23,7 +23,7 @@
/*
* Return a string for the error code.
*/
-const char* dvmJdwpErrorStr(enum JdwpError error)
+const char* dvmJdwpErrorStr(JdwpError error)
{
switch (error) {
case ERR_NONE:
@@ -146,7 +146,7 @@
/*
* Return a string for the EventKind.
*/
-const char* dvmJdwpEventKindStr(enum JdwpEventKind kind)
+const char* dvmJdwpEventKindStr(JdwpEventKind kind)
{
switch (kind) {
case EK_SINGLE_STEP: return "SINGLE_STEP";
@@ -176,7 +176,7 @@
/*
* Return a string for the ModKind.
*/
-const char* dvmJdwpModKindStr(enum JdwpModKind kind)
+const char* dvmJdwpModKindStr(JdwpModKind kind)
{
switch (kind) {
case MK_COUNT: return "COUNT";
@@ -197,7 +197,7 @@
/*
* Return a string for the StepDepth.
*/
-const char* dvmJdwpStepDepthStr(enum JdwpStepDepth depth)
+const char* dvmJdwpStepDepthStr(JdwpStepDepth depth)
{
switch (depth) {
case SD_INTO: return "INTO";
@@ -210,7 +210,7 @@
/*
* Return a string for the StepSize.
*/
-const char* dvmJdwpStepSizeStr(enum JdwpStepSize size)
+const char* dvmJdwpStepSizeStr(JdwpStepSize size)
{
switch (size) {
case SS_MIN: return "MIN";
@@ -222,7 +222,7 @@
/*
* Return a string for the SuspendPolicy.
*/
-const char* dvmJdwpSuspendPolicyStr(enum JdwpSuspendPolicy policy)
+const char* dvmJdwpSuspendPolicyStr(JdwpSuspendPolicy policy)
{
switch (policy) {
case SP_NONE: return "NONE";
@@ -235,7 +235,7 @@
/*
* Return a string for the SuspendStatus.
*/
-const char* dvmJdwpSuspendStatusStr(enum JdwpSuspendStatus status)
+const char* dvmJdwpSuspendStatusStr(JdwpSuspendStatus status)
{
switch (status) {
case 0: return "Not SUSPENDED";
@@ -247,7 +247,7 @@
/*
* Return a string for the ThreadStatus.
*/
-const char* dvmJdwpThreadStatusStr(enum JdwpThreadStatus status)
+const char* dvmJdwpThreadStatusStr(JdwpThreadStatus status)
{
switch (status) {
case TS_ZOMBIE: return "ZOMBIE";
diff --git a/vm/jdwp/JdwpConstants.h b/vm/jdwp/JdwpConstants.h
index 746bc59..f3049e5 100644
--- a/vm/jdwp/JdwpConstants.h
+++ b/vm/jdwp/JdwpConstants.h
@@ -80,8 +80,7 @@
ERR_NATIVE_METHOD = 511,
ERR_INVALID_COUNT = 512,
};
-typedef enum JdwpError JdwpError;
-const char* dvmJdwpErrorStr(enum JdwpError error);
+const char* dvmJdwpErrorStr(JdwpError error);
/*
@@ -119,7 +118,7 @@
EK_VM_START = EK_VM_INIT,
EK_THREAD_DEATH = EK_THREAD_END,
};
-const char* dvmJdwpEventKindStr(enum JdwpEventKind kind);
+const char* dvmJdwpEventKindStr(JdwpEventKind kind);
/*
* Values for "modKind" in EventRequest.Set.
@@ -137,7 +136,7 @@
MK_STEP = 10,
MK_INSTANCE_ONLY = 11,
};
-const char* dvmJdwpModKindStr(enum JdwpModKind kind);
+const char* dvmJdwpModKindStr(JdwpModKind kind);
/*
* InvokeOptions constants (bit flags).
@@ -155,7 +154,7 @@
SD_OVER = 1, /* step over method calls */
SD_OUT = 2, /* step out of current method */
};
-const char* dvmJdwpStepDepthStr(enum JdwpStepDepth depth);
+const char* dvmJdwpStepDepthStr(JdwpStepDepth depth);
/*
* StepSize constants.
@@ -164,7 +163,7 @@
SS_MIN = 0, /* step by minimum (e.g. 1 bytecode inst) */
SS_LINE = 1, /* if possible, step to next line */
};
-const char* dvmJdwpStepSizeStr(enum JdwpStepSize size);
+const char* dvmJdwpStepSizeStr(JdwpStepSize size);
/*
* SuspendPolicy constants.
@@ -174,7 +173,7 @@
SP_EVENT_THREAD = 1, /* suspend event thread */
SP_ALL = 2, /* suspend all threads */
};
-const char* dvmJdwpSuspendPolicyStr(enum JdwpSuspendPolicy policy);
+const char* dvmJdwpSuspendPolicyStr(JdwpSuspendPolicy policy);
/*
* SuspendStatus constants.
@@ -182,7 +181,7 @@
enum JdwpSuspendStatus {
SUSPEND_STATUS_SUSPENDED = 1,
};
-const char* dvmJdwpSuspendStatusStr(enum JdwpSuspendStatus status);
+const char* dvmJdwpSuspendStatusStr(JdwpSuspendStatus status);
/*
* ThreadStatus constants.
@@ -194,7 +193,7 @@
TS_MONITOR = 3, // WAITING (monitor wait)
TS_WAIT = 4, // (in Object.wait())
};
-const char* dvmJdwpThreadStatusStr(enum JdwpThreadStatus status);
+const char* dvmJdwpThreadStatusStr(JdwpThreadStatus status);
/*
* TypeTag constants.
diff --git a/vm/jdwp/JdwpEvent.c b/vm/jdwp/JdwpEvent.cpp
similarity index 93%
rename from vm/jdwp/JdwpEvent.c
rename to vm/jdwp/JdwpEvent.cpp
index fbcae52..15f0b2a 100644
--- a/vm/jdwp/JdwpEvent.c
+++ b/vm/jdwp/JdwpEvent.cpp
@@ -100,7 +100,7 @@
* values for mods valid for the event being evaluated will be filled in.
* The rest will be zeroed.
*/
-typedef struct ModBasket {
+struct ModBasket {
const JdwpLocation* pLoc; /* LocationOnly */
const char* className; /* ClassMatch/ClassExclude */
ObjectId threadId; /* ThreadOnly */
@@ -110,7 +110,7 @@
FieldId field; /* FieldOnly */
ObjectId thisPtr; /* InstanceOnly */
/* nothing for StepOnly -- handled differently */
-} ModBasket;
+};
/*
* Get the next "request" serial number. We use this when sending
@@ -118,10 +118,8 @@
*/
u4 dvmJdwpNextRequestSerial(JdwpState* state)
{
- u4 result;
-
dvmDbgLockMutex(&state->serialLock);
- result = state->requestSerial++;
+ u4 result = state->requestSerial++;
dvmDbgUnlockMutex(&state->serialLock);
return result;
@@ -133,10 +131,8 @@
*/
u4 dvmJdwpNextEventSerial(JdwpState* state)
{
- u4 result;
-
dvmDbgLockMutex(&state->serialLock);
- result = state->eventSerial++;
+ u4 result = state->eventSerial++;
dvmDbgUnlockMutex(&state->serialLock);
return result;
@@ -172,10 +168,10 @@
dvmJdwpSuspendPolicyStr(pEvent->suspendPolicy),
pEvent->modCount);
- int i;
- for (i = 0; i < pEvent->modCount; i++) {
+ for (int i = 0; i < pEvent->modCount; i++) {
const JdwpEventMod* pMod = &pEvent->mods[i];
- LOGI(" %s\n", dvmJdwpModKindStr(pMod->modKind));
+ JdwpModKind kind = static_cast<JdwpModKind>(pMod->modKind);
+ LOGI(" %s\n", dvmJdwpModKindStr(kind));
/* TODO - show details */
}
}
@@ -189,9 +185,6 @@
*/
JdwpError dvmJdwpRegisterEvent(JdwpState* state, JdwpEvent* pEvent)
{
- JdwpError err = ERR_NONE;
- int i;
-
lockEventMutex(state);
assert(state != NULL);
@@ -203,15 +196,16 @@
* If one or more "break"-type mods are used, register them with
* the interpreter.
*/
- for (i = 0; i < pEvent->modCount; i++) {
+ for (int i = 0; i < pEvent->modCount; i++) {
const JdwpEventMod* pMod = &pEvent->mods[i];
if (pMod->modKind == MK_LOCATION_ONLY) {
/* should only be for Breakpoint, Step, and Exception */
dvmDbgWatchLocation(&pMod->locationOnly.loc);
} else if (pMod->modKind == MK_STEP) {
/* should only be for EK_SINGLE_STEP; should only be one */
- dvmDbgConfigureStep(pMod->step.threadId, pMod->step.size,
- pMod->step.depth);
+ JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
+ JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
+ dvmDbgConfigureStep(pMod->step.threadId, size, depth);
} else if (pMod->modKind == MK_FIELD_ONLY) {
/* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
dumpEvent(pEvent); /* TODO - need for field watches */
@@ -230,7 +224,7 @@
unlockEventMutex(state);
- return err;
+ return ERR_NONE;
}
/*
@@ -243,8 +237,6 @@
*/
static void unregisterEvent(JdwpState* state, JdwpEvent* pEvent)
{
- int i;
-
if (pEvent->prev == NULL) {
/* head of the list */
assert(state->eventList == pEvent);
@@ -263,7 +255,7 @@
/*
* Unhook us from the interpreter, if necessary.
*/
- for (i = 0; i < pEvent->modCount; i++) {
+ for (int i = 0; i < pEvent->modCount; i++) {
JdwpEventMod* pMod = &pEvent->mods[i];
if (pMod->modKind == MK_LOCATION_ONLY) {
/* should only be for Breakpoint, Step, and Exception */
@@ -288,11 +280,9 @@
*/
void dvmJdwpUnregisterEventById(JdwpState* state, u4 requestId)
{
- JdwpEvent* pEvent;
-
lockEventMutex(state);
- pEvent = state->eventList;
+ JdwpEvent* pEvent = state->eventList;
while (pEvent != NULL) {
if (pEvent->requestId == requestId) {
unregisterEvent(state, pEvent);
@@ -314,14 +304,11 @@
*/
void dvmJdwpUnregisterAll(JdwpState* state)
{
- JdwpEvent* pEvent;
- JdwpEvent* pNextEvent;
-
lockEventMutex(state);
- pEvent = state->eventList;
+ JdwpEvent* pEvent = state->eventList;
while (pEvent != NULL) {
- pNextEvent = pEvent->next;
+ JdwpEvent* pNextEvent = pEvent->next;
unregisterEvent(state, pEvent);
dvmJdwpEventFree(pEvent);
@@ -357,8 +344,6 @@
*/
void dvmJdwpEventFree(JdwpEvent* pEvent)
{
- int i;
-
if (pEvent == NULL)
return;
@@ -370,7 +355,7 @@
/*
* Free any hairy bits in the mods.
*/
- for (i = 0; i < pEvent->modCount; i++) {
+ for (int i = 0; i < pEvent->modCount; i++) {
if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
free(pEvent->mods[i].classMatch.classPattern);
pEvent->mods[i].classMatch.classPattern = NULL;
@@ -406,9 +391,8 @@
while (matchCount--) {
JdwpEvent* pEvent = *ppEvent;
- int i;
- for (i = 0; i < pEvent->modCount; i++) {
+ for (int i = 0; i < pEvent->modCount; i++) {
if (pEvent->mods[i].modKind == MK_COUNT &&
pEvent->mods[i].count.count == 0)
{
@@ -478,9 +462,8 @@
static bool modsMatch(JdwpState* state, JdwpEvent* pEvent, ModBasket* basket)
{
JdwpEventMod* pMod = pEvent->mods;
- int i;
- for (i = pEvent->modCount; i > 0; i--, pMod++) {
+ for (int i = pEvent->modCount; i > 0; i--, pMod++) {
switch (pMod->modKind) {
case MK_COUNT:
assert(pMod->count.count > 0);
@@ -553,15 +536,13 @@
* DO NOT call this multiple times for the same eventKind, as Count mods are
* decremented during the scan.
*/
-static void findMatchingEvents(JdwpState* state, enum JdwpEventKind eventKind,
+static void findMatchingEvents(JdwpState* state, JdwpEventKind eventKind,
ModBasket* basket, JdwpEvent** matchList, int* pMatchCount)
{
- JdwpEvent* pEvent;
-
/* start after the existing entries */
matchList += *pMatchCount;
- pEvent = state->eventList;
+ JdwpEvent* pEvent = state->eventList;
while (pEvent != NULL) {
if (pEvent->eventKind == eventKind && modsMatch(state, pEvent, basket))
{
@@ -577,10 +558,10 @@
* Scan through the list of matches and determine the most severe
* suspension policy.
*/
-static enum JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList,
+static JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList,
int matchCount)
{
- enum JdwpSuspendPolicy policy = SP_NONE;
+ JdwpSuspendPolicy policy = SP_NONE;
while (matchCount--) {
if ((*matchList)->suspendPolicy > policy)
@@ -597,8 +578,7 @@
* SP_EVENT_THREAD - suspend ourselves
* SP_ALL - suspend everybody except JDWP support thread
*/
-static void suspendByPolicy(JdwpState* state,
- enum JdwpSuspendPolicy suspendPolicy)
+static void suspendByPolicy(JdwpState* state, JdwpSuspendPolicy suspendPolicy)
{
if (suspendPolicy == SP_NONE)
return;
@@ -725,11 +705,9 @@
* Prep an event. Allocates storage for the message and leaves space for
* the header.
*/
-static ExpandBuf* eventPrep(void)
+static ExpandBuf* eventPrep()
{
- ExpandBuf* pReq;
-
- pReq = expandBufAlloc();
+ ExpandBuf* pReq = expandBufAlloc();
expandBufAddSpace(pReq, kJDWPHeaderLen);
return pReq;
@@ -766,7 +744,7 @@
*/
bool dvmJdwpPostVMStart(JdwpState* state, bool suspend)
{
- enum JdwpSuspendPolicy suspendPolicy;
+ JdwpSuspendPolicy suspendPolicy;
ObjectId threadId = dvmDbgGetThreadSelfId();
if (suspend)
@@ -832,10 +810,8 @@
bool dvmJdwpPostLocationEvent(JdwpState* state, const JdwpLocation* pLoc,
ObjectId thisPtr, int eventFlags)
{
- enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
+ JdwpSuspendPolicy suspendPolicy = SP_NONE;
ModBasket basket;
- JdwpEvent** matchList;
- int matchCount;
char* nameAlloc = NULL;
memset(&basket, 0, sizeof(basket));
@@ -876,8 +852,8 @@
/* don't allow the list to be updated while we scan it */
lockEventMutex(state);
- matchList = allocMatchList(state);
- matchCount = 0;
+ JdwpEvent** matchList = allocMatchList(state);
+ int matchCount = 0;
if ((eventFlags & DBG_BREAKPOINT) != 0)
findMatchingEvents(state, EK_BREAKPOINT, &basket, matchList,
@@ -894,8 +870,6 @@
ExpandBuf* pReq = NULL;
if (matchCount != 0) {
- int i;
-
LOGV("EVENT: %s(%d total) %s.%s thread=%llx code=%llx)\n",
dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
basket.className,
@@ -910,7 +884,7 @@
expandBufAdd1(pReq, suspendPolicy);
expandBufAdd4BE(pReq, matchCount);
- for (i = 0; i < matchCount; i++) {
+ for (int i = 0; i < matchCount; i++) {
expandBufAdd1(pReq, matchList[i]->eventKind);
expandBufAdd4BE(pReq, matchList[i]->requestId);
expandBufAdd8BE(pReq, basket.threadId);
@@ -945,10 +919,7 @@
*/
bool dvmJdwpPostThreadChange(JdwpState* state, ObjectId threadId, bool start)
{
- enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
- ModBasket basket;
- JdwpEvent** matchList;
- int matchCount;
+ JdwpSuspendPolicy suspendPolicy = SP_NONE;
assert(threadId = dvmDbgGetThreadSelfId());
@@ -960,14 +931,15 @@
return false;
}
+ ModBasket basket;
memset(&basket, 0, sizeof(basket));
basket.threadId = threadId;
/* don't allow the list to be updated while we scan it */
lockEventMutex(state);
- matchList = allocMatchList(state);
- matchCount = 0;
+ JdwpEvent** matchList = allocMatchList(state);
+ int matchCount = 0;
if (start)
findMatchingEvents(state, EK_THREAD_START, &basket, matchList,
@@ -978,8 +950,6 @@
ExpandBuf* pReq = NULL;
if (matchCount != 0) {
- int i;
-
LOGV("EVENT: %s(%d total) thread=%llx)\n",
dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
basket.threadId);
@@ -992,7 +962,7 @@
expandBufAdd1(pReq, suspendPolicy);
expandBufAdd4BE(pReq, matchCount);
- for (i = 0; i < matchCount; i++) {
+ for (int i = 0; i < matchCount; i++) {
expandBufAdd1(pReq, matchList[i]->eventKind);
expandBufAdd4BE(pReq, matchList[i]->requestId);
expandBufAdd8BE(pReq, basket.threadId);
@@ -1025,11 +995,9 @@
*/
bool dvmJdwpPostVMDeath(JdwpState* state)
{
- ExpandBuf* pReq;
-
LOGV("EVENT: %s\n", dvmJdwpEventKindStr(EK_VM_DEATH));
- pReq = eventPrep();
+ ExpandBuf* pReq = eventPrep();
expandBufAdd1(pReq, SP_NONE);
expandBufAdd4BE(pReq, 1);
@@ -1055,10 +1023,8 @@
ObjectId exceptionId, RefTypeId exceptionClassId,
const JdwpLocation* pCatchLoc, ObjectId thisPtr)
{
- enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
+ JdwpSuspendPolicy suspendPolicy = SP_NONE;
ModBasket basket;
- JdwpEvent** matchList;
- int matchCount;
char* nameAlloc = NULL;
memset(&basket, 0, sizeof(basket));
@@ -1081,15 +1047,13 @@
/* don't allow the list to be updated while we scan it */
lockEventMutex(state);
- matchList = allocMatchList(state);
- matchCount = 0;
+ JdwpEvent** matchList = allocMatchList(state);
+ int matchCount = 0;
findMatchingEvents(state, EK_EXCEPTION, &basket, matchList, &matchCount);
ExpandBuf* pReq = NULL;
if (matchCount != 0) {
- int i;
-
LOGV("EVENT: %s(%d total) thread=%llx exceptId=%llx caught=%d)\n",
dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
basket.threadId, exceptionId, basket.caught);
@@ -1114,7 +1078,7 @@
expandBufAdd1(pReq, suspendPolicy);
expandBufAdd4BE(pReq, matchCount);
- for (i = 0; i < matchCount; i++) {
+ for (int i = 0; i < matchCount; i++) {
expandBufAdd1(pReq, matchList[i]->eventKind);
expandBufAdd4BE(pReq, matchList[i]->requestId);
expandBufAdd8BE(pReq, basket.threadId);
@@ -1157,10 +1121,8 @@
bool dvmJdwpPostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId,
const char* signature, int status)
{
- enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
+ JdwpSuspendPolicy suspendPolicy = SP_NONE;
ModBasket basket;
- JdwpEvent** matchList;
- int matchCount;
char* nameAlloc = NULL;
memset(&basket, 0, sizeof(basket));
@@ -1179,16 +1141,14 @@
/* don't allow the list to be updated while we scan it */
lockEventMutex(state);
- matchList = allocMatchList(state);
- matchCount = 0;
+ JdwpEvent** matchList = allocMatchList(state);
+ int matchCount = 0;
findMatchingEvents(state, EK_CLASS_PREPARE, &basket, matchList,
&matchCount);
ExpandBuf* pReq = NULL;
if (matchCount != 0) {
- int i;
-
LOGV("EVENT: %s(%d total) thread=%llx)\n",
dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
basket.threadId);
@@ -1213,7 +1173,7 @@
expandBufAdd1(pReq, suspendPolicy);
expandBufAdd4BE(pReq, matchCount);
- for (i = 0; i < matchCount; i++) {
+ for (int i = 0; i < matchCount; i++) {
expandBufAdd1(pReq, matchList[i]->eventKind);
expandBufAdd4BE(pReq, matchList[i]->requestId);
expandBufAdd8BE(pReq, basket.threadId);
@@ -1283,7 +1243,6 @@
{
u1 header[kJDWPHeaderLen + 8];
size_t dataLen = 0;
- int i;
assert(iov != NULL);
assert(iovcnt > 0 && iovcnt < 10);
@@ -1293,7 +1252,7 @@
* this by creating a new copy of the vector with space for the header.
*/
struct iovec wrapiov[iovcnt+1];
- for (i = 0; i < iovcnt; i++) {
+ for (int i = 0; i < iovcnt; i++) {
wrapiov[i+1].iov_base = iov[i].iov_base;
wrapiov[i+1].iov_len = iov[i].iov_len;
dataLen += iov[i].iov_len;
diff --git a/vm/jdwp/JdwpEvent.h b/vm/jdwp/JdwpEvent.h
index 288ab8c..1eb9b15 100644
--- a/vm/jdwp/JdwpEvent.h
+++ b/vm/jdwp/JdwpEvent.h
@@ -25,7 +25,7 @@
/*
* Event modifiers. A JdwpEvent may have zero or more of these.
*/
-typedef union JdwpEventMod {
+union JdwpEventMod {
u1 modKind; /* JdwpModKind */
struct {
u1 modKind;
@@ -76,24 +76,24 @@
u1 modKind;
ObjectId objectId;
} instanceOnly;
-} JdwpEventMod;
+};
/*
* One of these for every registered event.
*
* We over-allocate the struct to hold the modifiers.
*/
-typedef struct JdwpEvent {
- struct JdwpEvent* prev; /* linked list */
- struct JdwpEvent* next;
+struct JdwpEvent {
+ JdwpEvent* prev; /* linked list */
+ JdwpEvent* next;
- enum JdwpEventKind eventKind; /* what kind of event is this? */
- enum JdwpSuspendPolicy suspendPolicy; /* suspend all, none, or self? */
- int modCount; /* #of entries in mods[] */
- u4 requestId; /* serial#, reported to debugger */
+ JdwpEventKind eventKind; /* what kind of event is this? */
+ JdwpSuspendPolicy suspendPolicy; /* suspend all, none, or self? */
+ int modCount; /* #of entries in mods[] */
+ u4 requestId; /* serial#, reported to debugger */
- JdwpEventMod mods[1]; /* MUST be last field in struct */
-} JdwpEvent;
+ JdwpEventMod mods[1]; /* MUST be last field in struct */
+};
/*
* Allocate an event structure with enough space.
diff --git a/vm/jdwp/JdwpHandler.c b/vm/jdwp/JdwpHandler.cpp
similarity index 85%
rename from vm/jdwp/JdwpHandler.c
rename to vm/jdwp/JdwpHandler.cpp
index f04fb95..930d25e 100644
--- a/vm/jdwp/JdwpHandler.c
+++ b/vm/jdwp/JdwpHandler.cpp
@@ -38,23 +38,6 @@
#include <string.h>
#include <unistd.h>
-#if 0
-#include <time.h>
-#include <sys/time.h>
-static void showTime(const char* label)
-{
- struct timeval tv;
- int min, sec, msec;
-
- gettimeofday(&tv, NULL);
- min = (tv.tv_sec / 60) % 60;
- sec = tv.tv_sec % 60;
- msec = tv.tv_usec / 1000;
-
- LOGI("%02d:%02d.%03d %s\n", min, sec, msec, label);
-}
-#endif
-
/*
* Helper function: read a "location" from an input buffer.
*/
@@ -121,15 +104,9 @@
ObjectId threadId, ObjectId objectId, RefTypeId classId, MethodId methodId,
bool isConstructor)
{
- JdwpError err = ERR_NONE;
- u8* argArray = NULL;
- u4 numArgs;
- u4 options; /* enum InvokeOptions bit flags */
- int i;
-
assert(!isConstructor || objectId != 0);
- numArgs = read4BE(&buf);
+ u4 numArgs = read4BE(&buf);
LOGV(" --> threadId=%llx objectId=%llx\n", threadId, objectId);
LOGV(" classId=%llx methodId=%x %s.%s\n",
@@ -138,23 +115,20 @@
dvmDbgGetMethodName(classId, methodId));
LOGV(" %d args:\n", numArgs);
+ u8* argArray = NULL;
if (numArgs > 0)
argArray = (ObjectId*) malloc(sizeof(ObjectId) * numArgs);
- for (i = 0; i < (int) numArgs; i++) {
- u1 typeTag;
- u8 value;
- int width;
-
- typeTag = read1(&buf);
- width = dvmDbgGetTagWidth(typeTag);
- value = jdwpReadValue(&buf, width);
+ for (u4 i = 0; i < numArgs; i++) {
+ u1 typeTag = read1(&buf);
+ int width = dvmDbgGetTagWidth(typeTag);
+ u8 value = jdwpReadValue(&buf, width);
LOGV(" '%c'(%d): 0x%llx\n", typeTag, width, value);
argArray[i] = value;
}
- options = read4BE(&buf);
+ u4 options = read4BE(&buf); /* enum InvokeOptions bit flags */
LOGV(" options=0x%04x%s%s\n", options,
(options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "",
(options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
@@ -163,8 +137,7 @@
u1 resultTag;
u8 resultValue;
ObjectId exceptObjId;
-
- err = dvmDbgInvokeMethod(threadId, objectId, classId, methodId,
+ JdwpError err = dvmDbgInvokeMethod(threadId, objectId, classId, methodId,
numArgs, argArray, options,
&resultTag, &resultValue, &exceptObjId);
if (err != ERR_NONE)
@@ -236,12 +209,8 @@
static JdwpError handleVM_ClassesBySignature(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- char* classDescriptor = NULL;
- u4 numClasses;
size_t strLen;
- RefTypeId refTypeId;
-
- classDescriptor = readNewUtf8String(&buf, &strLen);
+ char* classDescriptor = readNewUtf8String(&buf, &strLen);
LOGV(" Req for class by signature '%s'\n", classDescriptor);
/*
@@ -250,6 +219,8 @@
*
* NOTE: this may mangle "className".
*/
+ u4 numClasses;
+ RefTypeId refTypeId;
if (!dvmDbgFindLoadedClassBySignature(classDescriptor, &refTypeId)) {
/* not currently loaded */
LOGV(" --> no match!\n");
@@ -287,17 +258,14 @@
static JdwpError handleVM_AllThreads(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- u4 threadCount;
ObjectId* pThreadIds;
- ObjectId* walker;
- int i;
-
+ u4 threadCount;
dvmDbgGetAllThreads(&pThreadIds, &threadCount);
expandBufAdd4BE(pReply, threadCount);
- walker = pThreadIds;
- for (i = 0; i < (int) threadCount; i++) {
+ ObjectId* walker = pThreadIds;
+ for (u4 i = 0; i < threadCount; i++) {
expandBufAddObjectId(pReply, *walker++);
}
@@ -312,20 +280,17 @@
static JdwpError handleVM_TopLevelThreadGroups(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- u4 groups;
- ObjectId threadGroupId;
-
/*
* TODO: maintain a list of parentless thread groups in the VM.
*
* For now, just return "system". Application threads are created
* in "main", which is a child of "system".
*/
- groups = 1;
+ u4 groups = 1;
expandBufAdd4BE(pReply, groups);
//threadGroupId = debugGetMainThreadGroup();
//expandBufAdd8BE(pReply, threadGroupId);
- threadGroupId = dvmDbgGetSystemThreadGroupId();
+ ObjectId threadGroupId = dvmDbgGetSystemThreadGroupId();
expandBufAddObjectId(pReply, threadGroupId);
return ERR_NONE;
@@ -388,9 +353,7 @@
static JdwpError handleVM_Exit(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- u4 exitCode;
-
- exitCode = get4BE(buf);
+ u4 exitCode = get4BE(buf);
LOGW("Debugger is telling the VM to exit with code=%d\n", exitCode);
@@ -407,15 +370,12 @@
static JdwpError handleVM_CreateString(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- char* str;
size_t strLen;
- ObjectId stringId;
-
- str = readNewUtf8String(&buf, &strLen);
+ char* str = readNewUtf8String(&buf, &strLen);
LOGV(" Req to create string '%s'\n", str);
- stringId = dvmDbgCreateString(str);
+ ObjectId stringId = dvmDbgCreateString(str);
if (stringId == 0)
return ERR_OUT_OF_MEMORY;
@@ -446,25 +406,22 @@
const u1* buf, int dataLen, ExpandBuf* pReply)
{
char baseDir[2] = "/";
- u4 classPaths;
- u4 bootClassPaths;
- int i;
/*
* TODO: make this real. Not important for remote debugging, but
* might be useful for local debugging.
*/
- classPaths = 1;
- bootClassPaths = 0;
+ u4 classPaths = 1;
+ u4 bootClassPaths = 0;
expandBufAddUtf8String(pReply, (const u1*) baseDir);
expandBufAdd4BE(pReply, classPaths);
- for (i = 0; i < (int) classPaths; i++) {
+ for (u4 i = 0; i < classPaths; i++) {
expandBufAddUtf8String(pReply, (const u1*) ".");
}
expandBufAdd4BE(pReply, bootClassPaths);
- for (i = 0; i < (int) classPaths; i++) {
+ for (u4 i = 0; i < classPaths; i++) {
/* add bootclasspath components as strings */
}
@@ -488,8 +445,6 @@
static JdwpError handleVM_CapabilitiesNew(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- int i;
-
expandBufAdd1(pReply, false); /* canWatchFieldModification */
expandBufAdd1(pReply, false); /* canWatchFieldAccess */
expandBufAdd1(pReply, false); /* canGetBytecodes */
@@ -513,7 +468,7 @@
expandBufAdd1(pReply, false); /* 1.6: canForceEarlyReturn */
/* fill in reserved22 through reserved32; note count started at 1 */
- for (i = 22; i <= 32; i++)
+ for (int i = 22; i <= 32; i++)
expandBufAdd1(pReply, false); /* reservedN */
return ERR_NONE;
}
@@ -526,13 +481,12 @@
{
u4 numClasses = 0;
RefTypeId* classRefBuf = NULL;
- int i;
dvmDbgGetClassList(&numClasses, &classRefBuf);
expandBufAdd4BE(pReply, numClasses);
- for (i = 0; i < (int) numClasses; i++) {
+ for (u4 i = 0; i < numClasses; i++) {
static const u1 genericSignature[1] = "";
u1 refTypeTag;
const char* signature;
@@ -559,13 +513,10 @@
static JdwpError handleRT_Signature(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- const char* signature;
- RefTypeId refTypeId;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
LOGV(" Req for signature of refTypeId=0x%llx\n", refTypeId);
- signature = dvmDbgGetSignature(refTypeId);
+ const char* signature = dvmDbgGetSignature(refTypeId);
expandBufAddUtf8String(pReply, (const u1*) signature);
return ERR_NONE;
@@ -577,11 +528,8 @@
static JdwpError handleRT_Modifiers(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- u4 modBits;
-
- refTypeId = dvmReadRefTypeId(&buf);
- modBits = dvmDbgGetAccessFlags(refTypeId);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
+ u4 modBits = dvmDbgGetAccessFlags(refTypeId);
expandBufAdd4BE(pReply, modBits);
@@ -594,17 +542,13 @@
static JdwpError handleRT_GetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- u4 numFields;
- int i;
-
- refTypeId = dvmReadRefTypeId(&buf);
- numFields = read4BE(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
+ u4 numFields = read4BE(&buf);
LOGV(" RT_GetValues %u:\n", numFields);
expandBufAdd4BE(pReply, numFields);
- for (i = 0; i < (int) numFields; i++) {
+ for (u4 i = 0; i < numFields; i++) {
FieldId fieldId = dvmReadFieldId(&buf);
dvmDbgGetStaticFieldValue(refTypeId, fieldId, pReply);
}
@@ -618,12 +562,9 @@
static JdwpError handleRT_SourceFile(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- const char* fileName;
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
- refTypeId = dvmReadRefTypeId(&buf);
-
- fileName = dvmDbgGetSourceFile(refTypeId);
+ const char* fileName = dvmDbgGetSourceFile(refTypeId);
if (fileName != NULL) {
expandBufAddUtf8String(pReply, (const u1*) fileName);
return ERR_NONE;
@@ -638,13 +579,11 @@
static JdwpError handleRT_Status(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- u1 typeTag;
- u4 status;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
/* get status flags */
+ u1 typeTag;
+ u4 status;
dvmDbgGetClassInfo(refTypeId, &typeTag, &status, NULL);
expandBufAdd4BE(pReply, status);
return ERR_NONE;
@@ -656,9 +595,7 @@
static JdwpError handleRT_Interfaces(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
LOGV(" Req for interfaces in %llx (%s)\n", refTypeId,
dvmDbgGetClassDescriptor(refTypeId));
@@ -674,11 +611,8 @@
static JdwpError handleRT_ClassObject(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- ObjectId classObjId;
-
- refTypeId = dvmReadRefTypeId(&buf);
- classObjId = dvmDbgGetClassObject(refTypeId);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
+ ObjectId classObjId = dvmDbgGetClassObject(refTypeId);
LOGV(" RefTypeId %llx -> ObjectId %llx\n", refTypeId, classObjId);
@@ -706,13 +640,11 @@
const u1* buf, int dataLen, ExpandBuf* pReply)
{
static const u1 genericSignature[1] = "";
- const char* signature;
- RefTypeId refTypeId;
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
LOGV(" Req for signature of refTypeId=0x%llx\n", refTypeId);
- signature = dvmDbgGetSignature(refTypeId);
+ const char* signature = dvmDbgGetSignature(refTypeId);
if (signature != NULL) {
expandBufAddUtf8String(pReply, (const u1*) signature);
} else {
@@ -731,9 +663,7 @@
static JdwpError handleRT_ClassLoader(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
expandBufAddObjectId(pReply, dvmDbgGetClassLoader(refTypeId));
@@ -747,9 +677,7 @@
static JdwpError handleRT_FieldsWithGeneric(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
LOGV(" Req for fields in refTypeId=0x%llx\n", refTypeId);
LOGV(" --> '%s'\n", dvmDbgGetSignature(refTypeId));
@@ -765,9 +693,7 @@
static JdwpError handleRT_MethodsWithGeneric(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
-
- refTypeId = dvmReadRefTypeId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
LOGV(" Req for methods in refTypeId=0x%llx\n", refTypeId);
LOGV(" --> '%s'\n", dvmDbgGetSignature(refTypeId));
@@ -783,12 +709,9 @@
static JdwpError handleCT_Superclass(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classId;
- RefTypeId superClassId;
+ RefTypeId classId = dvmReadRefTypeId(&buf);
- classId = dvmReadRefTypeId(&buf);
-
- superClassId = dvmDbgGetSuperclass(classId);
+ RefTypeId superClassId = dvmDbgGetSuperclass(classId);
expandBufAddRefTypeId(pReply, superClassId);
@@ -801,25 +724,16 @@
static JdwpError handleCT_SetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classId;
- u4 values;
- int i;
-
- classId = dvmReadRefTypeId(&buf);
- values = read4BE(&buf);
+ RefTypeId classId = dvmReadRefTypeId(&buf);
+ u4 values = read4BE(&buf);
LOGV(" Req to set %d values in classId=%llx\n", values, classId);
- for (i = 0; i < (int) values; i++) {
- FieldId fieldId;
- u1 fieldTag;
- u8 value;
- int width;
-
- fieldId = dvmReadFieldId(&buf);
- fieldTag = dvmDbgGetStaticFieldBasicTag(classId, fieldId);
- width = dvmDbgGetTagWidth(fieldTag);
- value = jdwpReadValue(&buf, width);
+ for (u4 i = 0; i < values; i++) {
+ FieldId fieldId = dvmReadFieldId(&buf);
+ u1 fieldTag = dvmDbgGetStaticFieldBasicTag(classId, fieldId);
+ int width = dvmDbgGetTagWidth(fieldTag);
+ u8 value = jdwpReadValue(&buf, width);
LOGV(" --> field=%x tag=%c -> %lld\n", fieldId, fieldTag, value);
dvmDbgSetStaticFieldValue(classId, fieldId, value, width);
@@ -837,13 +751,9 @@
static JdwpError handleCT_InvokeMethod(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classId;
- ObjectId threadId;
- MethodId methodId;
-
- classId = dvmReadRefTypeId(&buf);
- threadId = dvmReadObjectId(&buf);
- methodId = dvmReadMethodId(&buf);
+ RefTypeId classId = dvmReadRefTypeId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ MethodId methodId = dvmReadMethodId(&buf);
return finishInvoke(state, buf, dataLen, pReply,
threadId, 0, classId, methodId, false);
@@ -859,17 +769,12 @@
static JdwpError handleCT_NewInstance(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classId;
- ObjectId threadId;
- MethodId methodId;
- ObjectId objectId;
-
- classId = dvmReadRefTypeId(&buf);
- threadId = dvmReadObjectId(&buf);
- methodId = dvmReadMethodId(&buf);
+ RefTypeId classId = dvmReadRefTypeId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ MethodId methodId = dvmReadMethodId(&buf);
LOGV("Creating instance of %s\n", dvmDbgGetClassDescriptor(classId));
- objectId = dvmDbgCreateObject(classId);
+ ObjectId objectId = dvmDbgCreateObject(classId);
if (objectId == 0)
return ERR_OUT_OF_MEMORY;
@@ -883,16 +788,12 @@
static JdwpError handleAT_newInstance(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId arrayTypeId;
- u4 length;
- ObjectId objectId;
-
- arrayTypeId = dvmReadRefTypeId(&buf);
- length = read4BE(&buf);
+ RefTypeId arrayTypeId = dvmReadRefTypeId(&buf);
+ u4 length = read4BE(&buf);
LOGV("Creating array %s[%u]\n",
dvmDbgGetClassDescriptor(arrayTypeId), length);
- objectId = dvmDbgCreateArrayObject(arrayTypeId, length);
+ ObjectId objectId = dvmDbgCreateArrayObject(arrayTypeId, length);
if (objectId == 0)
return ERR_OUT_OF_MEMORY;
@@ -907,11 +808,8 @@
static JdwpError handleM_LineTable(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId refTypeId;
- MethodId methodId;
-
- refTypeId = dvmReadRefTypeId(&buf);
- methodId = dvmReadMethodId(&buf);
+ RefTypeId refTypeId = dvmReadRefTypeId(&buf);
+ MethodId methodId = dvmReadMethodId(&buf);
LOGV(" Req for line table in %s.%s\n",
dvmDbgGetClassDescriptor(refTypeId),
@@ -928,11 +826,8 @@
static JdwpError handleM_VariableTableWithGeneric(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classId;
- MethodId methodId;
-
- classId = dvmReadRefTypeId(&buf);
- methodId = dvmReadMethodId(&buf);
+ RefTypeId classId = dvmReadRefTypeId(&buf);
+ MethodId methodId = dvmReadMethodId(&buf);
LOGV(" Req for LocalVarTab in class=%s method=%s\n",
dvmDbgGetClassDescriptor(classId),
@@ -959,13 +854,11 @@
static JdwpError handleOR_ReferenceType(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId objectId;
- u1 refTypeTag;
- RefTypeId typeId;
-
- objectId = dvmReadObjectId(&buf);
+ ObjectId objectId = dvmReadObjectId(&buf);
LOGV(" Req for type of objectId=0x%llx\n", objectId);
+ u1 refTypeTag;
+ RefTypeId typeId;
dvmDbgGetObjectType(objectId, &refTypeTag, &typeId);
expandBufAdd1(pReply, refTypeTag);
@@ -980,18 +873,14 @@
static JdwpError handleOR_GetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId objectId;
- u4 numFields;
- int i;
-
- objectId = dvmReadObjectId(&buf);
- numFields = read4BE(&buf);
+ ObjectId objectId = dvmReadObjectId(&buf);
+ u4 numFields = read4BE(&buf);
LOGV(" Req for %d fields from objectId=0x%llx\n", numFields, objectId);
expandBufAdd4BE(pReply, numFields);
- for (i = 0; i < (int) numFields; i++) {
+ for (u4 i = 0; i < numFields; i++) {
FieldId fieldId = dvmReadFieldId(&buf);
dvmDbgGetFieldValue(objectId, fieldId, pReply);
}
@@ -1005,26 +894,17 @@
static JdwpError handleOR_SetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId objectId;
- u4 numFields;
- int i;
-
- objectId = dvmReadObjectId(&buf);
- numFields = read4BE(&buf);
+ ObjectId objectId = dvmReadObjectId(&buf);
+ u4 numFields = read4BE(&buf);
LOGV(" Req to set %d fields in objectId=0x%llx\n", numFields, objectId);
- for (i = 0; i < (int) numFields; i++) {
- FieldId fieldId;
- u1 fieldTag;
- int width;
- u8 value;
+ for (u4 i = 0; i < numFields; i++) {
+ FieldId fieldId = dvmReadFieldId(&buf);
- fieldId = dvmReadFieldId(&buf);
-
- fieldTag = dvmDbgGetFieldBasicTag(objectId, fieldId);
- width = dvmDbgGetTagWidth(fieldTag);
- value = jdwpReadValue(&buf, width);
+ u1 fieldTag = dvmDbgGetFieldBasicTag(objectId, fieldId);
+ int width = dvmDbgGetTagWidth(fieldTag);
+ u8 value = jdwpReadValue(&buf, width);
LOGV(" --> fieldId=%x tag='%c'(%d) value=%lld\n",
fieldId, fieldTag, width, value);
@@ -1049,15 +929,10 @@
static JdwpError handleOR_InvokeMethod(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId objectId;
- ObjectId threadId;
- RefTypeId classId;
- MethodId methodId;
-
- objectId = dvmReadObjectId(&buf);
- threadId = dvmReadObjectId(&buf);
- classId = dvmReadRefTypeId(&buf);
- methodId = dvmReadMethodId(&buf);
+ ObjectId objectId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ RefTypeId classId = dvmReadRefTypeId(&buf);
+ MethodId methodId = dvmReadMethodId(&buf);
return finishInvoke(state, buf, dataLen, pReply,
threadId, objectId, classId, methodId, false);
@@ -1092,7 +967,6 @@
ObjectId objectId;
objectId = dvmReadObjectId(&buf);
-
LOGV(" Req IsCollected(0x%llx)\n", objectId);
// TODO: currently returning false; must integrate with GC
@@ -1107,11 +981,8 @@
static JdwpError handleSR_Value(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId stringObject;
- char* str;
-
- stringObject = dvmReadObjectId(&buf);
- str = dvmDbgStringToUtf8(stringObject);
+ ObjectId stringObject = dvmReadObjectId(&buf);
+ char* str = dvmDbgStringToUtf8(stringObject);
LOGV(" Req for str %llx --> '%s'\n", stringObject, str);
@@ -1127,13 +998,10 @@
static JdwpError handleTR_Name(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- char* name;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
LOGV(" Req for name of thread 0x%llx\n", threadId);
- name = dvmDbgGetThreadName(threadId);
+ char* name = dvmDbgGetThreadName(threadId);
if (name == NULL)
return ERR_INVALID_THREAD;
@@ -1152,9 +1020,7 @@
static JdwpError handleTR_Suspend(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
if (threadId == dvmDbgGetThreadSelfId()) {
LOGI(" Warning: ignoring request to suspend self\n");
@@ -1173,9 +1039,7 @@
static JdwpError handleTR_Resume(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
if (threadId == dvmDbgGetThreadSelfId()) {
LOGI(" Warning: ignoring request to resume self\n");
@@ -1194,14 +1058,12 @@
static JdwpError handleTR_Status(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- u4 threadStatus;
- u4 suspendStatus;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
LOGV(" Req for status of thread 0x%llx\n", threadId);
+ u4 threadStatus;
+ u4 suspendStatus;
if (!dvmDbgGetThreadStatus(threadId, &threadStatus, &suspendStatus))
return ERR_INVALID_THREAD;
@@ -1220,13 +1082,10 @@
static JdwpError handleTR_ThreadGroup(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- ObjectId threadGroupId;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
/* currently not handling these */
- threadGroupId = dvmDbgGetThreadGroup(threadId);
+ ObjectId threadGroupId = dvmDbgGetThreadGroup(threadId);
expandBufAddObjectId(pReply, threadGroupId);
return ERR_NONE;
@@ -1241,13 +1100,9 @@
static JdwpError handleTR_Frames(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- u4 startFrame, length, frames;
- int i, frameCount;
-
- threadId = dvmReadObjectId(&buf);
- startFrame = read4BE(&buf);
- length = read4BE(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ u4 startFrame = read4BE(&buf);
+ u4 length = read4BE(&buf);
if (!dvmDbgThreadExists(threadId))
return ERR_INVALID_THREAD;
@@ -1257,7 +1112,7 @@
return ERR_THREAD_NOT_SUSPENDED;
}
- frameCount = dvmDbgGetThreadFrameCount(threadId);
+ int frameCount = dvmDbgGetThreadFrameCount(threadId);
LOGV(" Request for frames: threadId=%llx start=%d length=%d [count=%d]\n",
threadId, startFrame, length, frameCount);
@@ -1269,9 +1124,9 @@
assert((int) startFrame >= 0 && (int) startFrame < frameCount);
assert((int) (startFrame + length) <= frameCount);
- frames = length;
+ u4 frames = length;
expandBufAdd4BE(pReply, frames);
- for (i = startFrame; i < (int) (startFrame+length); i++) {
+ for (u4 i = startFrame; i < (startFrame+length); i++) {
FrameId frameId;
JdwpLocation loc;
@@ -1293,10 +1148,7 @@
static JdwpError handleTR_FrameCount(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- int frameCount;
-
- threadId = dvmReadObjectId(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
if (!dvmDbgThreadExists(threadId))
return ERR_INVALID_THREAD;
@@ -1306,7 +1158,7 @@
return ERR_THREAD_NOT_SUSPENDED;
}
- frameCount = dvmDbgGetThreadFrameCount(threadId);
+ int frameCount = dvmDbgGetThreadFrameCount(threadId);
if (frameCount < 0)
return ERR_INVALID_THREAD;
expandBufAdd4BE(pReply, (u4)frameCount);
@@ -1339,12 +1191,9 @@
static JdwpError handleTR_SuspendCount(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- u4 suspendCount;
+ ObjectId threadId = dvmReadObjectId(&buf);
- threadId = dvmReadObjectId(&buf);
-
- suspendCount = dvmDbgGetThreadSuspendCount(threadId);
+ u4 suspendCount = dvmDbgGetThreadSuspendCount(threadId);
expandBufAdd4BE(pReply, suspendCount);
return ERR_NONE;
@@ -1358,13 +1207,10 @@
static JdwpError handleTGR_Name(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadGroupId;
- char* name = NULL;
-
- threadGroupId = dvmReadObjectId(&buf);
+ ObjectId threadGroupId = dvmReadObjectId(&buf);
LOGV(" Req for name of threadGroupId=0x%llx\n", threadGroupId);
- name = dvmDbgGetThreadGroupName(threadGroupId);
+ char* name = dvmDbgGetThreadGroupName(threadGroupId);
if (name != NULL)
expandBufAddUtf8String(pReply, (u1*) name);
else {
@@ -1384,12 +1230,9 @@
static JdwpError handleTGR_Parent(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId groupId;
- ObjectId parentGroup;
+ ObjectId groupId = dvmReadObjectId(&buf);
- groupId = dvmReadObjectId(&buf);
-
- parentGroup = dvmDbgGetThreadGroupParent(groupId);
+ ObjectId parentGroup = dvmDbgGetThreadGroupParent(groupId);
expandBufAddObjectId(pReply, parentGroup);
return ERR_NONE;
@@ -1402,21 +1245,16 @@
static JdwpError handleTGR_Children(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadGroupId;
- u4 threadCount;
- ObjectId* pThreadIds;
- ObjectId* walker;
- int i;
-
- threadGroupId = dvmReadObjectId(&buf);
+ ObjectId threadGroupId = dvmReadObjectId(&buf);
LOGV(" Req for threads in threadGroupId=0x%llx\n", threadGroupId);
+ ObjectId* pThreadIds;
+ u4 threadCount;
dvmDbgGetThreadGroupThreads(threadGroupId, &pThreadIds, &threadCount);
expandBufAdd4BE(pReply, threadCount);
- walker = pThreadIds;
- for (i = 0; i < (int) threadCount; i++)
+ for (u4 i = 0; i < threadCount; i++)
expandBufAddObjectId(pReply, pThreadIds[i]);
free(pThreadIds);
@@ -1441,13 +1279,10 @@
static JdwpError handleAR_Length(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId arrayId;
- u4 arrayLength;
-
- arrayId = dvmReadObjectId(&buf);
+ ObjectId arrayId = dvmReadObjectId(&buf);
LOGV(" Req for length of array 0x%llx\n", arrayId);
- arrayLength = dvmDbgGetArrayLength(arrayId);
+ u4 arrayLength = dvmDbgGetArrayLength(arrayId);
LOGV(" --> %d\n", arrayLength);
@@ -1462,16 +1297,11 @@
static JdwpError handleAR_GetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId arrayId;
- u4 firstIndex;
- u4 length;
- u1 tag;
+ ObjectId arrayId = dvmReadObjectId(&buf);
+ u4 firstIndex = read4BE(&buf);
+ u4 length = read4BE(&buf);
- arrayId = dvmReadObjectId(&buf);
- firstIndex = read4BE(&buf);
- length = read4BE(&buf);
-
- tag = dvmDbgGetArrayElementTag(arrayId);
+ u1 tag = dvmDbgGetArrayElementTag(arrayId);
LOGV(" Req for array values 0x%llx first=%d len=%d (elem tag=%c)\n",
arrayId, firstIndex, length, tag);
@@ -1490,13 +1320,9 @@
static JdwpError handleAR_SetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId arrayId;
- u4 firstIndex;
- u4 values;
-
- arrayId = dvmReadObjectId(&buf);
- firstIndex = read4BE(&buf);
- values = read4BE(&buf);
+ ObjectId arrayId = dvmReadObjectId(&buf);
+ u4 firstIndex = read4BE(&buf);
+ u4 values = read4BE(&buf);
LOGV(" Req to set array values 0x%llx first=%d count=%d\n",
arrayId, firstIndex, values);
@@ -1544,19 +1370,11 @@
static JdwpError handleER_Set(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- JdwpEvent* pEvent;
- JdwpError err;
const u1* origBuf = buf;
- /*int origDataLen = dataLen;*/
- u1 eventKind;
- u1 suspendPolicy;
- u4 modifierCount;
- u4 requestId;
- int idx;
- eventKind = read1(&buf);
- suspendPolicy = read1(&buf);
- modifierCount = read4BE(&buf);
+ u1 eventKind = read1(&buf);
+ u1 suspendPolicy = read1(&buf);
+ u4 modifierCount = read4BE(&buf);
LOGVV(" Set(kind=%s(%u) suspend=%s(%u) mods=%u)\n",
dvmJdwpEventKindStr(eventKind), eventKind,
@@ -1565,19 +1383,17 @@
assert(modifierCount < 256); /* reasonableness check */
- pEvent = dvmJdwpEventAlloc(modifierCount);
- pEvent->eventKind = eventKind;
- pEvent->suspendPolicy = suspendPolicy;
+ JdwpEvent* pEvent = dvmJdwpEventAlloc(modifierCount);
+ pEvent->eventKind = static_cast<JdwpEventKind>(eventKind);
+ pEvent->suspendPolicy = static_cast<JdwpSuspendPolicy>(suspendPolicy);
pEvent->modCount = modifierCount;
/*
* Read modifiers. Ordering may be significant (see explanation of Count
* mods in JDWP doc).
*/
- for (idx = 0; idx < (int) modifierCount; idx++) {
- u1 modKind;
-
- modKind = read1(&buf);
+ for (u4 idx = 0; idx < modifierCount; idx++) {
+ u1 modKind = read1(&buf);
pEvent->mods[idx].modKind = modKind;
@@ -1717,7 +1533,7 @@
/*
* We reply with an integer "requestID".
*/
- requestId = dvmJdwpNextEventSerial(state);
+ u4 requestId = dvmJdwpNextEventSerial(state);
expandBufAdd4BE(pReply, requestId);
pEvent->requestId = requestId;
@@ -1725,7 +1541,7 @@
LOGV(" --> event requestId=0x%x\n", requestId);
/* add it to the list */
- err = dvmJdwpRegisterEvent(state, pEvent);
+ JdwpError err = dvmJdwpRegisterEvent(state, pEvent);
if (err != ERR_NONE) {
/* registration failed, probably because event is bogus */
dvmJdwpEventFree(pEvent);
@@ -1742,12 +1558,10 @@
const u1* buf, int dataLen, ExpandBuf* pReply)
{
u1 eventKind;
- u4 requestId;
-
eventKind = read1(&buf);
- requestId = read4BE(&buf);
+ u4 requestId = read4BE(&buf);
- LOGV(" Req to clear eventKind=%d requestId=0x%08x\n", eventKind,requestId);
+ LOGV(" Req to clear eventKind=%d requestId=%#x", eventKind, requestId);
dvmJdwpUnregisterEventById(state, requestId);
@@ -1760,32 +1574,22 @@
static JdwpError handleSF_GetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- FrameId frameId;
- u4 slots;
- int i;
-
- threadId = dvmReadObjectId(&buf);
- frameId = dvmReadFrameId(&buf);
- slots = read4BE(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ FrameId frameId = dvmReadFrameId(&buf);
+ u4 slots = read4BE(&buf);
LOGV(" Req for %d slots in threadId=%llx frameId=%llx\n",
slots, threadId, frameId);
expandBufAdd4BE(pReply, slots); /* "int values" */
- for (i = 0; i < (int) slots; i++) {
- u4 slot;
- u1 reqSigByte;
- int width;
- u1* ptr;
-
- slot = read4BE(&buf);
- reqSigByte = read1(&buf);
+ for (u4 i = 0; i < slots; i++) {
+ u4 slot = read4BE(&buf);
+ u1 reqSigByte = read1(&buf);
LOGV(" --> slot %d '%c'\n", slot, reqSigByte);
- width = dvmDbgGetTagWidth(reqSigByte);
- ptr = expandBufAddSpace(pReply, width+1);
+ int width = dvmDbgGetTagWidth(reqSigByte);
+ u1* ptr = expandBufAddSpace(pReply, width+1);
dvmDbgGetLocalValue(threadId, frameId, slot, reqSigByte, ptr, width);
}
@@ -1798,28 +1602,18 @@
static JdwpError handleSF_SetValues(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- FrameId frameId;
- u4 slots;
- int i;
-
- threadId = dvmReadObjectId(&buf);
- frameId = dvmReadFrameId(&buf);
- slots = read4BE(&buf);
+ ObjectId threadId = dvmReadObjectId(&buf);
+ FrameId frameId = dvmReadFrameId(&buf);
+ u4 slots = read4BE(&buf);
LOGV(" Req to set %d slots in threadId=%llx frameId=%llx\n",
slots, threadId, frameId);
- for (i = 0; i < (int) slots; i++) {
- u4 slot;
- u1 sigByte;
- u8 value;
- int width;
-
- slot = read4BE(&buf);
- sigByte = read1(&buf);
- width = dvmDbgGetTagWidth(sigByte);
- value = jdwpReadValue(&buf, width);
+ for (u4 i = 0; i < slots; i++) {
+ u4 slot = read4BE(&buf);
+ u1 sigByte = read1(&buf);
+ int width = dvmDbgGetTagWidth(sigByte);
+ u8 value = jdwpReadValue(&buf, width);
LOGV(" --> slot %d '%c' %llx\n", slot, sigByte, value);
dvmDbgSetLocalValue(threadId, frameId, slot, sigByte, value, width);
@@ -1834,18 +1628,14 @@
static JdwpError handleSF_ThisObject(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- ObjectId threadId;
- FrameId frameId;
- u1 objectTag;
+ ObjectId threadId = dvmReadObjectId(&buf);
+ FrameId frameId = dvmReadFrameId(&buf);
+
ObjectId objectId;
-
- threadId = dvmReadObjectId(&buf);
- frameId = dvmReadFrameId(&buf);
-
if (!dvmDbgGetThisObject(threadId, frameId, &objectId))
return ERR_INVALID_FRAMEID;
- objectTag = dvmDbgGetObjectTag(objectId);
+ u1 objectTag = dvmDbgGetObjectTag(objectId);
LOGV(" Req for 'this' in thread=%llx frame=%llx --> %llx %s '%c'\n",
threadId, frameId, objectId, dvmDbgGetObjectTypeName(objectId),
(char)objectTag);
@@ -1866,9 +1656,7 @@
static JdwpError handleCOR_ReflectedType(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply)
{
- RefTypeId classObjectId;
-
- classObjectId = dvmReadRefTypeId(&buf);
+ RefTypeId classObjectId = dvmReadRefTypeId(&buf);
LOGV(" Req for refTypeId for class=%llx (%s)\n",
classObjectId, dvmDbgGetClassDescriptor(classObjectId));
@@ -1925,12 +1713,12 @@
typedef JdwpError (*JdwpRequestHandler)(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* reply);
-typedef struct {
+struct JdwpHandlerMap {
u1 cmdSet;
u1 cmd;
JdwpRequestHandler func;
const char* descr;
-} JdwpHandlerMap;
+};
/*
* Map commands to functions.
diff --git a/vm/jdwp/JdwpHandler.h b/vm/jdwp/JdwpHandler.h
index 3a7a98c..aade65d 100644
--- a/vm/jdwp/JdwpHandler.h
+++ b/vm/jdwp/JdwpHandler.h
@@ -25,12 +25,12 @@
/*
* JDWP message header for a request.
*/
-typedef struct JdwpReqHeader {
+struct JdwpReqHeader {
u4 length;
u4 id;
u1 cmdSet;
u1 cmd;
-} JdwpReqHeader;
+};
/*
* Process a request from the debugger.
diff --git a/vm/jdwp/JdwpMain.c b/vm/jdwp/JdwpMain.cpp
similarity index 99%
rename from vm/jdwp/JdwpMain.c
rename to vm/jdwp/JdwpMain.cpp
index 24e5c6c..4a33913 100644
--- a/vm/jdwp/JdwpMain.c
+++ b/vm/jdwp/JdwpMain.cpp
@@ -372,7 +372,7 @@
/*
* Get a notion of the current time, in milliseconds.
*/
-s8 dvmJdwpGetNowMsec(void)
+s8 dvmJdwpGetNowMsec()
{
#ifdef HAVE_POSIX_CLOCKS
struct timespec now;
diff --git a/vm/jdwp/JdwpPriv.h b/vm/jdwp/JdwpPriv.h
index bc249f1..6b15fa9 100644
--- a/vm/jdwp/JdwpPriv.h
+++ b/vm/jdwp/JdwpPriv.h
@@ -43,14 +43,12 @@
* Transport-specific network status.
*/
struct JdwpNetState;
-typedef struct JdwpNetState JdwpNetState;
-
struct JdwpState;
/*
* Transport functions.
*/
-typedef struct JdwpTransport {
+struct JdwpTransport {
bool (*startup)(struct JdwpState* state, const JdwpStartupParams* pParams);
bool (*accept)(struct JdwpState* state);
bool (*establish)(struct JdwpState* state);
@@ -63,7 +61,7 @@
bool (*sendRequest)(struct JdwpState* state, ExpandBuf* pReq);
bool (*sendBufferedRequest)(struct JdwpState* state,
const struct iovec* iov, int iovcnt);
-} JdwpTransport;
+};
const JdwpTransport* dvmJdwpSocketTransport();
const JdwpTransport* dvmJdwpAndroidAdbTransport();
diff --git a/vm/jdwp/JdwpSocket.c b/vm/jdwp/JdwpSocket.cpp
similarity index 99%
rename from vm/jdwp/JdwpSocket.c
rename to vm/jdwp/JdwpSocket.cpp
index 0c39202..d318b50 100644
--- a/vm/jdwp/JdwpSocket.c
+++ b/vm/jdwp/JdwpSocket.cpp
@@ -918,7 +918,7 @@
/*
* Return our set.
*/
-const JdwpTransport* dvmJdwpSocketTransport(void)
+const JdwpTransport* dvmJdwpSocketTransport()
{
return &socketTransport;
}
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.cpp
similarity index 96%
rename from vm/mterp/Mterp.c
rename to vm/mterp/Mterp.cpp
index fa9b037..ab439d5 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.cpp
@@ -17,6 +17,7 @@
/*
* Mterp entry point and support functions.
*/
+#include "Dalvik.h"
#include "mterp/Mterp.h"
#include <stddef.h>
@@ -25,7 +26,7 @@
/*
* Verify some constants used by the mterp interpreter.
*/
-bool dvmCheckAsmConstants(void)
+bool dvmCheckAsmConstants()
{
bool failed = false;
@@ -86,7 +87,7 @@
free(desc);
}
//LOGI("self is %p, pc=%p, fp=%p\n", self, self->interpSave.pc,
- // self->interpSave.fp);
+ // self->interpSave.curFrame);
//LOGI("first instruction is 0x%04x\n", self->interpSave.pc[0]);
/*
diff --git a/vm/mterp/Mterp.h b/vm/mterp/Mterp.h
index 69e5a2c..d68e0b1 100644
--- a/vm/mterp/Mterp.h
+++ b/vm/mterp/Mterp.h
@@ -30,7 +30,7 @@
* Call this during initialization to verify that the values in asm-constants.h
* are still correct.
*/
-bool dvmCheckAsmConstants(void);
+extern "C" bool dvmCheckAsmConstants(void);
/*
* Local entry and exit points. The platform-specific implementation must
@@ -42,7 +42,13 @@
*
* The "mterp" interpreter is always "standard".
*/
-bool dvmMterpStdRun(Thread* self);
-void dvmMterpStdBail(Thread* self, bool changeInterp);
+extern "C" bool dvmMterpStdRun(Thread* self);
+extern "C" void dvmMterpStdBail(Thread* self, bool changeInterp);
+
+/*
+ * Helper for common_printMethod(), invoked from the assembly
+ * interpreter.
+ */
+extern "C" void dvmMterpPrintMethod(Method* method);
#endif /*_DALVIK_MTERP_MTERP*/
diff --git a/vm/mterp/README.txt b/vm/mterp/README.txt
index ed7e003..6106740 100644
--- a/vm/mterp/README.txt
+++ b/vm/mterp/README.txt
@@ -83,7 +83,7 @@
import <filename>
The specified file is included immediately, in its entirety. No
- substitutions are performed. ".c" and ".h" files are copied to the
+ substitutions are performed. ".cpp" and ".h" files are copied to the
C output, ".S" files are copied to the asm output.
asm-stub <filename>
@@ -251,18 +251,55 @@
==== Interpreter Control ====
-To handle thread suspension, debugging, profiling, JIT compilation, etc.,
-there needs to be a way to break out of interpreter execution. To support
-this, there is an "interpBreak" record in each thread's private storage.
-If interpBreak.ctl.breakFlags is non-zero, the interpreter main loop must
-be interrupted and control sent to dvmCheckBefore(), which will figure out
-what actions are needed and carry them out.
+The central mechanism for interpreter control is the InterpBreak struture
+that is found in each thread's Thread struct (see vm/Thread.h). There
+is one mandatory field, and two optional fields:
-In the portable interpreter, this requirement is implemented as a simple
-polling test in the main loop. breakFlags is checked before the interpretation
-of each instruction. Though simple, this is costly. For mterp interpreters,
-we use a mechanism that swaps out the handler base register with a pointer
-to an alternate, or break-out, set of handlers. Note that interpretation
-interruption may be slightly delayed. Each thread has its own copy of the
-handler base (register rIBASE), which it will refresh on taken backards
-branches, exception throws and returns.
+ subMode - required, describes debug/profile/special operation
+ breakFlags & curHandlerTable - optional, used lower subMode polling costs
+
+The subMode field is a bitmask which records all currently active
+special modes of operation. For example, when Traceview profiling
+is active, kSubModeMethodTrace is set. This bit informs the interpreter
+that it must notify the profiling subsystem on each method entry and
+return. There are similar bits for an active debugging session,
+instruction count profiling, pending thread suspension request, etc.
+
+To support special subMode operation the simplest mechanism for the
+interpreter is to poll the subMode field before interpreting each Dalvik
+bytecode and take any required action. In fact, this is precisely
+what the portable interpreter does. The "FINISH" macro expands to
+include a test of subMode and subsequent call to the "dvmCheckBefore()".
+
+Per-instruction polling, however, is expensive and subMode operation is
+relative rare. For normal operation we'd like to avoid having to perform
+any checks unless a special subMode is actually in effect. This is
+where curHandlerTable and breakFlags come in to play.
+
+The mterp fast interpreter achieves much of its performance advantage
+over the portable interpreter through its efficient mechanism of
+transitioning from one Dalvik bytecode to the next. Mterp for ARM targets
+uses a computed-goto mechanism, in which the handler entrypoints are
+located at the base of the handler table + (opcode * 64). Mterp for x86
+targets instead uses a jump table of handler entry points indexed
+by the Dalvik opcode. To support efficient handling of special subModes,
+mterp supports two sets of handler entries (for ARM) or two jump
+tables (for x86). One handler set is optimized for speed and performs no
+inter-instruction checks (mainHandlerTable in the Thread structure), while
+the other includes a test of the subMode field (altHandlerTable).
+
+In normal operation (i.e. subMode == 0), the dedicated register rIBASE
+(r8 for ARM, edx for x86) holds a mainHandlerTable. If we need to switch
+to a subMode that requires inter-instruction checking, rIBASE is changed
+to altHandlerTable. Note that this change is not immediate. What is actually
+changed is the value of curHandlerTable - which is part of the interpBreak
+structure. Rather than explicitly check for changes, each thread will
+blindly refresh rIBASE at backward branches, exception throws and returns.
+
+The breakFlags field tells the interpreter control mechanism whether
+curHandlerTable should hold the real or alternate handler base. If
+non-zero, we use the altHandlerBase. The bits within breakFlags
+tells dvmCheckBefore which set of subModes need to be checked.
+
+See dvmCheckBefore() for subMode handling, and dvmEnableSubMode(),
+dvmDisableSubMode() for switching on and off.
diff --git a/vm/mterp/armv5te/OP_EXECUTE_INLINE.S b/vm/mterp/armv5te/OP_EXECUTE_INLINE.S
index a77ce12..806eb98 100644
--- a/vm/mterp/armv5te/OP_EXECUTE_INLINE.S
+++ b/vm/mterp/armv5te/OP_EXECUTE_INLINE.S
@@ -14,7 +14,7 @@
* swap if profiler/debuggger active.
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
diff --git a/vm/mterp/armv5te/OP_EXECUTE_INLINE_RANGE.S b/vm/mterp/armv5te/OP_EXECUTE_INLINE_RANGE.S
index b5b9c32..bb4b0e8 100644
--- a/vm/mterp/armv5te/OP_EXECUTE_INLINE_RANGE.S
+++ b/vm/mterp/armv5te/OP_EXECUTE_INLINE_RANGE.S
@@ -12,7 +12,7 @@
* us if an exception was thrown.
*/
/* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
diff --git a/vm/mterp/armv5te/OP_INVOKE_OBJECT_INIT_RANGE.S b/vm/mterp/armv5te/OP_INVOKE_OBJECT_INIT_RANGE.S
index cdb98df..fb0e657 100644
--- a/vm/mterp/armv5te/OP_INVOKE_OBJECT_INIT_RANGE.S
+++ b/vm/mterp/armv5te/OP_INVOKE_OBJECT_INIT_RANGE.S
@@ -15,7 +15,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .L${opcode}_setFinal @ yes, go
.L${opcode}_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .L${opcode}_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(${cccc}+1) @ advance to next instr, load rINST
diff --git a/vm/mterp/armv5te/OP_INVOKE_STATIC.S b/vm/mterp/armv5te/OP_INVOKE_STATIC.S
index 66a5be3..a89db03 100644
--- a/vm/mterp/armv5te/OP_INVOKE_STATIC.S
+++ b/vm/mterp/armv5te/OP_INVOKE_STATIC.S
@@ -35,7 +35,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethod${routine} @ no (r0=method, r9="this")
diff --git a/vm/mterp/armv5te/OP_INVOKE_STATIC_JUMBO.S b/vm/mterp/armv5te/OP_INVOKE_STATIC_JUMBO.S
index 1ff4152..171127d 100644
--- a/vm/mterp/armv5te/OP_INVOKE_STATIC_JUMBO.S
+++ b/vm/mterp/armv5te/OP_INVOKE_STATIC_JUMBO.S
@@ -32,7 +32,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodJumboNoThis @ no (r0=method, r9="this")
diff --git a/vm/mterp/armv5te/OP_NEW_INSTANCE.S b/vm/mterp/armv5te/OP_NEW_INSTANCE.S
index eadd438..e280c4c 100644
--- a/vm/mterp/armv5te/OP_NEW_INSTANCE.S
+++ b/vm/mterp/armv5te/OP_NEW_INSTANCE.S
@@ -39,7 +39,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .L${opcode}_jitCheck
diff --git a/vm/mterp/armv5te/OP_NEW_INSTANCE_JUMBO.S b/vm/mterp/armv5te/OP_NEW_INSTANCE_JUMBO.S
index c5f7bdb..ce41bf3 100644
--- a/vm/mterp/armv5te/OP_NEW_INSTANCE_JUMBO.S
+++ b/vm/mterp/armv5te/OP_NEW_INSTANCE_JUMBO.S
@@ -41,7 +41,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .L${opcode}_jitCheck
diff --git a/vm/mterp/armv5te/debug.c b/vm/mterp/armv5te/debug.cpp
similarity index 100%
rename from vm/mterp/armv5te/debug.c
rename to vm/mterp/armv5te/debug.cpp
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index b262b1e..5e587b9 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -150,10 +150,8 @@
mov r1, #1
str r1, [rSELF,#offThread_singleStepCount] @ just step once
mov r0, rSELF
- mov r1, #kInterpSingleStep
- mov r2, #kSubModeNormal
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeCountedStep
+ bl dvmEnableSubMode @ (self, newMode)
ldr rIBASE, [rSELF,#offThread_curHandlerTable]
FETCH_INST()
GET_INST_OPCODE(ip)
@@ -371,8 +369,8 @@
* r2 is jit state.
*/
common_selectTrace:
- ldrb r0,[rSELF,#offThread_breakFlags]
- ands r0,#kInterpJitBreak
+ ldrh r0,[rSELF,#offThread_subMode]
+ ands r0, #(kSubModeJitTraceBuild | kSubModeJitSV)
bne 3f @ already doing JIT work, continue
str r2,[rSELF,#offThread_jitState]
mov r0, rSELF
@@ -427,10 +425,8 @@
beq 1f
@ Set up SV single-stepping
mov r0, rSELF
- mov r1, #kInterpJitBreak
- mov r2, #kSubModeJitSV
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeJitSV
+ bl dvmEnableSubMode @ (self, subMode)
mov r2,#kJitSelfVerification @ ask for self verification
str r2,[rSELF,#offThread_jitState]
@ intentional fallthrough
@@ -485,7 +481,7 @@
/* On entry: r0 is "Method* methodToCall, r9 is "this" */
.LinvokeNewJumbo:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -507,7 +503,7 @@
common_invokeMethodRange:
.LinvokeNewRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -537,7 +533,7 @@
common_invokeMethodNoRange:
.LinvokeNewNoRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -587,7 +583,7 @@
ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@@ -641,7 +637,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
cmp r0,#0
bne common_updateProfile
GOTO_OPCODE(ip) @ jump to next instruction
@@ -649,7 +645,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
GOTO_OPCODE(ip) @ jump to next instruction
#endif
@@ -657,7 +653,6 @@
@ Profiling - record method entry. r0: methodToCall
stmfd sp!, {r0-r3} @ preserve r0-r3
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r1, r0
mov r0, rSELF
bl dvmReportInvoke @ (self, method)
@@ -667,9 +662,9 @@
.LinvokeNative:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFp (points to args)
@@ -697,7 +692,7 @@
@ equivalent to dvmPopJniLocals
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
bne common_exceptionThrown @ no, handle exception
@@ -709,11 +704,10 @@
11:
@ r0=newFp, r1=&retval, r2=methodToCall, r3=self, lr=subModes
stmfd sp!, {r0-r3} @ save all but subModes
- str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPreNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPreNativeInvoke @ (methodToCall, self, fp)
ldmfd sp, {r0-r3} @ refresh. NOTE: no sp autoincrement
@ Call the native method
@@ -724,10 +718,10 @@
ldmfd sp!, {r0-r3} @ r2<- methodToCall (others unneeded)
@ Finish up any post-invoke subMode requirements
- @ interpSave already up-to-date
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPostNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPostNativeInvoke @ (methodToCall, self, fp)
b 7b @ resume
.LstackOverflow: @ r0=methodToCall
@@ -776,7 +770,7 @@
*/
common_returnFromMethod:
.LreturnNew:
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r0, rFP)
ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
cmp lr, #0 @ any special subMode handling needed?
@@ -800,7 +794,7 @@
PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
#if defined(WITH_JIT)
ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
mov rPC, r9 @ publish new rPC
@@ -822,7 +816,7 @@
@ On entry, r0: StackSaveArea
ldr r1, [r0, #offStackSaveArea_prevFrame] @ r2<- prevFP
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str r1, [rSELF, #offThread_fp] @ update interpSave.fp
+ str r1, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF
bl dvmReportReturn @ (self)
SAVEAREA_FROM_FP(r0, rFP) @ restore StackSaveArea
@@ -863,7 +857,7 @@
mov r1, rSELF @ r1<- self
mov r0, r9 @ r0<- exception
bl dvmAddTrackedAlloc @ don't let the exception be GCed
- ldrb r2, [rSELF, #offThread_subMode] @ get subMode flags
+ ldrh r2, [rSELF, #offThread_subMode] @ get subMode flags
mov r3, #0 @ r3<- NULL
str r3, [rSELF, #offThread_exception] @ self->exception = NULL
@@ -880,7 +874,7 @@
ldr r1, [rSELF, #offThread_method] @ r1<- self->method
mov r0, rSELF @ r0<- self
ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
- ldrb lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
+ ldrh lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
mov r2, r9 @ r2<- exception
sub r1, rPC, r1 @ r1<- pc - method->insns
mov r1, r1, asr #1 @ r1<- offset in code units
@@ -905,7 +899,7 @@
add sp, sp, #8 @ restore stack
bmi .LnotCaughtLocally
- /* adjust locals to match self->curFrame and updated PC */
+ /* adjust locals to match self->interpSave.curFrame and updated PC */
SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
str r1, [rSELF, #offThread_method] @ self->method = new method
@@ -931,7 +925,7 @@
@ Manage debugger bookkeeping
7:
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
+ str rFP, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF @ arg0<- self
mov r1, r9 @ arg1<- exception
bl dvmReportExceptionThrow @ (self, exception)
@@ -998,7 +992,7 @@
* r0: field pointer (must preserve)
*/
common_verifyField:
- ldrb r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
+ ldrh r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
ands r3, #kSubModeJitTraceBuild
bxeq lr @ Not building trace, continue
ldr r1, [r10] @ r1<- reload resolved StaticField ptr
diff --git a/vm/mterp/armv5te/header.S b/vm/mterp/armv5te/header.S
index ad45eb7..b3c8f0a 100644
--- a/vm/mterp/armv5te/header.S
+++ b/vm/mterp/armv5te/header.S
@@ -75,8 +75,8 @@
/* save/restore the PC and/or FP from the thread struct */
#define LOAD_PC_FROM_SELF() ldr rPC, [rSELF, #offThread_pc]
#define SAVE_PC_TO_SELF() str rPC, [rSELF, #offThread_pc]
-#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_fp]
-#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_fp]
+#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_curFrame]
+#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_curFrame]
#define LOAD_PC_FP_FROM_SELF() ldmia rSELF, {rPC, rFP}
#define SAVE_PC_FP_TO_SELF() stmia rSELF, {rPC, rFP}
diff --git a/vm/mterp/c/OP_ADD_DOUBLE.c b/vm/mterp/c/OP_ADD_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_DOUBLE.c
rename to vm/mterp/c/OP_ADD_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_ADD_DOUBLE_2ADDR.c b/vm/mterp/c/OP_ADD_DOUBLE_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_DOUBLE_2ADDR.c
rename to vm/mterp/c/OP_ADD_DOUBLE_2ADDR.cpp
diff --git a/vm/mterp/c/OP_ADD_FLOAT.c b/vm/mterp/c/OP_ADD_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_FLOAT.c
rename to vm/mterp/c/OP_ADD_FLOAT.cpp
diff --git a/vm/mterp/c/OP_ADD_FLOAT_2ADDR.c b/vm/mterp/c/OP_ADD_FLOAT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_FLOAT_2ADDR.c
rename to vm/mterp/c/OP_ADD_FLOAT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_ADD_INT.c b/vm/mterp/c/OP_ADD_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_INT.c
rename to vm/mterp/c/OP_ADD_INT.cpp
diff --git a/vm/mterp/c/OP_ADD_INT_2ADDR.c b/vm/mterp/c/OP_ADD_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_INT_2ADDR.c
rename to vm/mterp/c/OP_ADD_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_ADD_INT_LIT16.c b/vm/mterp/c/OP_ADD_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_INT_LIT16.c
rename to vm/mterp/c/OP_ADD_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_ADD_INT_LIT8.c b/vm/mterp/c/OP_ADD_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_INT_LIT8.c
rename to vm/mterp/c/OP_ADD_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_ADD_LONG.c b/vm/mterp/c/OP_ADD_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_LONG.c
rename to vm/mterp/c/OP_ADD_LONG.cpp
diff --git a/vm/mterp/c/OP_ADD_LONG_2ADDR.c b/vm/mterp/c/OP_ADD_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_ADD_LONG_2ADDR.c
rename to vm/mterp/c/OP_ADD_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_AGET.c b/vm/mterp/c/OP_AGET.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET.c
rename to vm/mterp/c/OP_AGET.cpp
diff --git a/vm/mterp/c/OP_AGET_BOOLEAN.c b/vm/mterp/c/OP_AGET_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_BOOLEAN.c
rename to vm/mterp/c/OP_AGET_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_AGET_BYTE.c b/vm/mterp/c/OP_AGET_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_BYTE.c
rename to vm/mterp/c/OP_AGET_BYTE.cpp
diff --git a/vm/mterp/c/OP_AGET_CHAR.c b/vm/mterp/c/OP_AGET_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_CHAR.c
rename to vm/mterp/c/OP_AGET_CHAR.cpp
diff --git a/vm/mterp/c/OP_AGET_OBJECT.c b/vm/mterp/c/OP_AGET_OBJECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_OBJECT.c
rename to vm/mterp/c/OP_AGET_OBJECT.cpp
diff --git a/vm/mterp/c/OP_AGET_SHORT.c b/vm/mterp/c/OP_AGET_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_SHORT.c
rename to vm/mterp/c/OP_AGET_SHORT.cpp
diff --git a/vm/mterp/c/OP_AGET_WIDE.c b/vm/mterp/c/OP_AGET_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_AGET_WIDE.c
rename to vm/mterp/c/OP_AGET_WIDE.cpp
diff --git a/vm/mterp/c/OP_AND_INT.c b/vm/mterp/c/OP_AND_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_INT.c
rename to vm/mterp/c/OP_AND_INT.cpp
diff --git a/vm/mterp/c/OP_AND_INT_2ADDR.c b/vm/mterp/c/OP_AND_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_INT_2ADDR.c
rename to vm/mterp/c/OP_AND_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_AND_INT_LIT16.c b/vm/mterp/c/OP_AND_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_INT_LIT16.c
rename to vm/mterp/c/OP_AND_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_AND_INT_LIT8.c b/vm/mterp/c/OP_AND_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_INT_LIT8.c
rename to vm/mterp/c/OP_AND_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_AND_LONG.c b/vm/mterp/c/OP_AND_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_LONG.c
rename to vm/mterp/c/OP_AND_LONG.cpp
diff --git a/vm/mterp/c/OP_AND_LONG_2ADDR.c b/vm/mterp/c/OP_AND_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_AND_LONG_2ADDR.c
rename to vm/mterp/c/OP_AND_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_APUT.c b/vm/mterp/c/OP_APUT.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT.c
rename to vm/mterp/c/OP_APUT.cpp
diff --git a/vm/mterp/c/OP_APUT_BOOLEAN.c b/vm/mterp/c/OP_APUT_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT_BOOLEAN.c
rename to vm/mterp/c/OP_APUT_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_APUT_BYTE.c b/vm/mterp/c/OP_APUT_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT_BYTE.c
rename to vm/mterp/c/OP_APUT_BYTE.cpp
diff --git a/vm/mterp/c/OP_APUT_CHAR.c b/vm/mterp/c/OP_APUT_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT_CHAR.c
rename to vm/mterp/c/OP_APUT_CHAR.cpp
diff --git a/vm/mterp/c/OP_APUT_OBJECT.c b/vm/mterp/c/OP_APUT_OBJECT.cpp
similarity index 92%
rename from vm/mterp/c/OP_APUT_OBJECT.c
rename to vm/mterp/c/OP_APUT_OBJECT.cpp
index af0dce3..253df25 100644
--- a/vm/mterp/c/OP_APUT_OBJECT.c
+++ b/vm/mterp/c/OP_APUT_OBJECT.cpp
@@ -21,11 +21,11 @@
if (obj != NULL) {
if (!checkForNull(obj))
GOTO_exceptionThrown();
- if (!dvmCanPutArrayElement(obj->clazz, arrayObj->obj.clazz)) {
+ if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) {
LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
obj->clazz->descriptor, obj,
arrayObj->obj.clazz->descriptor, arrayObj);
- dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->obj.clazz);
+ dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz);
GOTO_exceptionThrown();
}
}
diff --git a/vm/mterp/c/OP_APUT_SHORT.c b/vm/mterp/c/OP_APUT_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT_SHORT.c
rename to vm/mterp/c/OP_APUT_SHORT.cpp
diff --git a/vm/mterp/c/OP_APUT_WIDE.c b/vm/mterp/c/OP_APUT_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_APUT_WIDE.c
rename to vm/mterp/c/OP_APUT_WIDE.cpp
diff --git a/vm/mterp/c/OP_ARRAY_LENGTH.c b/vm/mterp/c/OP_ARRAY_LENGTH.cpp
similarity index 100%
rename from vm/mterp/c/OP_ARRAY_LENGTH.c
rename to vm/mterp/c/OP_ARRAY_LENGTH.cpp
diff --git a/vm/mterp/c/OP_BREAKPOINT.c b/vm/mterp/c/OP_BREAKPOINT.cpp
similarity index 100%
rename from vm/mterp/c/OP_BREAKPOINT.c
rename to vm/mterp/c/OP_BREAKPOINT.cpp
diff --git a/vm/mterp/c/OP_CHECK_CAST.c b/vm/mterp/c/OP_CHECK_CAST.cpp
similarity index 100%
rename from vm/mterp/c/OP_CHECK_CAST.c
rename to vm/mterp/c/OP_CHECK_CAST.cpp
diff --git a/vm/mterp/c/OP_CHECK_CAST_JUMBO.c b/vm/mterp/c/OP_CHECK_CAST_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_CHECK_CAST_JUMBO.c
rename to vm/mterp/c/OP_CHECK_CAST_JUMBO.cpp
diff --git a/vm/mterp/c/OP_CMPG_DOUBLE.c b/vm/mterp/c/OP_CMPG_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_CMPG_DOUBLE.c
rename to vm/mterp/c/OP_CMPG_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_CMPG_FLOAT.c b/vm/mterp/c/OP_CMPG_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_CMPG_FLOAT.c
rename to vm/mterp/c/OP_CMPG_FLOAT.cpp
diff --git a/vm/mterp/c/OP_CMPL_DOUBLE.c b/vm/mterp/c/OP_CMPL_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_CMPL_DOUBLE.c
rename to vm/mterp/c/OP_CMPL_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_CMPL_FLOAT.c b/vm/mterp/c/OP_CMPL_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_CMPL_FLOAT.c
rename to vm/mterp/c/OP_CMPL_FLOAT.cpp
diff --git a/vm/mterp/c/OP_CMP_LONG.c b/vm/mterp/c/OP_CMP_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_CMP_LONG.c
rename to vm/mterp/c/OP_CMP_LONG.cpp
diff --git a/vm/mterp/c/OP_CONST.c b/vm/mterp/c/OP_CONST.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST.c
rename to vm/mterp/c/OP_CONST.cpp
diff --git a/vm/mterp/c/OP_CONST_16.c b/vm/mterp/c/OP_CONST_16.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_16.c
rename to vm/mterp/c/OP_CONST_16.cpp
diff --git a/vm/mterp/c/OP_CONST_4.c b/vm/mterp/c/OP_CONST_4.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_4.c
rename to vm/mterp/c/OP_CONST_4.cpp
diff --git a/vm/mterp/c/OP_CONST_CLASS.c b/vm/mterp/c/OP_CONST_CLASS.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_CLASS.c
rename to vm/mterp/c/OP_CONST_CLASS.cpp
diff --git a/vm/mterp/c/OP_CONST_CLASS_JUMBO.c b/vm/mterp/c/OP_CONST_CLASS_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_CLASS_JUMBO.c
rename to vm/mterp/c/OP_CONST_CLASS_JUMBO.cpp
diff --git a/vm/mterp/c/OP_CONST_HIGH16.c b/vm/mterp/c/OP_CONST_HIGH16.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_HIGH16.c
rename to vm/mterp/c/OP_CONST_HIGH16.cpp
diff --git a/vm/mterp/c/OP_CONST_STRING.c b/vm/mterp/c/OP_CONST_STRING.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_STRING.c
rename to vm/mterp/c/OP_CONST_STRING.cpp
diff --git a/vm/mterp/c/OP_CONST_STRING_JUMBO.c b/vm/mterp/c/OP_CONST_STRING_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_STRING_JUMBO.c
rename to vm/mterp/c/OP_CONST_STRING_JUMBO.cpp
diff --git a/vm/mterp/c/OP_CONST_WIDE.c b/vm/mterp/c/OP_CONST_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_WIDE.c
rename to vm/mterp/c/OP_CONST_WIDE.cpp
diff --git a/vm/mterp/c/OP_CONST_WIDE_16.c b/vm/mterp/c/OP_CONST_WIDE_16.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_WIDE_16.c
rename to vm/mterp/c/OP_CONST_WIDE_16.cpp
diff --git a/vm/mterp/c/OP_CONST_WIDE_32.c b/vm/mterp/c/OP_CONST_WIDE_32.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_WIDE_32.c
rename to vm/mterp/c/OP_CONST_WIDE_32.cpp
diff --git a/vm/mterp/c/OP_CONST_WIDE_HIGH16.c b/vm/mterp/c/OP_CONST_WIDE_HIGH16.cpp
similarity index 100%
rename from vm/mterp/c/OP_CONST_WIDE_HIGH16.c
rename to vm/mterp/c/OP_CONST_WIDE_HIGH16.cpp
diff --git a/vm/mterp/c/OP_DISPATCH_FF.c b/vm/mterp/c/OP_DISPATCH_FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_DISPATCH_FF.c
rename to vm/mterp/c/OP_DISPATCH_FF.cpp
diff --git a/vm/mterp/c/OP_DIV_DOUBLE.c b/vm/mterp/c/OP_DIV_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_DOUBLE.c
rename to vm/mterp/c/OP_DIV_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_DIV_DOUBLE_2ADDR.c b/vm/mterp/c/OP_DIV_DOUBLE_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_DOUBLE_2ADDR.c
rename to vm/mterp/c/OP_DIV_DOUBLE_2ADDR.cpp
diff --git a/vm/mterp/c/OP_DIV_FLOAT.c b/vm/mterp/c/OP_DIV_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_FLOAT.c
rename to vm/mterp/c/OP_DIV_FLOAT.cpp
diff --git a/vm/mterp/c/OP_DIV_FLOAT_2ADDR.c b/vm/mterp/c/OP_DIV_FLOAT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_FLOAT_2ADDR.c
rename to vm/mterp/c/OP_DIV_FLOAT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_DIV_INT.c b/vm/mterp/c/OP_DIV_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_INT.c
rename to vm/mterp/c/OP_DIV_INT.cpp
diff --git a/vm/mterp/c/OP_DIV_INT_2ADDR.c b/vm/mterp/c/OP_DIV_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_INT_2ADDR.c
rename to vm/mterp/c/OP_DIV_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_DIV_INT_LIT16.c b/vm/mterp/c/OP_DIV_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_INT_LIT16.c
rename to vm/mterp/c/OP_DIV_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_DIV_INT_LIT8.c b/vm/mterp/c/OP_DIV_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_INT_LIT8.c
rename to vm/mterp/c/OP_DIV_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_DIV_LONG.c b/vm/mterp/c/OP_DIV_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_LONG.c
rename to vm/mterp/c/OP_DIV_LONG.cpp
diff --git a/vm/mterp/c/OP_DIV_LONG_2ADDR.c b/vm/mterp/c/OP_DIV_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_DIV_LONG_2ADDR.c
rename to vm/mterp/c/OP_DIV_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_DOUBLE_TO_FLOAT.c b/vm/mterp/c/OP_DOUBLE_TO_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_DOUBLE_TO_FLOAT.c
rename to vm/mterp/c/OP_DOUBLE_TO_FLOAT.cpp
diff --git a/vm/mterp/c/OP_DOUBLE_TO_INT.c b/vm/mterp/c/OP_DOUBLE_TO_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_DOUBLE_TO_INT.c
rename to vm/mterp/c/OP_DOUBLE_TO_INT.cpp
diff --git a/vm/mterp/c/OP_DOUBLE_TO_LONG.c b/vm/mterp/c/OP_DOUBLE_TO_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_DOUBLE_TO_LONG.c
rename to vm/mterp/c/OP_DOUBLE_TO_LONG.cpp
diff --git a/vm/mterp/c/OP_EXECUTE_INLINE.c b/vm/mterp/c/OP_EXECUTE_INLINE.cpp
similarity index 100%
rename from vm/mterp/c/OP_EXECUTE_INLINE.c
rename to vm/mterp/c/OP_EXECUTE_INLINE.cpp
diff --git a/vm/mterp/c/OP_EXECUTE_INLINE_RANGE.c b/vm/mterp/c/OP_EXECUTE_INLINE_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_EXECUTE_INLINE_RANGE.c
rename to vm/mterp/c/OP_EXECUTE_INLINE_RANGE.cpp
diff --git a/vm/mterp/c/OP_FILLED_NEW_ARRAY.c b/vm/mterp/c/OP_FILLED_NEW_ARRAY.cpp
similarity index 100%
rename from vm/mterp/c/OP_FILLED_NEW_ARRAY.c
rename to vm/mterp/c/OP_FILLED_NEW_ARRAY.cpp
diff --git a/vm/mterp/c/OP_FILLED_NEW_ARRAY_JUMBO.c b/vm/mterp/c/OP_FILLED_NEW_ARRAY_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_FILLED_NEW_ARRAY_JUMBO.c
rename to vm/mterp/c/OP_FILLED_NEW_ARRAY_JUMBO.cpp
diff --git a/vm/mterp/c/OP_FILLED_NEW_ARRAY_RANGE.c b/vm/mterp/c/OP_FILLED_NEW_ARRAY_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_FILLED_NEW_ARRAY_RANGE.c
rename to vm/mterp/c/OP_FILLED_NEW_ARRAY_RANGE.cpp
diff --git a/vm/mterp/c/OP_FILL_ARRAY_DATA.c b/vm/mterp/c/OP_FILL_ARRAY_DATA.cpp
similarity index 100%
rename from vm/mterp/c/OP_FILL_ARRAY_DATA.c
rename to vm/mterp/c/OP_FILL_ARRAY_DATA.cpp
diff --git a/vm/mterp/c/OP_FLOAT_TO_DOUBLE.c b/vm/mterp/c/OP_FLOAT_TO_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_FLOAT_TO_DOUBLE.c
rename to vm/mterp/c/OP_FLOAT_TO_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_FLOAT_TO_INT.c b/vm/mterp/c/OP_FLOAT_TO_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_FLOAT_TO_INT.c
rename to vm/mterp/c/OP_FLOAT_TO_INT.cpp
diff --git a/vm/mterp/c/OP_FLOAT_TO_LONG.c b/vm/mterp/c/OP_FLOAT_TO_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_FLOAT_TO_LONG.c
rename to vm/mterp/c/OP_FLOAT_TO_LONG.cpp
diff --git a/vm/mterp/c/OP_GOTO.c b/vm/mterp/c/OP_GOTO.cpp
similarity index 100%
rename from vm/mterp/c/OP_GOTO.c
rename to vm/mterp/c/OP_GOTO.cpp
diff --git a/vm/mterp/c/OP_GOTO_16.c b/vm/mterp/c/OP_GOTO_16.cpp
similarity index 100%
rename from vm/mterp/c/OP_GOTO_16.c
rename to vm/mterp/c/OP_GOTO_16.cpp
diff --git a/vm/mterp/c/OP_GOTO_32.c b/vm/mterp/c/OP_GOTO_32.cpp
similarity index 100%
rename from vm/mterp/c/OP_GOTO_32.c
rename to vm/mterp/c/OP_GOTO_32.cpp
diff --git a/vm/mterp/c/OP_IF_EQ.c b/vm/mterp/c/OP_IF_EQ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_EQ.c
rename to vm/mterp/c/OP_IF_EQ.cpp
diff --git a/vm/mterp/c/OP_IF_EQZ.c b/vm/mterp/c/OP_IF_EQZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_EQZ.c
rename to vm/mterp/c/OP_IF_EQZ.cpp
diff --git a/vm/mterp/c/OP_IF_GE.c b/vm/mterp/c/OP_IF_GE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_GE.c
rename to vm/mterp/c/OP_IF_GE.cpp
diff --git a/vm/mterp/c/OP_IF_GEZ.c b/vm/mterp/c/OP_IF_GEZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_GEZ.c
rename to vm/mterp/c/OP_IF_GEZ.cpp
diff --git a/vm/mterp/c/OP_IF_GT.c b/vm/mterp/c/OP_IF_GT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_GT.c
rename to vm/mterp/c/OP_IF_GT.cpp
diff --git a/vm/mterp/c/OP_IF_GTZ.c b/vm/mterp/c/OP_IF_GTZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_GTZ.c
rename to vm/mterp/c/OP_IF_GTZ.cpp
diff --git a/vm/mterp/c/OP_IF_LE.c b/vm/mterp/c/OP_IF_LE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_LE.c
rename to vm/mterp/c/OP_IF_LE.cpp
diff --git a/vm/mterp/c/OP_IF_LEZ.c b/vm/mterp/c/OP_IF_LEZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_LEZ.c
rename to vm/mterp/c/OP_IF_LEZ.cpp
diff --git a/vm/mterp/c/OP_IF_LT.c b/vm/mterp/c/OP_IF_LT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_LT.c
rename to vm/mterp/c/OP_IF_LT.cpp
diff --git a/vm/mterp/c/OP_IF_LTZ.c b/vm/mterp/c/OP_IF_LTZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_LTZ.c
rename to vm/mterp/c/OP_IF_LTZ.cpp
diff --git a/vm/mterp/c/OP_IF_NE.c b/vm/mterp/c/OP_IF_NE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_NE.c
rename to vm/mterp/c/OP_IF_NE.cpp
diff --git a/vm/mterp/c/OP_IF_NEZ.c b/vm/mterp/c/OP_IF_NEZ.cpp
similarity index 100%
rename from vm/mterp/c/OP_IF_NEZ.c
rename to vm/mterp/c/OP_IF_NEZ.cpp
diff --git a/vm/mterp/c/OP_IGET.c b/vm/mterp/c/OP_IGET.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET.c
rename to vm/mterp/c/OP_IGET.cpp
diff --git a/vm/mterp/c/OP_IGET_BOOLEAN.c b/vm/mterp/c/OP_IGET_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_BOOLEAN.c
rename to vm/mterp/c/OP_IGET_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_IGET_BOOLEAN_JUMBO.c b/vm/mterp/c/OP_IGET_BOOLEAN_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_BOOLEAN_JUMBO.c
rename to vm/mterp/c/OP_IGET_BOOLEAN_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_BYTE.c b/vm/mterp/c/OP_IGET_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_BYTE.c
rename to vm/mterp/c/OP_IGET_BYTE.cpp
diff --git a/vm/mterp/c/OP_IGET_BYTE_JUMBO.c b/vm/mterp/c/OP_IGET_BYTE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_BYTE_JUMBO.c
rename to vm/mterp/c/OP_IGET_BYTE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_CHAR.c b/vm/mterp/c/OP_IGET_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_CHAR.c
rename to vm/mterp/c/OP_IGET_CHAR.cpp
diff --git a/vm/mterp/c/OP_IGET_CHAR_JUMBO.c b/vm/mterp/c/OP_IGET_CHAR_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_CHAR_JUMBO.c
rename to vm/mterp/c/OP_IGET_CHAR_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_JUMBO.c b/vm/mterp/c/OP_IGET_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_JUMBO.c
rename to vm/mterp/c/OP_IGET_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_OBJECT.c b/vm/mterp/c/OP_IGET_OBJECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_OBJECT.c
rename to vm/mterp/c/OP_IGET_OBJECT.cpp
diff --git a/vm/mterp/c/OP_IGET_OBJECT_JUMBO.c b/vm/mterp/c/OP_IGET_OBJECT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_OBJECT_JUMBO.c
rename to vm/mterp/c/OP_IGET_OBJECT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_OBJECT_QUICK.c b/vm/mterp/c/OP_IGET_OBJECT_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_OBJECT_QUICK.c
rename to vm/mterp/c/OP_IGET_OBJECT_QUICK.cpp
diff --git a/vm/mterp/c/OP_IGET_OBJECT_VOLATILE.c b/vm/mterp/c/OP_IGET_OBJECT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_OBJECT_VOLATILE.c
rename to vm/mterp/c/OP_IGET_OBJECT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IGET_OBJECT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_OBJECT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_QUICK.c b/vm/mterp/c/OP_IGET_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_QUICK.c
rename to vm/mterp/c/OP_IGET_QUICK.cpp
diff --git a/vm/mterp/c/OP_IGET_SHORT.c b/vm/mterp/c/OP_IGET_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_SHORT.c
rename to vm/mterp/c/OP_IGET_SHORT.cpp
diff --git a/vm/mterp/c/OP_IGET_SHORT_JUMBO.c b/vm/mterp/c/OP_IGET_SHORT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_SHORT_JUMBO.c
rename to vm/mterp/c/OP_IGET_SHORT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_VOLATILE.c b/vm/mterp/c/OP_IGET_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_VOLATILE.c
rename to vm/mterp/c/OP_IGET_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IGET_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IGET_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IGET_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_WIDE.c b/vm/mterp/c/OP_IGET_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_WIDE.c
rename to vm/mterp/c/OP_IGET_WIDE.cpp
diff --git a/vm/mterp/c/OP_IGET_WIDE_JUMBO.c b/vm/mterp/c/OP_IGET_WIDE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_WIDE_JUMBO.c
rename to vm/mterp/c/OP_IGET_WIDE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IGET_WIDE_QUICK.c b/vm/mterp/c/OP_IGET_WIDE_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_WIDE_QUICK.c
rename to vm/mterp/c/OP_IGET_WIDE_QUICK.cpp
diff --git a/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_IGET_WIDE_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
rename to vm/mterp/c/OP_IGET_WIDE_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IGET_WIDE_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IGET_WIDE_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INSTANCE_OF.c b/vm/mterp/c/OP_INSTANCE_OF.cpp
similarity index 100%
rename from vm/mterp/c/OP_INSTANCE_OF.c
rename to vm/mterp/c/OP_INSTANCE_OF.cpp
diff --git a/vm/mterp/c/OP_INSTANCE_OF_JUMBO.c b/vm/mterp/c/OP_INSTANCE_OF_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INSTANCE_OF_JUMBO.c
rename to vm/mterp/c/OP_INSTANCE_OF_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INT_TO_BYTE.c b/vm/mterp/c/OP_INT_TO_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_BYTE.c
rename to vm/mterp/c/OP_INT_TO_BYTE.cpp
diff --git a/vm/mterp/c/OP_INT_TO_CHAR.c b/vm/mterp/c/OP_INT_TO_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_CHAR.c
rename to vm/mterp/c/OP_INT_TO_CHAR.cpp
diff --git a/vm/mterp/c/OP_INT_TO_DOUBLE.c b/vm/mterp/c/OP_INT_TO_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_DOUBLE.c
rename to vm/mterp/c/OP_INT_TO_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_INT_TO_FLOAT.c b/vm/mterp/c/OP_INT_TO_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_FLOAT.c
rename to vm/mterp/c/OP_INT_TO_FLOAT.cpp
diff --git a/vm/mterp/c/OP_INT_TO_LONG.c b/vm/mterp/c/OP_INT_TO_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_LONG.c
rename to vm/mterp/c/OP_INT_TO_LONG.cpp
diff --git a/vm/mterp/c/OP_INT_TO_SHORT.c b/vm/mterp/c/OP_INT_TO_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_INT_TO_SHORT.c
rename to vm/mterp/c/OP_INT_TO_SHORT.cpp
diff --git a/vm/mterp/c/OP_INVOKE_DIRECT.c b/vm/mterp/c/OP_INVOKE_DIRECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_DIRECT.c
rename to vm/mterp/c/OP_INVOKE_DIRECT.cpp
diff --git a/vm/mterp/c/OP_INVOKE_DIRECT_JUMBO.c b/vm/mterp/c/OP_INVOKE_DIRECT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_DIRECT_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_DIRECT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_DIRECT_RANGE.c b/vm/mterp/c/OP_INVOKE_DIRECT_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_DIRECT_RANGE.c
rename to vm/mterp/c/OP_INVOKE_DIRECT_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_INTERFACE.c b/vm/mterp/c/OP_INVOKE_INTERFACE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_INTERFACE.c
rename to vm/mterp/c/OP_INVOKE_INTERFACE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_INTERFACE_JUMBO.c b/vm/mterp/c/OP_INVOKE_INTERFACE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_INTERFACE_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_INTERFACE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_INTERFACE_RANGE.c b/vm/mterp/c/OP_INVOKE_INTERFACE_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_INTERFACE_RANGE.c
rename to vm/mterp/c/OP_INVOKE_INTERFACE_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_OBJECT_INIT_JUMBO.c b/vm/mterp/c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_OBJECT_INIT_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_OBJECT_INIT_RANGE.c b/vm/mterp/c/OP_INVOKE_OBJECT_INIT_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_OBJECT_INIT_RANGE.c
rename to vm/mterp/c/OP_INVOKE_OBJECT_INIT_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_STATIC.c b/vm/mterp/c/OP_INVOKE_STATIC.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_STATIC.c
rename to vm/mterp/c/OP_INVOKE_STATIC.cpp
diff --git a/vm/mterp/c/OP_INVOKE_STATIC_JUMBO.c b/vm/mterp/c/OP_INVOKE_STATIC_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_STATIC_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_STATIC_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_STATIC_RANGE.c b/vm/mterp/c/OP_INVOKE_STATIC_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_STATIC_RANGE.c
rename to vm/mterp/c/OP_INVOKE_STATIC_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_SUPER.c b/vm/mterp/c/OP_INVOKE_SUPER.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_SUPER.c
rename to vm/mterp/c/OP_INVOKE_SUPER.cpp
diff --git a/vm/mterp/c/OP_INVOKE_SUPER_JUMBO.c b/vm/mterp/c/OP_INVOKE_SUPER_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_SUPER_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_SUPER_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_SUPER_QUICK.c b/vm/mterp/c/OP_INVOKE_SUPER_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_SUPER_QUICK.c
rename to vm/mterp/c/OP_INVOKE_SUPER_QUICK.cpp
diff --git a/vm/mterp/c/OP_INVOKE_SUPER_QUICK_RANGE.c b/vm/mterp/c/OP_INVOKE_SUPER_QUICK_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_SUPER_QUICK_RANGE.c
rename to vm/mterp/c/OP_INVOKE_SUPER_QUICK_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_SUPER_RANGE.c b/vm/mterp/c/OP_INVOKE_SUPER_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_SUPER_RANGE.c
rename to vm/mterp/c/OP_INVOKE_SUPER_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_VIRTUAL.c b/vm/mterp/c/OP_INVOKE_VIRTUAL.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_VIRTUAL.c
rename to vm/mterp/c/OP_INVOKE_VIRTUAL.cpp
diff --git a/vm/mterp/c/OP_INVOKE_VIRTUAL_JUMBO.c b/vm/mterp/c/OP_INVOKE_VIRTUAL_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_VIRTUAL_JUMBO.c
rename to vm/mterp/c/OP_INVOKE_VIRTUAL_JUMBO.cpp
diff --git a/vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK.c b/vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK.c
rename to vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK.cpp
diff --git a/vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c b/vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c
rename to vm/mterp/c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp
diff --git a/vm/mterp/c/OP_INVOKE_VIRTUAL_RANGE.c b/vm/mterp/c/OP_INVOKE_VIRTUAL_RANGE.cpp
similarity index 100%
rename from vm/mterp/c/OP_INVOKE_VIRTUAL_RANGE.c
rename to vm/mterp/c/OP_INVOKE_VIRTUAL_RANGE.cpp
diff --git a/vm/mterp/c/OP_IPUT.c b/vm/mterp/c/OP_IPUT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT.c
rename to vm/mterp/c/OP_IPUT.cpp
diff --git a/vm/mterp/c/OP_IPUT_BOOLEAN.c b/vm/mterp/c/OP_IPUT_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_BOOLEAN.c
rename to vm/mterp/c/OP_IPUT_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_IPUT_BOOLEAN_JUMBO.c b/vm/mterp/c/OP_IPUT_BOOLEAN_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_BOOLEAN_JUMBO.c
rename to vm/mterp/c/OP_IPUT_BOOLEAN_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_BYTE.c b/vm/mterp/c/OP_IPUT_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_BYTE.c
rename to vm/mterp/c/OP_IPUT_BYTE.cpp
diff --git a/vm/mterp/c/OP_IPUT_BYTE_JUMBO.c b/vm/mterp/c/OP_IPUT_BYTE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_BYTE_JUMBO.c
rename to vm/mterp/c/OP_IPUT_BYTE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_CHAR.c b/vm/mterp/c/OP_IPUT_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_CHAR.c
rename to vm/mterp/c/OP_IPUT_CHAR.cpp
diff --git a/vm/mterp/c/OP_IPUT_CHAR_JUMBO.c b/vm/mterp/c/OP_IPUT_CHAR_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_CHAR_JUMBO.c
rename to vm/mterp/c/OP_IPUT_CHAR_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_JUMBO.c b/vm/mterp/c/OP_IPUT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_JUMBO.c
rename to vm/mterp/c/OP_IPUT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_OBJECT.c b/vm/mterp/c/OP_IPUT_OBJECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_OBJECT.c
rename to vm/mterp/c/OP_IPUT_OBJECT.cpp
diff --git a/vm/mterp/c/OP_IPUT_OBJECT_JUMBO.c b/vm/mterp/c/OP_IPUT_OBJECT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_OBJECT_JUMBO.c
rename to vm/mterp/c/OP_IPUT_OBJECT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_OBJECT_QUICK.c b/vm/mterp/c/OP_IPUT_OBJECT_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_OBJECT_QUICK.c
rename to vm/mterp/c/OP_IPUT_OBJECT_QUICK.cpp
diff --git a/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.c b/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.c
rename to vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_QUICK.c b/vm/mterp/c/OP_IPUT_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_QUICK.c
rename to vm/mterp/c/OP_IPUT_QUICK.cpp
diff --git a/vm/mterp/c/OP_IPUT_SHORT.c b/vm/mterp/c/OP_IPUT_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_SHORT.c
rename to vm/mterp/c/OP_IPUT_SHORT.cpp
diff --git a/vm/mterp/c/OP_IPUT_SHORT_JUMBO.c b/vm/mterp/c/OP_IPUT_SHORT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_SHORT_JUMBO.c
rename to vm/mterp/c/OP_IPUT_SHORT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_VOLATILE.c b/vm/mterp/c/OP_IPUT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_VOLATILE.c
rename to vm/mterp/c/OP_IPUT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IPUT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IPUT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IPUT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_WIDE.c b/vm/mterp/c/OP_IPUT_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_WIDE.c
rename to vm/mterp/c/OP_IPUT_WIDE.cpp
diff --git a/vm/mterp/c/OP_IPUT_WIDE_JUMBO.c b/vm/mterp/c/OP_IPUT_WIDE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_WIDE_JUMBO.c
rename to vm/mterp/c/OP_IPUT_WIDE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_IPUT_WIDE_QUICK.c b/vm/mterp/c/OP_IPUT_WIDE_QUICK.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_WIDE_QUICK.c
rename to vm/mterp/c/OP_IPUT_WIDE_QUICK.cpp
diff --git a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
rename to vm/mterp/c/OP_IPUT_WIDE_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE_JUMBO.c b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_IPUT_WIDE_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_LONG_TO_DOUBLE.c b/vm/mterp/c/OP_LONG_TO_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_LONG_TO_DOUBLE.c
rename to vm/mterp/c/OP_LONG_TO_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_LONG_TO_FLOAT.c b/vm/mterp/c/OP_LONG_TO_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_LONG_TO_FLOAT.c
rename to vm/mterp/c/OP_LONG_TO_FLOAT.cpp
diff --git a/vm/mterp/c/OP_LONG_TO_INT.c b/vm/mterp/c/OP_LONG_TO_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_LONG_TO_INT.c
rename to vm/mterp/c/OP_LONG_TO_INT.cpp
diff --git a/vm/mterp/c/OP_MONITOR_ENTER.c b/vm/mterp/c/OP_MONITOR_ENTER.cpp
similarity index 100%
rename from vm/mterp/c/OP_MONITOR_ENTER.c
rename to vm/mterp/c/OP_MONITOR_ENTER.cpp
diff --git a/vm/mterp/c/OP_MONITOR_EXIT.c b/vm/mterp/c/OP_MONITOR_EXIT.cpp
similarity index 100%
rename from vm/mterp/c/OP_MONITOR_EXIT.c
rename to vm/mterp/c/OP_MONITOR_EXIT.cpp
diff --git a/vm/mterp/c/OP_MOVE.c b/vm/mterp/c/OP_MOVE.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE.c
rename to vm/mterp/c/OP_MOVE.cpp
diff --git a/vm/mterp/c/OP_MOVE_16.c b/vm/mterp/c/OP_MOVE_16.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_16.c
rename to vm/mterp/c/OP_MOVE_16.cpp
diff --git a/vm/mterp/c/OP_MOVE_EXCEPTION.c b/vm/mterp/c/OP_MOVE_EXCEPTION.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_EXCEPTION.c
rename to vm/mterp/c/OP_MOVE_EXCEPTION.cpp
diff --git a/vm/mterp/c/OP_MOVE_FROM16.c b/vm/mterp/c/OP_MOVE_FROM16.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_FROM16.c
rename to vm/mterp/c/OP_MOVE_FROM16.cpp
diff --git a/vm/mterp/c/OP_MOVE_OBJECT.c b/vm/mterp/c/OP_MOVE_OBJECT.c
deleted file mode 100644
index 6ace6d9..0000000
--- a/vm/mterp/c/OP_MOVE_OBJECT.c
+++ /dev/null
@@ -1 +0,0 @@
-%include "c/OP_MOVE.c"
diff --git a/vm/mterp/c/OP_MOVE_OBJECT.cpp b/vm/mterp/c/OP_MOVE_OBJECT.cpp
new file mode 100644
index 0000000..579095f
--- /dev/null
+++ b/vm/mterp/c/OP_MOVE_OBJECT.cpp
@@ -0,0 +1 @@
+%include "c/OP_MOVE.cpp"
diff --git a/vm/mterp/c/OP_MOVE_OBJECT_16.c b/vm/mterp/c/OP_MOVE_OBJECT_16.c
deleted file mode 100644
index 7789ef4..0000000
--- a/vm/mterp/c/OP_MOVE_OBJECT_16.c
+++ /dev/null
@@ -1 +0,0 @@
-%include "c/OP_MOVE_16.c"
diff --git a/vm/mterp/c/OP_MOVE_OBJECT_16.cpp b/vm/mterp/c/OP_MOVE_OBJECT_16.cpp
new file mode 100644
index 0000000..89cfb77
--- /dev/null
+++ b/vm/mterp/c/OP_MOVE_OBJECT_16.cpp
@@ -0,0 +1 @@
+%include "c/OP_MOVE_16.cpp"
diff --git a/vm/mterp/c/OP_MOVE_OBJECT_FROM16.c b/vm/mterp/c/OP_MOVE_OBJECT_FROM16.c
deleted file mode 100644
index 8caf995..0000000
--- a/vm/mterp/c/OP_MOVE_OBJECT_FROM16.c
+++ /dev/null
@@ -1 +0,0 @@
-%include "c/OP_MOVE_FROM16.c"
diff --git a/vm/mterp/c/OP_MOVE_OBJECT_FROM16.cpp b/vm/mterp/c/OP_MOVE_OBJECT_FROM16.cpp
new file mode 100644
index 0000000..9451b9e
--- /dev/null
+++ b/vm/mterp/c/OP_MOVE_OBJECT_FROM16.cpp
@@ -0,0 +1 @@
+%include "c/OP_MOVE_FROM16.cpp"
diff --git a/vm/mterp/c/OP_MOVE_RESULT.c b/vm/mterp/c/OP_MOVE_RESULT.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_RESULT.c
rename to vm/mterp/c/OP_MOVE_RESULT.cpp
diff --git a/vm/mterp/c/OP_MOVE_RESULT_OBJECT.c b/vm/mterp/c/OP_MOVE_RESULT_OBJECT.c
deleted file mode 100644
index a8358b1..0000000
--- a/vm/mterp/c/OP_MOVE_RESULT_OBJECT.c
+++ /dev/null
@@ -1 +0,0 @@
-%include "c/OP_MOVE_RESULT.c"
diff --git a/vm/mterp/c/OP_MOVE_RESULT_OBJECT.cpp b/vm/mterp/c/OP_MOVE_RESULT_OBJECT.cpp
new file mode 100644
index 0000000..08c5c02
--- /dev/null
+++ b/vm/mterp/c/OP_MOVE_RESULT_OBJECT.cpp
@@ -0,0 +1 @@
+%include "c/OP_MOVE_RESULT.cpp"
diff --git a/vm/mterp/c/OP_MOVE_RESULT_WIDE.c b/vm/mterp/c/OP_MOVE_RESULT_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_RESULT_WIDE.c
rename to vm/mterp/c/OP_MOVE_RESULT_WIDE.cpp
diff --git a/vm/mterp/c/OP_MOVE_WIDE.c b/vm/mterp/c/OP_MOVE_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_WIDE.c
rename to vm/mterp/c/OP_MOVE_WIDE.cpp
diff --git a/vm/mterp/c/OP_MOVE_WIDE_16.c b/vm/mterp/c/OP_MOVE_WIDE_16.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_WIDE_16.c
rename to vm/mterp/c/OP_MOVE_WIDE_16.cpp
diff --git a/vm/mterp/c/OP_MOVE_WIDE_FROM16.c b/vm/mterp/c/OP_MOVE_WIDE_FROM16.cpp
similarity index 100%
rename from vm/mterp/c/OP_MOVE_WIDE_FROM16.c
rename to vm/mterp/c/OP_MOVE_WIDE_FROM16.cpp
diff --git a/vm/mterp/c/OP_MUL_DOUBLE.c b/vm/mterp/c/OP_MUL_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_DOUBLE.c
rename to vm/mterp/c/OP_MUL_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_MUL_DOUBLE_2ADDR.c b/vm/mterp/c/OP_MUL_DOUBLE_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_DOUBLE_2ADDR.c
rename to vm/mterp/c/OP_MUL_DOUBLE_2ADDR.cpp
diff --git a/vm/mterp/c/OP_MUL_FLOAT.c b/vm/mterp/c/OP_MUL_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_FLOAT.c
rename to vm/mterp/c/OP_MUL_FLOAT.cpp
diff --git a/vm/mterp/c/OP_MUL_FLOAT_2ADDR.c b/vm/mterp/c/OP_MUL_FLOAT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_FLOAT_2ADDR.c
rename to vm/mterp/c/OP_MUL_FLOAT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_MUL_INT.c b/vm/mterp/c/OP_MUL_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_INT.c
rename to vm/mterp/c/OP_MUL_INT.cpp
diff --git a/vm/mterp/c/OP_MUL_INT_2ADDR.c b/vm/mterp/c/OP_MUL_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_INT_2ADDR.c
rename to vm/mterp/c/OP_MUL_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_MUL_INT_LIT16.c b/vm/mterp/c/OP_MUL_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_INT_LIT16.c
rename to vm/mterp/c/OP_MUL_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_MUL_INT_LIT8.c b/vm/mterp/c/OP_MUL_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_INT_LIT8.c
rename to vm/mterp/c/OP_MUL_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_MUL_LONG.c b/vm/mterp/c/OP_MUL_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_LONG.c
rename to vm/mterp/c/OP_MUL_LONG.cpp
diff --git a/vm/mterp/c/OP_MUL_LONG_2ADDR.c b/vm/mterp/c/OP_MUL_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_MUL_LONG_2ADDR.c
rename to vm/mterp/c/OP_MUL_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_NEG_DOUBLE.c b/vm/mterp/c/OP_NEG_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEG_DOUBLE.c
rename to vm/mterp/c/OP_NEG_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_NEG_FLOAT.c b/vm/mterp/c/OP_NEG_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEG_FLOAT.c
rename to vm/mterp/c/OP_NEG_FLOAT.cpp
diff --git a/vm/mterp/c/OP_NEG_INT.c b/vm/mterp/c/OP_NEG_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEG_INT.c
rename to vm/mterp/c/OP_NEG_INT.cpp
diff --git a/vm/mterp/c/OP_NEG_LONG.c b/vm/mterp/c/OP_NEG_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEG_LONG.c
rename to vm/mterp/c/OP_NEG_LONG.cpp
diff --git a/vm/mterp/c/OP_NEW_ARRAY.c b/vm/mterp/c/OP_NEW_ARRAY.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEW_ARRAY.c
rename to vm/mterp/c/OP_NEW_ARRAY.cpp
diff --git a/vm/mterp/c/OP_NEW_ARRAY_JUMBO.c b/vm/mterp/c/OP_NEW_ARRAY_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEW_ARRAY_JUMBO.c
rename to vm/mterp/c/OP_NEW_ARRAY_JUMBO.cpp
diff --git a/vm/mterp/c/OP_NEW_INSTANCE.c b/vm/mterp/c/OP_NEW_INSTANCE.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEW_INSTANCE.c
rename to vm/mterp/c/OP_NEW_INSTANCE.cpp
diff --git a/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c b/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
rename to vm/mterp/c/OP_NEW_INSTANCE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_NOP.c b/vm/mterp/c/OP_NOP.cpp
similarity index 100%
rename from vm/mterp/c/OP_NOP.c
rename to vm/mterp/c/OP_NOP.cpp
diff --git a/vm/mterp/c/OP_NOT_INT.c b/vm/mterp/c/OP_NOT_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_NOT_INT.c
rename to vm/mterp/c/OP_NOT_INT.cpp
diff --git a/vm/mterp/c/OP_NOT_LONG.c b/vm/mterp/c/OP_NOT_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_NOT_LONG.c
rename to vm/mterp/c/OP_NOT_LONG.cpp
diff --git a/vm/mterp/c/OP_OR_INT.c b/vm/mterp/c/OP_OR_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_INT.c
rename to vm/mterp/c/OP_OR_INT.cpp
diff --git a/vm/mterp/c/OP_OR_INT_2ADDR.c b/vm/mterp/c/OP_OR_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_INT_2ADDR.c
rename to vm/mterp/c/OP_OR_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_OR_INT_LIT16.c b/vm/mterp/c/OP_OR_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_INT_LIT16.c
rename to vm/mterp/c/OP_OR_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_OR_INT_LIT8.c b/vm/mterp/c/OP_OR_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_INT_LIT8.c
rename to vm/mterp/c/OP_OR_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_OR_LONG.c b/vm/mterp/c/OP_OR_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_LONG.c
rename to vm/mterp/c/OP_OR_LONG.cpp
diff --git a/vm/mterp/c/OP_OR_LONG_2ADDR.c b/vm/mterp/c/OP_OR_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_OR_LONG_2ADDR.c
rename to vm/mterp/c/OP_OR_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_PACKED_SWITCH.c b/vm/mterp/c/OP_PACKED_SWITCH.cpp
similarity index 100%
rename from vm/mterp/c/OP_PACKED_SWITCH.c
rename to vm/mterp/c/OP_PACKED_SWITCH.cpp
diff --git a/vm/mterp/c/OP_REM_DOUBLE.c b/vm/mterp/c/OP_REM_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_DOUBLE.c
rename to vm/mterp/c/OP_REM_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_REM_DOUBLE_2ADDR.c b/vm/mterp/c/OP_REM_DOUBLE_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_DOUBLE_2ADDR.c
rename to vm/mterp/c/OP_REM_DOUBLE_2ADDR.cpp
diff --git a/vm/mterp/c/OP_REM_FLOAT.c b/vm/mterp/c/OP_REM_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_FLOAT.c
rename to vm/mterp/c/OP_REM_FLOAT.cpp
diff --git a/vm/mterp/c/OP_REM_FLOAT_2ADDR.c b/vm/mterp/c/OP_REM_FLOAT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_FLOAT_2ADDR.c
rename to vm/mterp/c/OP_REM_FLOAT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_REM_INT.c b/vm/mterp/c/OP_REM_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_INT.c
rename to vm/mterp/c/OP_REM_INT.cpp
diff --git a/vm/mterp/c/OP_REM_INT_2ADDR.c b/vm/mterp/c/OP_REM_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_INT_2ADDR.c
rename to vm/mterp/c/OP_REM_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_REM_INT_LIT16.c b/vm/mterp/c/OP_REM_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_INT_LIT16.c
rename to vm/mterp/c/OP_REM_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_REM_INT_LIT8.c b/vm/mterp/c/OP_REM_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_INT_LIT8.c
rename to vm/mterp/c/OP_REM_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_REM_LONG.c b/vm/mterp/c/OP_REM_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_LONG.c
rename to vm/mterp/c/OP_REM_LONG.cpp
diff --git a/vm/mterp/c/OP_REM_LONG_2ADDR.c b/vm/mterp/c/OP_REM_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_REM_LONG_2ADDR.c
rename to vm/mterp/c/OP_REM_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_RETURN.c b/vm/mterp/c/OP_RETURN.cpp
similarity index 100%
rename from vm/mterp/c/OP_RETURN.c
rename to vm/mterp/c/OP_RETURN.cpp
diff --git a/vm/mterp/c/OP_RETURN_OBJECT.c b/vm/mterp/c/OP_RETURN_OBJECT.c
deleted file mode 100644
index 87cca39..0000000
--- a/vm/mterp/c/OP_RETURN_OBJECT.c
+++ /dev/null
@@ -1 +0,0 @@
-%include "c/OP_RETURN.c"
diff --git a/vm/mterp/c/OP_RETURN_OBJECT.cpp b/vm/mterp/c/OP_RETURN_OBJECT.cpp
new file mode 100644
index 0000000..d8bae43
--- /dev/null
+++ b/vm/mterp/c/OP_RETURN_OBJECT.cpp
@@ -0,0 +1 @@
+%include "c/OP_RETURN.cpp"
diff --git a/vm/mterp/c/OP_RETURN_VOID.c b/vm/mterp/c/OP_RETURN_VOID.cpp
similarity index 100%
rename from vm/mterp/c/OP_RETURN_VOID.c
rename to vm/mterp/c/OP_RETURN_VOID.cpp
diff --git a/vm/mterp/c/OP_RETURN_VOID_BARRIER.c b/vm/mterp/c/OP_RETURN_VOID_BARRIER.cpp
similarity index 100%
rename from vm/mterp/c/OP_RETURN_VOID_BARRIER.c
rename to vm/mterp/c/OP_RETURN_VOID_BARRIER.cpp
diff --git a/vm/mterp/c/OP_RETURN_WIDE.c b/vm/mterp/c/OP_RETURN_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_RETURN_WIDE.c
rename to vm/mterp/c/OP_RETURN_WIDE.cpp
diff --git a/vm/mterp/c/OP_RSUB_INT.c b/vm/mterp/c/OP_RSUB_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_RSUB_INT.c
rename to vm/mterp/c/OP_RSUB_INT.cpp
diff --git a/vm/mterp/c/OP_RSUB_INT_LIT8.c b/vm/mterp/c/OP_RSUB_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_RSUB_INT_LIT8.c
rename to vm/mterp/c/OP_RSUB_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_SGET.c b/vm/mterp/c/OP_SGET.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET.c
rename to vm/mterp/c/OP_SGET.cpp
diff --git a/vm/mterp/c/OP_SGET_BOOLEAN.c b/vm/mterp/c/OP_SGET_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_BOOLEAN.c
rename to vm/mterp/c/OP_SGET_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_SGET_BOOLEAN_JUMBO.c b/vm/mterp/c/OP_SGET_BOOLEAN_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_BOOLEAN_JUMBO.c
rename to vm/mterp/c/OP_SGET_BOOLEAN_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_BYTE.c b/vm/mterp/c/OP_SGET_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_BYTE.c
rename to vm/mterp/c/OP_SGET_BYTE.cpp
diff --git a/vm/mterp/c/OP_SGET_BYTE_JUMBO.c b/vm/mterp/c/OP_SGET_BYTE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_BYTE_JUMBO.c
rename to vm/mterp/c/OP_SGET_BYTE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_CHAR.c b/vm/mterp/c/OP_SGET_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_CHAR.c
rename to vm/mterp/c/OP_SGET_CHAR.cpp
diff --git a/vm/mterp/c/OP_SGET_CHAR_JUMBO.c b/vm/mterp/c/OP_SGET_CHAR_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_CHAR_JUMBO.c
rename to vm/mterp/c/OP_SGET_CHAR_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_JUMBO.c b/vm/mterp/c/OP_SGET_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_JUMBO.c
rename to vm/mterp/c/OP_SGET_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_OBJECT.c b/vm/mterp/c/OP_SGET_OBJECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_OBJECT.c
rename to vm/mterp/c/OP_SGET_OBJECT.cpp
diff --git a/vm/mterp/c/OP_SGET_OBJECT_JUMBO.c b/vm/mterp/c/OP_SGET_OBJECT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_OBJECT_JUMBO.c
rename to vm/mterp/c/OP_SGET_OBJECT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_OBJECT_VOLATILE.c b/vm/mterp/c/OP_SGET_OBJECT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_OBJECT_VOLATILE.c
rename to vm/mterp/c/OP_SGET_OBJECT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SGET_OBJECT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_OBJECT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_SHORT.c b/vm/mterp/c/OP_SGET_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_SHORT.c
rename to vm/mterp/c/OP_SGET_SHORT.cpp
diff --git a/vm/mterp/c/OP_SGET_SHORT_JUMBO.c b/vm/mterp/c/OP_SGET_SHORT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_SHORT_JUMBO.c
rename to vm/mterp/c/OP_SGET_SHORT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_VOLATILE.c b/vm/mterp/c/OP_SGET_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_VOLATILE.c
rename to vm/mterp/c/OP_SGET_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SGET_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SGET_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SGET_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_WIDE.c b/vm/mterp/c/OP_SGET_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_WIDE.c
rename to vm/mterp/c/OP_SGET_WIDE.cpp
diff --git a/vm/mterp/c/OP_SGET_WIDE_JUMBO.c b/vm/mterp/c/OP_SGET_WIDE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_WIDE_JUMBO.c
rename to vm/mterp/c/OP_SGET_WIDE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_SGET_WIDE_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
rename to vm/mterp/c/OP_SGET_WIDE_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SGET_WIDE_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SGET_WIDE_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SHL_INT.c b/vm/mterp/c/OP_SHL_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHL_INT.c
rename to vm/mterp/c/OP_SHL_INT.cpp
diff --git a/vm/mterp/c/OP_SHL_INT_2ADDR.c b/vm/mterp/c/OP_SHL_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHL_INT_2ADDR.c
rename to vm/mterp/c/OP_SHL_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SHL_INT_LIT8.c b/vm/mterp/c/OP_SHL_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHL_INT_LIT8.c
rename to vm/mterp/c/OP_SHL_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_SHL_LONG.c b/vm/mterp/c/OP_SHL_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHL_LONG.c
rename to vm/mterp/c/OP_SHL_LONG.cpp
diff --git a/vm/mterp/c/OP_SHL_LONG_2ADDR.c b/vm/mterp/c/OP_SHL_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHL_LONG_2ADDR.c
rename to vm/mterp/c/OP_SHL_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SHR_INT.c b/vm/mterp/c/OP_SHR_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHR_INT.c
rename to vm/mterp/c/OP_SHR_INT.cpp
diff --git a/vm/mterp/c/OP_SHR_INT_2ADDR.c b/vm/mterp/c/OP_SHR_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHR_INT_2ADDR.c
rename to vm/mterp/c/OP_SHR_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SHR_INT_LIT8.c b/vm/mterp/c/OP_SHR_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHR_INT_LIT8.c
rename to vm/mterp/c/OP_SHR_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_SHR_LONG.c b/vm/mterp/c/OP_SHR_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHR_LONG.c
rename to vm/mterp/c/OP_SHR_LONG.cpp
diff --git a/vm/mterp/c/OP_SHR_LONG_2ADDR.c b/vm/mterp/c/OP_SHR_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SHR_LONG_2ADDR.c
rename to vm/mterp/c/OP_SHR_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SPARSE_SWITCH.c b/vm/mterp/c/OP_SPARSE_SWITCH.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPARSE_SWITCH.c
rename to vm/mterp/c/OP_SPARSE_SWITCH.cpp
diff --git a/vm/mterp/c/OP_SPUT.c b/vm/mterp/c/OP_SPUT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT.c
rename to vm/mterp/c/OP_SPUT.cpp
diff --git a/vm/mterp/c/OP_SPUT_BOOLEAN.c b/vm/mterp/c/OP_SPUT_BOOLEAN.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_BOOLEAN.c
rename to vm/mterp/c/OP_SPUT_BOOLEAN.cpp
diff --git a/vm/mterp/c/OP_SPUT_BOOLEAN_JUMBO.c b/vm/mterp/c/OP_SPUT_BOOLEAN_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_BOOLEAN_JUMBO.c
rename to vm/mterp/c/OP_SPUT_BOOLEAN_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_BYTE.c b/vm/mterp/c/OP_SPUT_BYTE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_BYTE.c
rename to vm/mterp/c/OP_SPUT_BYTE.cpp
diff --git a/vm/mterp/c/OP_SPUT_BYTE_JUMBO.c b/vm/mterp/c/OP_SPUT_BYTE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_BYTE_JUMBO.c
rename to vm/mterp/c/OP_SPUT_BYTE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_CHAR.c b/vm/mterp/c/OP_SPUT_CHAR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_CHAR.c
rename to vm/mterp/c/OP_SPUT_CHAR.cpp
diff --git a/vm/mterp/c/OP_SPUT_CHAR_JUMBO.c b/vm/mterp/c/OP_SPUT_CHAR_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_CHAR_JUMBO.c
rename to vm/mterp/c/OP_SPUT_CHAR_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_JUMBO.c b/vm/mterp/c/OP_SPUT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_JUMBO.c
rename to vm/mterp/c/OP_SPUT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_OBJECT.c b/vm/mterp/c/OP_SPUT_OBJECT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_OBJECT.c
rename to vm/mterp/c/OP_SPUT_OBJECT.cpp
diff --git a/vm/mterp/c/OP_SPUT_OBJECT_JUMBO.c b/vm/mterp/c/OP_SPUT_OBJECT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_OBJECT_JUMBO.c
rename to vm/mterp/c/OP_SPUT_OBJECT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.c b/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.c
rename to vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_SHORT.c b/vm/mterp/c/OP_SPUT_SHORT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_SHORT.c
rename to vm/mterp/c/OP_SPUT_SHORT.cpp
diff --git a/vm/mterp/c/OP_SPUT_SHORT_JUMBO.c b/vm/mterp/c/OP_SPUT_SHORT_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_SHORT_JUMBO.c
rename to vm/mterp/c/OP_SPUT_SHORT_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_VOLATILE.c b/vm/mterp/c/OP_SPUT_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_VOLATILE.c
rename to vm/mterp/c/OP_SPUT_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SPUT_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SPUT_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SPUT_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_WIDE.c b/vm/mterp/c/OP_SPUT_WIDE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_WIDE.c
rename to vm/mterp/c/OP_SPUT_WIDE.cpp
diff --git a/vm/mterp/c/OP_SPUT_WIDE_JUMBO.c b/vm/mterp/c/OP_SPUT_WIDE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_WIDE_JUMBO.c
rename to vm/mterp/c/OP_SPUT_WIDE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
rename to vm/mterp/c/OP_SPUT_WIDE_VOLATILE.cpp
diff --git a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE_JUMBO.c b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_SPUT_WIDE_VOLATILE_JUMBO.c
rename to vm/mterp/c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp
diff --git a/vm/mterp/c/OP_SUB_DOUBLE.c b/vm/mterp/c/OP_SUB_DOUBLE.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_DOUBLE.c
rename to vm/mterp/c/OP_SUB_DOUBLE.cpp
diff --git a/vm/mterp/c/OP_SUB_DOUBLE_2ADDR.c b/vm/mterp/c/OP_SUB_DOUBLE_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_DOUBLE_2ADDR.c
rename to vm/mterp/c/OP_SUB_DOUBLE_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SUB_FLOAT.c b/vm/mterp/c/OP_SUB_FLOAT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_FLOAT.c
rename to vm/mterp/c/OP_SUB_FLOAT.cpp
diff --git a/vm/mterp/c/OP_SUB_FLOAT_2ADDR.c b/vm/mterp/c/OP_SUB_FLOAT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_FLOAT_2ADDR.c
rename to vm/mterp/c/OP_SUB_FLOAT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SUB_INT.c b/vm/mterp/c/OP_SUB_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_INT.c
rename to vm/mterp/c/OP_SUB_INT.cpp
diff --git a/vm/mterp/c/OP_SUB_INT_2ADDR.c b/vm/mterp/c/OP_SUB_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_INT_2ADDR.c
rename to vm/mterp/c/OP_SUB_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_SUB_LONG.c b/vm/mterp/c/OP_SUB_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_LONG.c
rename to vm/mterp/c/OP_SUB_LONG.cpp
diff --git a/vm/mterp/c/OP_SUB_LONG_2ADDR.c b/vm/mterp/c/OP_SUB_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_SUB_LONG_2ADDR.c
rename to vm/mterp/c/OP_SUB_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_THROW.c b/vm/mterp/c/OP_THROW.cpp
similarity index 100%
rename from vm/mterp/c/OP_THROW.c
rename to vm/mterp/c/OP_THROW.cpp
diff --git a/vm/mterp/c/OP_THROW_VERIFICATION_ERROR.c b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR.cpp
similarity index 100%
rename from vm/mterp/c/OP_THROW_VERIFICATION_ERROR.c
rename to vm/mterp/c/OP_THROW_VERIFICATION_ERROR.cpp
diff --git a/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp
similarity index 100%
rename from vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c
rename to vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp
diff --git a/vm/mterp/c/OP_UNUSED_27FF.c b/vm/mterp/c/OP_UNUSED_27FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_27FF.c
rename to vm/mterp/c/OP_UNUSED_27FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_28FF.c b/vm/mterp/c/OP_UNUSED_28FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_28FF.c
rename to vm/mterp/c/OP_UNUSED_28FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_29FF.c b/vm/mterp/c/OP_UNUSED_29FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_29FF.c
rename to vm/mterp/c/OP_UNUSED_29FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2AFF.c b/vm/mterp/c/OP_UNUSED_2AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2AFF.c
rename to vm/mterp/c/OP_UNUSED_2AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2BFF.c b/vm/mterp/c/OP_UNUSED_2BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2BFF.c
rename to vm/mterp/c/OP_UNUSED_2BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2CFF.c b/vm/mterp/c/OP_UNUSED_2CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2CFF.c
rename to vm/mterp/c/OP_UNUSED_2CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2DFF.c b/vm/mterp/c/OP_UNUSED_2DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2DFF.c
rename to vm/mterp/c/OP_UNUSED_2DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2EFF.c b/vm/mterp/c/OP_UNUSED_2EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2EFF.c
rename to vm/mterp/c/OP_UNUSED_2EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_2FFF.c b/vm/mterp/c/OP_UNUSED_2FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_2FFF.c
rename to vm/mterp/c/OP_UNUSED_2FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_30FF.c b/vm/mterp/c/OP_UNUSED_30FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_30FF.c
rename to vm/mterp/c/OP_UNUSED_30FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_31FF.c b/vm/mterp/c/OP_UNUSED_31FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_31FF.c
rename to vm/mterp/c/OP_UNUSED_31FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_32FF.c b/vm/mterp/c/OP_UNUSED_32FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_32FF.c
rename to vm/mterp/c/OP_UNUSED_32FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_33FF.c b/vm/mterp/c/OP_UNUSED_33FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_33FF.c
rename to vm/mterp/c/OP_UNUSED_33FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_34FF.c b/vm/mterp/c/OP_UNUSED_34FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_34FF.c
rename to vm/mterp/c/OP_UNUSED_34FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_35FF.c b/vm/mterp/c/OP_UNUSED_35FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_35FF.c
rename to vm/mterp/c/OP_UNUSED_35FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_36FF.c b/vm/mterp/c/OP_UNUSED_36FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_36FF.c
rename to vm/mterp/c/OP_UNUSED_36FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_37FF.c b/vm/mterp/c/OP_UNUSED_37FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_37FF.c
rename to vm/mterp/c/OP_UNUSED_37FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_38FF.c b/vm/mterp/c/OP_UNUSED_38FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_38FF.c
rename to vm/mterp/c/OP_UNUSED_38FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_39FF.c b/vm/mterp/c/OP_UNUSED_39FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_39FF.c
rename to vm/mterp/c/OP_UNUSED_39FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3AFF.c b/vm/mterp/c/OP_UNUSED_3AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3AFF.c
rename to vm/mterp/c/OP_UNUSED_3AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3BFF.c b/vm/mterp/c/OP_UNUSED_3BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3BFF.c
rename to vm/mterp/c/OP_UNUSED_3BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3CFF.c b/vm/mterp/c/OP_UNUSED_3CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3CFF.c
rename to vm/mterp/c/OP_UNUSED_3CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3DFF.c b/vm/mterp/c/OP_UNUSED_3DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3DFF.c
rename to vm/mterp/c/OP_UNUSED_3DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3E.c b/vm/mterp/c/OP_UNUSED_3E.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3E.c
rename to vm/mterp/c/OP_UNUSED_3E.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3EFF.c b/vm/mterp/c/OP_UNUSED_3EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3EFF.c
rename to vm/mterp/c/OP_UNUSED_3EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3F.c b/vm/mterp/c/OP_UNUSED_3F.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3F.c
rename to vm/mterp/c/OP_UNUSED_3F.cpp
diff --git a/vm/mterp/c/OP_UNUSED_3FFF.c b/vm/mterp/c/OP_UNUSED_3FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_3FFF.c
rename to vm/mterp/c/OP_UNUSED_3FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_40.c b/vm/mterp/c/OP_UNUSED_40.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_40.c
rename to vm/mterp/c/OP_UNUSED_40.cpp
diff --git a/vm/mterp/c/OP_UNUSED_40FF.c b/vm/mterp/c/OP_UNUSED_40FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_40FF.c
rename to vm/mterp/c/OP_UNUSED_40FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_41.c b/vm/mterp/c/OP_UNUSED_41.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_41.c
rename to vm/mterp/c/OP_UNUSED_41.cpp
diff --git a/vm/mterp/c/OP_UNUSED_41FF.c b/vm/mterp/c/OP_UNUSED_41FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_41FF.c
rename to vm/mterp/c/OP_UNUSED_41FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_42.c b/vm/mterp/c/OP_UNUSED_42.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_42.c
rename to vm/mterp/c/OP_UNUSED_42.cpp
diff --git a/vm/mterp/c/OP_UNUSED_42FF.c b/vm/mterp/c/OP_UNUSED_42FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_42FF.c
rename to vm/mterp/c/OP_UNUSED_42FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_43.c b/vm/mterp/c/OP_UNUSED_43.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_43.c
rename to vm/mterp/c/OP_UNUSED_43.cpp
diff --git a/vm/mterp/c/OP_UNUSED_43FF.c b/vm/mterp/c/OP_UNUSED_43FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_43FF.c
rename to vm/mterp/c/OP_UNUSED_43FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_44FF.c b/vm/mterp/c/OP_UNUSED_44FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_44FF.c
rename to vm/mterp/c/OP_UNUSED_44FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_45FF.c b/vm/mterp/c/OP_UNUSED_45FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_45FF.c
rename to vm/mterp/c/OP_UNUSED_45FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_46FF.c b/vm/mterp/c/OP_UNUSED_46FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_46FF.c
rename to vm/mterp/c/OP_UNUSED_46FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_47FF.c b/vm/mterp/c/OP_UNUSED_47FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_47FF.c
rename to vm/mterp/c/OP_UNUSED_47FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_48FF.c b/vm/mterp/c/OP_UNUSED_48FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_48FF.c
rename to vm/mterp/c/OP_UNUSED_48FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_49FF.c b/vm/mterp/c/OP_UNUSED_49FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_49FF.c
rename to vm/mterp/c/OP_UNUSED_49FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4AFF.c b/vm/mterp/c/OP_UNUSED_4AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4AFF.c
rename to vm/mterp/c/OP_UNUSED_4AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4BFF.c b/vm/mterp/c/OP_UNUSED_4BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4BFF.c
rename to vm/mterp/c/OP_UNUSED_4BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4CFF.c b/vm/mterp/c/OP_UNUSED_4CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4CFF.c
rename to vm/mterp/c/OP_UNUSED_4CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4DFF.c b/vm/mterp/c/OP_UNUSED_4DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4DFF.c
rename to vm/mterp/c/OP_UNUSED_4DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4EFF.c b/vm/mterp/c/OP_UNUSED_4EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4EFF.c
rename to vm/mterp/c/OP_UNUSED_4EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_4FFF.c b/vm/mterp/c/OP_UNUSED_4FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_4FFF.c
rename to vm/mterp/c/OP_UNUSED_4FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_50FF.c b/vm/mterp/c/OP_UNUSED_50FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_50FF.c
rename to vm/mterp/c/OP_UNUSED_50FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_51FF.c b/vm/mterp/c/OP_UNUSED_51FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_51FF.c
rename to vm/mterp/c/OP_UNUSED_51FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_52FF.c b/vm/mterp/c/OP_UNUSED_52FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_52FF.c
rename to vm/mterp/c/OP_UNUSED_52FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_53FF.c b/vm/mterp/c/OP_UNUSED_53FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_53FF.c
rename to vm/mterp/c/OP_UNUSED_53FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_54FF.c b/vm/mterp/c/OP_UNUSED_54FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_54FF.c
rename to vm/mterp/c/OP_UNUSED_54FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_55FF.c b/vm/mterp/c/OP_UNUSED_55FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_55FF.c
rename to vm/mterp/c/OP_UNUSED_55FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_56FF.c b/vm/mterp/c/OP_UNUSED_56FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_56FF.c
rename to vm/mterp/c/OP_UNUSED_56FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_57FF.c b/vm/mterp/c/OP_UNUSED_57FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_57FF.c
rename to vm/mterp/c/OP_UNUSED_57FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_58FF.c b/vm/mterp/c/OP_UNUSED_58FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_58FF.c
rename to vm/mterp/c/OP_UNUSED_58FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_59FF.c b/vm/mterp/c/OP_UNUSED_59FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_59FF.c
rename to vm/mterp/c/OP_UNUSED_59FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5AFF.c b/vm/mterp/c/OP_UNUSED_5AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5AFF.c
rename to vm/mterp/c/OP_UNUSED_5AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5BFF.c b/vm/mterp/c/OP_UNUSED_5BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5BFF.c
rename to vm/mterp/c/OP_UNUSED_5BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5CFF.c b/vm/mterp/c/OP_UNUSED_5CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5CFF.c
rename to vm/mterp/c/OP_UNUSED_5CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5DFF.c b/vm/mterp/c/OP_UNUSED_5DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5DFF.c
rename to vm/mterp/c/OP_UNUSED_5DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5EFF.c b/vm/mterp/c/OP_UNUSED_5EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5EFF.c
rename to vm/mterp/c/OP_UNUSED_5EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_5FFF.c b/vm/mterp/c/OP_UNUSED_5FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_5FFF.c
rename to vm/mterp/c/OP_UNUSED_5FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_60FF.c b/vm/mterp/c/OP_UNUSED_60FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_60FF.c
rename to vm/mterp/c/OP_UNUSED_60FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_61FF.c b/vm/mterp/c/OP_UNUSED_61FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_61FF.c
rename to vm/mterp/c/OP_UNUSED_61FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_62FF.c b/vm/mterp/c/OP_UNUSED_62FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_62FF.c
rename to vm/mterp/c/OP_UNUSED_62FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_63FF.c b/vm/mterp/c/OP_UNUSED_63FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_63FF.c
rename to vm/mterp/c/OP_UNUSED_63FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_64FF.c b/vm/mterp/c/OP_UNUSED_64FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_64FF.c
rename to vm/mterp/c/OP_UNUSED_64FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_65FF.c b/vm/mterp/c/OP_UNUSED_65FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_65FF.c
rename to vm/mterp/c/OP_UNUSED_65FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_66FF.c b/vm/mterp/c/OP_UNUSED_66FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_66FF.c
rename to vm/mterp/c/OP_UNUSED_66FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_67FF.c b/vm/mterp/c/OP_UNUSED_67FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_67FF.c
rename to vm/mterp/c/OP_UNUSED_67FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_68FF.c b/vm/mterp/c/OP_UNUSED_68FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_68FF.c
rename to vm/mterp/c/OP_UNUSED_68FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_69FF.c b/vm/mterp/c/OP_UNUSED_69FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_69FF.c
rename to vm/mterp/c/OP_UNUSED_69FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6AFF.c b/vm/mterp/c/OP_UNUSED_6AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6AFF.c
rename to vm/mterp/c/OP_UNUSED_6AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6BFF.c b/vm/mterp/c/OP_UNUSED_6BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6BFF.c
rename to vm/mterp/c/OP_UNUSED_6BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6CFF.c b/vm/mterp/c/OP_UNUSED_6CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6CFF.c
rename to vm/mterp/c/OP_UNUSED_6CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6DFF.c b/vm/mterp/c/OP_UNUSED_6DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6DFF.c
rename to vm/mterp/c/OP_UNUSED_6DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6EFF.c b/vm/mterp/c/OP_UNUSED_6EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6EFF.c
rename to vm/mterp/c/OP_UNUSED_6EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_6FFF.c b/vm/mterp/c/OP_UNUSED_6FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_6FFF.c
rename to vm/mterp/c/OP_UNUSED_6FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_70FF.c b/vm/mterp/c/OP_UNUSED_70FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_70FF.c
rename to vm/mterp/c/OP_UNUSED_70FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_71FF.c b/vm/mterp/c/OP_UNUSED_71FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_71FF.c
rename to vm/mterp/c/OP_UNUSED_71FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_72FF.c b/vm/mterp/c/OP_UNUSED_72FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_72FF.c
rename to vm/mterp/c/OP_UNUSED_72FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_73.c b/vm/mterp/c/OP_UNUSED_73.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_73.c
rename to vm/mterp/c/OP_UNUSED_73.cpp
diff --git a/vm/mterp/c/OP_UNUSED_73FF.c b/vm/mterp/c/OP_UNUSED_73FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_73FF.c
rename to vm/mterp/c/OP_UNUSED_73FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_74FF.c b/vm/mterp/c/OP_UNUSED_74FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_74FF.c
rename to vm/mterp/c/OP_UNUSED_74FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_75FF.c b/vm/mterp/c/OP_UNUSED_75FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_75FF.c
rename to vm/mterp/c/OP_UNUSED_75FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_76FF.c b/vm/mterp/c/OP_UNUSED_76FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_76FF.c
rename to vm/mterp/c/OP_UNUSED_76FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_77FF.c b/vm/mterp/c/OP_UNUSED_77FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_77FF.c
rename to vm/mterp/c/OP_UNUSED_77FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_78FF.c b/vm/mterp/c/OP_UNUSED_78FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_78FF.c
rename to vm/mterp/c/OP_UNUSED_78FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_79.c b/vm/mterp/c/OP_UNUSED_79.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_79.c
rename to vm/mterp/c/OP_UNUSED_79.cpp
diff --git a/vm/mterp/c/OP_UNUSED_79FF.c b/vm/mterp/c/OP_UNUSED_79FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_79FF.c
rename to vm/mterp/c/OP_UNUSED_79FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7A.c b/vm/mterp/c/OP_UNUSED_7A.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7A.c
rename to vm/mterp/c/OP_UNUSED_7A.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7AFF.c b/vm/mterp/c/OP_UNUSED_7AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7AFF.c
rename to vm/mterp/c/OP_UNUSED_7AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7BFF.c b/vm/mterp/c/OP_UNUSED_7BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7BFF.c
rename to vm/mterp/c/OP_UNUSED_7BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7CFF.c b/vm/mterp/c/OP_UNUSED_7CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7CFF.c
rename to vm/mterp/c/OP_UNUSED_7CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7DFF.c b/vm/mterp/c/OP_UNUSED_7DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7DFF.c
rename to vm/mterp/c/OP_UNUSED_7DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7EFF.c b/vm/mterp/c/OP_UNUSED_7EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7EFF.c
rename to vm/mterp/c/OP_UNUSED_7EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_7FFF.c b/vm/mterp/c/OP_UNUSED_7FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_7FFF.c
rename to vm/mterp/c/OP_UNUSED_7FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_80FF.c b/vm/mterp/c/OP_UNUSED_80FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_80FF.c
rename to vm/mterp/c/OP_UNUSED_80FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_81FF.c b/vm/mterp/c/OP_UNUSED_81FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_81FF.c
rename to vm/mterp/c/OP_UNUSED_81FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_82FF.c b/vm/mterp/c/OP_UNUSED_82FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_82FF.c
rename to vm/mterp/c/OP_UNUSED_82FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_83FF.c b/vm/mterp/c/OP_UNUSED_83FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_83FF.c
rename to vm/mterp/c/OP_UNUSED_83FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_84FF.c b/vm/mterp/c/OP_UNUSED_84FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_84FF.c
rename to vm/mterp/c/OP_UNUSED_84FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_85FF.c b/vm/mterp/c/OP_UNUSED_85FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_85FF.c
rename to vm/mterp/c/OP_UNUSED_85FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_86FF.c b/vm/mterp/c/OP_UNUSED_86FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_86FF.c
rename to vm/mterp/c/OP_UNUSED_86FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_87FF.c b/vm/mterp/c/OP_UNUSED_87FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_87FF.c
rename to vm/mterp/c/OP_UNUSED_87FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_88FF.c b/vm/mterp/c/OP_UNUSED_88FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_88FF.c
rename to vm/mterp/c/OP_UNUSED_88FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_89FF.c b/vm/mterp/c/OP_UNUSED_89FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_89FF.c
rename to vm/mterp/c/OP_UNUSED_89FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8AFF.c b/vm/mterp/c/OP_UNUSED_8AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8AFF.c
rename to vm/mterp/c/OP_UNUSED_8AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8BFF.c b/vm/mterp/c/OP_UNUSED_8BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8BFF.c
rename to vm/mterp/c/OP_UNUSED_8BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8CFF.c b/vm/mterp/c/OP_UNUSED_8CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8CFF.c
rename to vm/mterp/c/OP_UNUSED_8CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8DFF.c b/vm/mterp/c/OP_UNUSED_8DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8DFF.c
rename to vm/mterp/c/OP_UNUSED_8DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8EFF.c b/vm/mterp/c/OP_UNUSED_8EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8EFF.c
rename to vm/mterp/c/OP_UNUSED_8EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_8FFF.c b/vm/mterp/c/OP_UNUSED_8FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_8FFF.c
rename to vm/mterp/c/OP_UNUSED_8FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_90FF.c b/vm/mterp/c/OP_UNUSED_90FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_90FF.c
rename to vm/mterp/c/OP_UNUSED_90FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_91FF.c b/vm/mterp/c/OP_UNUSED_91FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_91FF.c
rename to vm/mterp/c/OP_UNUSED_91FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_92FF.c b/vm/mterp/c/OP_UNUSED_92FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_92FF.c
rename to vm/mterp/c/OP_UNUSED_92FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_93FF.c b/vm/mterp/c/OP_UNUSED_93FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_93FF.c
rename to vm/mterp/c/OP_UNUSED_93FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_94FF.c b/vm/mterp/c/OP_UNUSED_94FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_94FF.c
rename to vm/mterp/c/OP_UNUSED_94FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_95FF.c b/vm/mterp/c/OP_UNUSED_95FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_95FF.c
rename to vm/mterp/c/OP_UNUSED_95FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_96FF.c b/vm/mterp/c/OP_UNUSED_96FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_96FF.c
rename to vm/mterp/c/OP_UNUSED_96FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_97FF.c b/vm/mterp/c/OP_UNUSED_97FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_97FF.c
rename to vm/mterp/c/OP_UNUSED_97FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_98FF.c b/vm/mterp/c/OP_UNUSED_98FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_98FF.c
rename to vm/mterp/c/OP_UNUSED_98FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_99FF.c b/vm/mterp/c/OP_UNUSED_99FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_99FF.c
rename to vm/mterp/c/OP_UNUSED_99FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9AFF.c b/vm/mterp/c/OP_UNUSED_9AFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9AFF.c
rename to vm/mterp/c/OP_UNUSED_9AFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9BFF.c b/vm/mterp/c/OP_UNUSED_9BFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9BFF.c
rename to vm/mterp/c/OP_UNUSED_9BFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9CFF.c b/vm/mterp/c/OP_UNUSED_9CFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9CFF.c
rename to vm/mterp/c/OP_UNUSED_9CFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9DFF.c b/vm/mterp/c/OP_UNUSED_9DFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9DFF.c
rename to vm/mterp/c/OP_UNUSED_9DFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9EFF.c b/vm/mterp/c/OP_UNUSED_9EFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9EFF.c
rename to vm/mterp/c/OP_UNUSED_9EFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_9FFF.c b/vm/mterp/c/OP_UNUSED_9FFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_9FFF.c
rename to vm/mterp/c/OP_UNUSED_9FFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A0FF.c b/vm/mterp/c/OP_UNUSED_A0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A0FF.c
rename to vm/mterp/c/OP_UNUSED_A0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A1FF.c b/vm/mterp/c/OP_UNUSED_A1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A1FF.c
rename to vm/mterp/c/OP_UNUSED_A1FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A2FF.c b/vm/mterp/c/OP_UNUSED_A2FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A2FF.c
rename to vm/mterp/c/OP_UNUSED_A2FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A3FF.c b/vm/mterp/c/OP_UNUSED_A3FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A3FF.c
rename to vm/mterp/c/OP_UNUSED_A3FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A4FF.c b/vm/mterp/c/OP_UNUSED_A4FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A4FF.c
rename to vm/mterp/c/OP_UNUSED_A4FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A5FF.c b/vm/mterp/c/OP_UNUSED_A5FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A5FF.c
rename to vm/mterp/c/OP_UNUSED_A5FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A6FF.c b/vm/mterp/c/OP_UNUSED_A6FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A6FF.c
rename to vm/mterp/c/OP_UNUSED_A6FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A7FF.c b/vm/mterp/c/OP_UNUSED_A7FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A7FF.c
rename to vm/mterp/c/OP_UNUSED_A7FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A8FF.c b/vm/mterp/c/OP_UNUSED_A8FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A8FF.c
rename to vm/mterp/c/OP_UNUSED_A8FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_A9FF.c b/vm/mterp/c/OP_UNUSED_A9FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_A9FF.c
rename to vm/mterp/c/OP_UNUSED_A9FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_AAFF.c b/vm/mterp/c/OP_UNUSED_AAFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_AAFF.c
rename to vm/mterp/c/OP_UNUSED_AAFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_ABFF.c b/vm/mterp/c/OP_UNUSED_ABFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_ABFF.c
rename to vm/mterp/c/OP_UNUSED_ABFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_ACFF.c b/vm/mterp/c/OP_UNUSED_ACFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_ACFF.c
rename to vm/mterp/c/OP_UNUSED_ACFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_ADFF.c b/vm/mterp/c/OP_UNUSED_ADFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_ADFF.c
rename to vm/mterp/c/OP_UNUSED_ADFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_AEFF.c b/vm/mterp/c/OP_UNUSED_AEFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_AEFF.c
rename to vm/mterp/c/OP_UNUSED_AEFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_AFFF.c b/vm/mterp/c/OP_UNUSED_AFFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_AFFF.c
rename to vm/mterp/c/OP_UNUSED_AFFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B0FF.c b/vm/mterp/c/OP_UNUSED_B0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B0FF.c
rename to vm/mterp/c/OP_UNUSED_B0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B1FF.c b/vm/mterp/c/OP_UNUSED_B1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B1FF.c
rename to vm/mterp/c/OP_UNUSED_B1FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B2FF.c b/vm/mterp/c/OP_UNUSED_B2FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B2FF.c
rename to vm/mterp/c/OP_UNUSED_B2FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B3FF.c b/vm/mterp/c/OP_UNUSED_B3FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B3FF.c
rename to vm/mterp/c/OP_UNUSED_B3FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B4FF.c b/vm/mterp/c/OP_UNUSED_B4FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B4FF.c
rename to vm/mterp/c/OP_UNUSED_B4FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B5FF.c b/vm/mterp/c/OP_UNUSED_B5FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B5FF.c
rename to vm/mterp/c/OP_UNUSED_B5FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B6FF.c b/vm/mterp/c/OP_UNUSED_B6FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B6FF.c
rename to vm/mterp/c/OP_UNUSED_B6FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B7FF.c b/vm/mterp/c/OP_UNUSED_B7FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B7FF.c
rename to vm/mterp/c/OP_UNUSED_B7FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B8FF.c b/vm/mterp/c/OP_UNUSED_B8FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B8FF.c
rename to vm/mterp/c/OP_UNUSED_B8FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_B9FF.c b/vm/mterp/c/OP_UNUSED_B9FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_B9FF.c
rename to vm/mterp/c/OP_UNUSED_B9FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BAFF.c b/vm/mterp/c/OP_UNUSED_BAFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BAFF.c
rename to vm/mterp/c/OP_UNUSED_BAFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BBFF.c b/vm/mterp/c/OP_UNUSED_BBFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BBFF.c
rename to vm/mterp/c/OP_UNUSED_BBFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BCFF.c b/vm/mterp/c/OP_UNUSED_BCFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BCFF.c
rename to vm/mterp/c/OP_UNUSED_BCFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BDFF.c b/vm/mterp/c/OP_UNUSED_BDFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BDFF.c
rename to vm/mterp/c/OP_UNUSED_BDFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BEFF.c b/vm/mterp/c/OP_UNUSED_BEFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BEFF.c
rename to vm/mterp/c/OP_UNUSED_BEFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_BFFF.c b/vm/mterp/c/OP_UNUSED_BFFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_BFFF.c
rename to vm/mterp/c/OP_UNUSED_BFFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C0FF.c b/vm/mterp/c/OP_UNUSED_C0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C0FF.c
rename to vm/mterp/c/OP_UNUSED_C0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C1FF.c b/vm/mterp/c/OP_UNUSED_C1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C1FF.c
rename to vm/mterp/c/OP_UNUSED_C1FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C2FF.c b/vm/mterp/c/OP_UNUSED_C2FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C2FF.c
rename to vm/mterp/c/OP_UNUSED_C2FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C3FF.c b/vm/mterp/c/OP_UNUSED_C3FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C3FF.c
rename to vm/mterp/c/OP_UNUSED_C3FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C4FF.c b/vm/mterp/c/OP_UNUSED_C4FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C4FF.c
rename to vm/mterp/c/OP_UNUSED_C4FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C5FF.c b/vm/mterp/c/OP_UNUSED_C5FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C5FF.c
rename to vm/mterp/c/OP_UNUSED_C5FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C6FF.c b/vm/mterp/c/OP_UNUSED_C6FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C6FF.c
rename to vm/mterp/c/OP_UNUSED_C6FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C7FF.c b/vm/mterp/c/OP_UNUSED_C7FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C7FF.c
rename to vm/mterp/c/OP_UNUSED_C7FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C8FF.c b/vm/mterp/c/OP_UNUSED_C8FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C8FF.c
rename to vm/mterp/c/OP_UNUSED_C8FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_C9FF.c b/vm/mterp/c/OP_UNUSED_C9FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_C9FF.c
rename to vm/mterp/c/OP_UNUSED_C9FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CAFF.c b/vm/mterp/c/OP_UNUSED_CAFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CAFF.c
rename to vm/mterp/c/OP_UNUSED_CAFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CBFF.c b/vm/mterp/c/OP_UNUSED_CBFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CBFF.c
rename to vm/mterp/c/OP_UNUSED_CBFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CCFF.c b/vm/mterp/c/OP_UNUSED_CCFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CCFF.c
rename to vm/mterp/c/OP_UNUSED_CCFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CDFF.c b/vm/mterp/c/OP_UNUSED_CDFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CDFF.c
rename to vm/mterp/c/OP_UNUSED_CDFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CEFF.c b/vm/mterp/c/OP_UNUSED_CEFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CEFF.c
rename to vm/mterp/c/OP_UNUSED_CEFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_CFFF.c b/vm/mterp/c/OP_UNUSED_CFFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_CFFF.c
rename to vm/mterp/c/OP_UNUSED_CFFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D0FF.c b/vm/mterp/c/OP_UNUSED_D0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D0FF.c
rename to vm/mterp/c/OP_UNUSED_D0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D1FF.c b/vm/mterp/c/OP_UNUSED_D1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D1FF.c
rename to vm/mterp/c/OP_UNUSED_D1FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D2FF.c b/vm/mterp/c/OP_UNUSED_D2FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D2FF.c
rename to vm/mterp/c/OP_UNUSED_D2FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D3FF.c b/vm/mterp/c/OP_UNUSED_D3FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D3FF.c
rename to vm/mterp/c/OP_UNUSED_D3FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D4FF.c b/vm/mterp/c/OP_UNUSED_D4FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D4FF.c
rename to vm/mterp/c/OP_UNUSED_D4FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D5FF.c b/vm/mterp/c/OP_UNUSED_D5FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D5FF.c
rename to vm/mterp/c/OP_UNUSED_D5FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D6FF.c b/vm/mterp/c/OP_UNUSED_D6FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D6FF.c
rename to vm/mterp/c/OP_UNUSED_D6FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D7FF.c b/vm/mterp/c/OP_UNUSED_D7FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D7FF.c
rename to vm/mterp/c/OP_UNUSED_D7FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D8FF.c b/vm/mterp/c/OP_UNUSED_D8FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D8FF.c
rename to vm/mterp/c/OP_UNUSED_D8FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_D9FF.c b/vm/mterp/c/OP_UNUSED_D9FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_D9FF.c
rename to vm/mterp/c/OP_UNUSED_D9FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DAFF.c b/vm/mterp/c/OP_UNUSED_DAFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DAFF.c
rename to vm/mterp/c/OP_UNUSED_DAFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DBFF.c b/vm/mterp/c/OP_UNUSED_DBFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DBFF.c
rename to vm/mterp/c/OP_UNUSED_DBFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DCFF.c b/vm/mterp/c/OP_UNUSED_DCFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DCFF.c
rename to vm/mterp/c/OP_UNUSED_DCFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DDFF.c b/vm/mterp/c/OP_UNUSED_DDFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DDFF.c
rename to vm/mterp/c/OP_UNUSED_DDFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DEFF.c b/vm/mterp/c/OP_UNUSED_DEFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DEFF.c
rename to vm/mterp/c/OP_UNUSED_DEFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_DFFF.c b/vm/mterp/c/OP_UNUSED_DFFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_DFFF.c
rename to vm/mterp/c/OP_UNUSED_DFFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E0FF.c b/vm/mterp/c/OP_UNUSED_E0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E0FF.c
rename to vm/mterp/c/OP_UNUSED_E0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E1FF.c b/vm/mterp/c/OP_UNUSED_E1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E1FF.c
rename to vm/mterp/c/OP_UNUSED_E1FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E2FF.c b/vm/mterp/c/OP_UNUSED_E2FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E2FF.c
rename to vm/mterp/c/OP_UNUSED_E2FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E3FF.c b/vm/mterp/c/OP_UNUSED_E3FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E3FF.c
rename to vm/mterp/c/OP_UNUSED_E3FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E4FF.c b/vm/mterp/c/OP_UNUSED_E4FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E4FF.c
rename to vm/mterp/c/OP_UNUSED_E4FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E5FF.c b/vm/mterp/c/OP_UNUSED_E5FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E5FF.c
rename to vm/mterp/c/OP_UNUSED_E5FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E6FF.c b/vm/mterp/c/OP_UNUSED_E6FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E6FF.c
rename to vm/mterp/c/OP_UNUSED_E6FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E7FF.c b/vm/mterp/c/OP_UNUSED_E7FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E7FF.c
rename to vm/mterp/c/OP_UNUSED_E7FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E8FF.c b/vm/mterp/c/OP_UNUSED_E8FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E8FF.c
rename to vm/mterp/c/OP_UNUSED_E8FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_E9FF.c b/vm/mterp/c/OP_UNUSED_E9FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_E9FF.c
rename to vm/mterp/c/OP_UNUSED_E9FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_EAFF.c b/vm/mterp/c/OP_UNUSED_EAFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_EAFF.c
rename to vm/mterp/c/OP_UNUSED_EAFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_EBFF.c b/vm/mterp/c/OP_UNUSED_EBFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_EBFF.c
rename to vm/mterp/c/OP_UNUSED_EBFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_ECFF.c b/vm/mterp/c/OP_UNUSED_ECFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_ECFF.c
rename to vm/mterp/c/OP_UNUSED_ECFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_EDFF.c b/vm/mterp/c/OP_UNUSED_EDFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_EDFF.c
rename to vm/mterp/c/OP_UNUSED_EDFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_EEFF.c b/vm/mterp/c/OP_UNUSED_EEFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_EEFF.c
rename to vm/mterp/c/OP_UNUSED_EEFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_EFFF.c b/vm/mterp/c/OP_UNUSED_EFFF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_EFFF.c
rename to vm/mterp/c/OP_UNUSED_EFFF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_F0FF.c b/vm/mterp/c/OP_UNUSED_F0FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_F0FF.c
rename to vm/mterp/c/OP_UNUSED_F0FF.cpp
diff --git a/vm/mterp/c/OP_UNUSED_F1FF.c b/vm/mterp/c/OP_UNUSED_F1FF.cpp
similarity index 100%
rename from vm/mterp/c/OP_UNUSED_F1FF.c
rename to vm/mterp/c/OP_UNUSED_F1FF.cpp
diff --git a/vm/mterp/c/OP_USHR_INT.c b/vm/mterp/c/OP_USHR_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_USHR_INT.c
rename to vm/mterp/c/OP_USHR_INT.cpp
diff --git a/vm/mterp/c/OP_USHR_INT_2ADDR.c b/vm/mterp/c/OP_USHR_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_USHR_INT_2ADDR.c
rename to vm/mterp/c/OP_USHR_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_USHR_INT_LIT8.c b/vm/mterp/c/OP_USHR_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_USHR_INT_LIT8.c
rename to vm/mterp/c/OP_USHR_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_USHR_LONG.c b/vm/mterp/c/OP_USHR_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_USHR_LONG.c
rename to vm/mterp/c/OP_USHR_LONG.cpp
diff --git a/vm/mterp/c/OP_USHR_LONG_2ADDR.c b/vm/mterp/c/OP_USHR_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_USHR_LONG_2ADDR.c
rename to vm/mterp/c/OP_USHR_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/OP_XOR_INT.c b/vm/mterp/c/OP_XOR_INT.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_INT.c
rename to vm/mterp/c/OP_XOR_INT.cpp
diff --git a/vm/mterp/c/OP_XOR_INT_2ADDR.c b/vm/mterp/c/OP_XOR_INT_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_INT_2ADDR.c
rename to vm/mterp/c/OP_XOR_INT_2ADDR.cpp
diff --git a/vm/mterp/c/OP_XOR_INT_LIT16.c b/vm/mterp/c/OP_XOR_INT_LIT16.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_INT_LIT16.c
rename to vm/mterp/c/OP_XOR_INT_LIT16.cpp
diff --git a/vm/mterp/c/OP_XOR_INT_LIT8.c b/vm/mterp/c/OP_XOR_INT_LIT8.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_INT_LIT8.c
rename to vm/mterp/c/OP_XOR_INT_LIT8.cpp
diff --git a/vm/mterp/c/OP_XOR_LONG.c b/vm/mterp/c/OP_XOR_LONG.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_LONG.c
rename to vm/mterp/c/OP_XOR_LONG.cpp
diff --git a/vm/mterp/c/OP_XOR_LONG_2ADDR.c b/vm/mterp/c/OP_XOR_LONG_2ADDR.cpp
similarity index 100%
rename from vm/mterp/c/OP_XOR_LONG_2ADDR.c
rename to vm/mterp/c/OP_XOR_LONG_2ADDR.cpp
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.cpp
similarity index 98%
rename from vm/mterp/c/gotoTargets.c
rename to vm/mterp/c/gotoTargets.cpp
index 50ff677..18f4c04 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.cpp
@@ -87,7 +87,7 @@
/*
* Fill in the elements. It's legal for vsrc1 to be zero.
*/
- contents = (u4*) newArray->contents;
+ contents = (u4*)(void*)newArray->contents;
if (methodCallRange) {
for (i = 0; i < vsrc1; i++)
contents[i] = GET_REGISTER(vdst+i);
@@ -106,7 +106,7 @@
dvmWriteBarrierArray(newArray, 0, newArray->length);
}
- retval.l = newArray;
+ retval.l = (Object*)newArray;
}
if (jumboFormat) {
FINISH(5);
@@ -629,7 +629,7 @@
}
/* update thread FP, and reset local variables */
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -766,10 +766,10 @@
#endif
/*
- * Adjust local variables to match self->curFrame and the
+ * Adjust local variables to match self->interpSave.curFrame and the
* updated PC.
*/
- //fp = (u4*) self->curFrame;
+ //fp = (u4*) self->interpSave.curFrame;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -948,7 +948,7 @@
* calls. For native calls, we'll mark EXIT on return.
* For non-native calls, EXIT is marked in the RETURN op.
*/
- PC_FP_TO_SELF();
+ PC_TO_SELF();
dvmReportInvoke(self, methodToCall);
}
@@ -961,7 +961,7 @@
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
- self->curFrame = fp = newFp;
+ self->interpSave.curFrame = fp = newFp;
#ifdef EASY_GDB
debugSaveArea = SAVEAREA_FROM_FP(newFp);
#endif
@@ -974,13 +974,12 @@
/* set this up for JNI locals, even if not a JNI native */
newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
- self->curFrame = newFp;
+ self->interpSave.curFrame = newFp;
DUMP_REGS(methodToCall, newFp, true); // show input args
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
+ dvmReportPreNativeInvoke(methodToCall, self, fp);
}
ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
@@ -994,13 +993,12 @@
(*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
+ dvmReportPostNativeInvoke(methodToCall, self, fp);
}
/* pop frame off */
dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* If the native code threw an exception, or interpreted code
diff --git a/vm/mterp/c/header.c b/vm/mterp/c/header.cpp
similarity index 96%
rename from vm/mterp/c/header.c
rename to vm/mterp/c/header.cpp
index 06291e2..ca025e8 100644
--- a/vm/mterp/c/header.c
+++ b/vm/mterp/c/header.cpp
@@ -67,18 +67,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
diff --git a/vm/mterp/c/opcommon.c b/vm/mterp/c/opcommon.cpp
similarity index 98%
rename from vm/mterp/c/opcommon.c
rename to vm/mterp/c/opcommon.cpp
index 1957a7f..25ea5e3 100644
--- a/vm/mterp/c/opcommon.c
+++ b/vm/mterp/c/opcommon.cpp
@@ -457,7 +457,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -482,7 +482,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -527,7 +527,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -555,7 +554,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -600,7 +598,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -628,7 +625,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -678,7 +674,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -702,7 +697,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -726,7 +720,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -750,6 +743,5 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
diff --git a/vm/mterp/common/FindInterface.h b/vm/mterp/common/FindInterface.h
index 021ed65..72d45ff 100644
--- a/vm/mterp/common/FindInterface.h
+++ b/vm/mterp/common/FindInterface.h
@@ -17,6 +17,8 @@
/* common includes */
#include "Dalvik.h"
+extern "C" {
+
/*
* Look up an interface on a class using the cache.
*
@@ -35,3 +37,5 @@
#undef ATOMIC_CACHE_CALC
}
+
+}
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index 048dcbe..f9fb928 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -11,9 +11,9 @@
* down to nothing.
*/
# define MTERP_OFFSET(_name, _type, _field, _offset) \
- if (offsetof(_type, _field) != _offset) { \
+ if (OFFSETOF_MEMBER(_type, _field) != _offset) { \
LOGE("Bad asm offset %s (%d), should be %d\n", \
- #_name, _offset, offsetof(_type, _field)); \
+ #_name, _offset, OFFSETOF_MEMBER(_type, _field)); \
failed = true; \
}
# define MTERP_SIZEOF(_name, _type, _size) \
@@ -124,21 +124,13 @@
#endif
/* InstField fields */
-#ifdef PROFILE_FIELD_ACCESS
-MTERP_OFFSET(offInstField_byteOffset, InstField, byteOffset, 24)
-#else
MTERP_OFFSET(offInstField_byteOffset, InstField, byteOffset, 16)
-#endif
/* Field fields */
MTERP_OFFSET(offField_clazz, Field, clazz, 0)
/* StaticField fields */
-#ifdef PROFILE_FIELD_ACCESS
-MTERP_OFFSET(offStaticField_value, StaticField, value, 24)
-#else
MTERP_OFFSET(offStaticField_value, StaticField, value, 16)
-#endif
/* Method fields */
MTERP_OFFSET(offMethod_clazz, Method, clazz, 0)
@@ -155,7 +147,7 @@
/* Thread fields */
MTERP_OFFSET(offThread_pc, Thread, interpSave.pc, 0)
-MTERP_OFFSET(offThread_fp, Thread, interpSave.fp, 4)
+MTERP_OFFSET(offThread_curFrame, Thread, interpSave.curFrame, 4)
MTERP_OFFSET(offThread_method, Thread, interpSave.method, 8)
MTERP_OFFSET(offThread_methodClassDex, Thread, interpSave.methodClassDex, 12)
MTERP_OFFSET(offThread_bailPtr, Thread, interpSave.bailPtr, 16)
@@ -168,48 +160,44 @@
MTERP_OFFSET(offThread_retval_j, Thread, retval.j, 32)
MTERP_OFFSET(offThread_retval_l, Thread, retval.l, 32)
//40
-MTERP_OFFSET(offThread_cardTable, Thread, cardTable, 40)
-MTERP_OFFSET(offThread_interpStackEnd, Thread, interpStackEnd, 44)
-MTERP_OFFSET(offThread_curFrame, Thread, curFrame, 48)
-MTERP_OFFSET(offThread_exception, Thread, exception, 52)
-MTERP_OFFSET(offThread_debugIsMethodEntry, Thread, debugIsMethodEntry, 56)
-MTERP_OFFSET(offThread_interpStackSize, Thread, interpStackSize, 60)
-MTERP_OFFSET(offThread_stackOverflowed, Thread, stackOverflowed, 64)
-MTERP_OFFSET(offThread_breakFlags, \
- Thread, interpBreak.ctl.breakFlags, 72)
MTERP_OFFSET(offThread_subMode, \
- Thread, interpBreak.ctl.subMode, 73)
-MTERP_OFFSET(offThread_suspendCount, \
- Thread, interpBreak.ctl.suspendCount, 74)
-MTERP_OFFSET(offThread_dbgSuspendCount, \
- Thread, interpBreak.ctl.dbgSuspendCount, 75)
+ Thread, interpBreak.ctl.subMode, 40)
+MTERP_OFFSET(offThread_breakFlags, \
+ Thread, interpBreak.ctl.breakFlags, 42)
MTERP_OFFSET(offThread_curHandlerTable, \
- Thread, interpBreak.ctl.curHandlerTable, 76)
-MTERP_OFFSET(offThread_mainHandlerTable, Thread, mainHandlerTable, 80)
-
-MTERP_OFFSET(offThread_singleStepCount, Thread, singleStepCount, 88)
+ Thread, interpBreak.ctl.curHandlerTable, 44)
+MTERP_OFFSET(offThread_suspendCount, Thread, suspendCount, 48);
+MTERP_OFFSET(offThread_dbgSuspendCount, Thread, dbgSuspendCount, 52);
+MTERP_OFFSET(offThread_cardTable, Thread, cardTable, 56)
+MTERP_OFFSET(offThread_interpStackEnd, Thread, interpStackEnd, 60)
+MTERP_OFFSET(offThread_exception, Thread, exception, 68)
+MTERP_OFFSET(offThread_debugIsMethodEntry, Thread, debugIsMethodEntry, 72)
+MTERP_OFFSET(offThread_interpStackSize, Thread, interpStackSize, 76)
+MTERP_OFFSET(offThread_stackOverflowed, Thread, stackOverflowed, 80)
+MTERP_OFFSET(offThread_mainHandlerTable, Thread, mainHandlerTable, 88)
+MTERP_OFFSET(offThread_singleStepCount, Thread, singleStepCount, 96)
#ifdef WITH_JIT
-MTERP_OFFSET(offThread_jitToInterpEntries,Thread, jitToInterpEntries, 92)
-MTERP_OFFSET(offThread_inJitCodeCache, Thread, inJitCodeCache, 116)
-MTERP_OFFSET(offThread_pJitProfTable, Thread, pJitProfTable, 120)
-MTERP_OFFSET(offThread_jitThreshold, Thread, jitThreshold, 124)
-MTERP_OFFSET(offThread_jitResumeNPC, Thread, jitResumeNPC, 128)
-MTERP_OFFSET(offThread_jitResumeNSP, Thread, jitResumeNSP, 132)
-MTERP_OFFSET(offThread_jitResumeDPC, Thread, jitResumeDPC, 136)
-MTERP_OFFSET(offThread_jitState, Thread, jitState, 140)
-MTERP_OFFSET(offThread_icRechainCount, Thread, icRechainCount, 144)
-MTERP_OFFSET(offThread_pProfileCountdown, Thread, pProfileCountdown, 148)
-MTERP_OFFSET(offThread_callsiteClass, Thread, callsiteClass, 152)
-MTERP_OFFSET(offThread_methodToCall, Thread, methodToCall, 156)
+MTERP_OFFSET(offThread_jitToInterpEntries,Thread, jitToInterpEntries, 100)
+MTERP_OFFSET(offThread_inJitCodeCache, Thread, inJitCodeCache, 124)
+MTERP_OFFSET(offThread_pJitProfTable, Thread, pJitProfTable, 128)
+MTERP_OFFSET(offThread_jitThreshold, Thread, jitThreshold, 132)
+MTERP_OFFSET(offThread_jitResumeNPC, Thread, jitResumeNPC, 136)
+MTERP_OFFSET(offThread_jitResumeNSP, Thread, jitResumeNSP, 140)
+MTERP_OFFSET(offThread_jitResumeDPC, Thread, jitResumeDPC, 144)
+MTERP_OFFSET(offThread_jitState, Thread, jitState, 148)
+MTERP_OFFSET(offThread_icRechainCount, Thread, icRechainCount, 152)
+MTERP_OFFSET(offThread_pProfileCountdown, Thread, pProfileCountdown, 156)
+MTERP_OFFSET(offThread_callsiteClass, Thread, callsiteClass, 160)
+MTERP_OFFSET(offThread_methodToCall, Thread, methodToCall, 164)
MTERP_OFFSET(offThread_jniLocal_topCookie, \
- Thread, jniLocalRefTable.segmentState.all, 160)
+ Thread, jniLocalRefTable.segmentState.all, 168)
#if defined(WITH_SELF_VERIFICATION)
-MTERP_OFFSET(offThread_shadowSpace, Thread, shadowSpace, 184)
+MTERP_OFFSET(offThread_shadowSpace, Thread, shadowSpace, 192)
#endif
#else
MTERP_OFFSET(offThread_jniLocal_topCookie, \
- Thread, jniLocalRefTable.segmentState.all, 92)
+ Thread, jniLocalRefTable.segmentState.all, 100)
#endif
/* Object fields */
@@ -257,15 +245,6 @@
MTERP_OFFSET(offClassObject_vtableCount, ClassObject, vtableCount, 112)
MTERP_OFFSET(offClassObject_vtable, ClassObject, vtable, 116)
-/* InterpEntry enumeration */
-MTERP_SIZEOF(sizeofClassStatus, InterpEntry, MTERP_SMALL_ENUM)
-MTERP_CONSTANT(kInterpEntryInstr, 0)
-MTERP_CONSTANT(kInterpEntryReturn, 1)
-MTERP_CONSTANT(kInterpEntryThrow, 2)
-#if defined(WITH_JIT)
-MTERP_CONSTANT(kInterpEntryResume, 3)
-#endif
-
#if defined(WITH_JIT)
MTERP_CONSTANT(kJitNot, 0)
MTERP_CONSTANT(kJitTSelectRequest, 1)
@@ -320,26 +299,21 @@
MTERP_CONSTANT(OP_INVOKE_DIRECT_JUMBO, 0x124)
/* flags for interpBreak */
-MTERP_CONSTANT(kSubModeNormal, 0x00)
-MTERP_CONSTANT(kSubModeMethodTrace, 0x01)
-MTERP_CONSTANT(kSubModeEmulatorTrace, 0x02)
-MTERP_CONSTANT(kSubModeInstCounting, 0x04)
-MTERP_CONSTANT(kSubModeDebuggerActive, 0x08)
-#if defined(WITH_JIT)
-MTERP_CONSTANT(kSubModeJitTraceBuild, 0x10)
-MTERP_CONSTANT(kSubModeJitSV, 0x20)
-#endif
+MTERP_CONSTANT(kSubModeNormal, 0x0000)
+MTERP_CONSTANT(kSubModeMethodTrace, 0x0001)
+MTERP_CONSTANT(kSubModeEmulatorTrace, 0x0002)
+MTERP_CONSTANT(kSubModeInstCounting, 0x0004)
+MTERP_CONSTANT(kSubModeDebuggerActive, 0x0008)
+MTERP_CONSTANT(kSubModeSuspendPending, 0x0010)
+MTERP_CONSTANT(kSubModeCallbackPending, 0x0020)
+MTERP_CONSTANT(kSubModeCountedStep, 0x0040)
+MTERP_CONSTANT(kSubModeJitTraceBuild, 0x4000)
+MTERP_CONSTANT(kSubModeJitSV, 0x8000)
+MTERP_CONSTANT(kSubModeDebugProfile, 0x000f)
MTERP_CONSTANT(kInterpNoBreak, 0x00)
-MTERP_CONSTANT(kInterpSuspendBreak, 0x01)
-MTERP_CONSTANT(kInterpInstCountBreak, 0x02)
-MTERP_CONSTANT(kInterpDebugBreak, 0x04)
-MTERP_CONSTANT(kInterpEmulatorTraceBreak, 0x08)
-MTERP_CONSTANT(kInterpSingleStep, 0x10)
-#if defined(WITH_JIT)
-MTERP_CONSTANT(kInterpJitBreak, 0x40)
-#endif
-MTERP_CONSTANT(kSubModeDebugProfile, 0x0f)
+MTERP_CONSTANT(kInterpSingleStep, 0x01)
+MTERP_CONSTANT(kInterpSafePoint, 0x02)
MTERP_CONSTANT(DBG_METHOD_ENTRY, 0x04)
MTERP_CONSTANT(DBG_METHOD_EXIT, 0x08)
diff --git a/vm/mterp/config-allstubs b/vm/mterp/config-allstubs
index a105049..9df7b12 100644
--- a/vm/mterp/config-allstubs
+++ b/vm/mterp/config-allstubs
@@ -24,13 +24,13 @@
handler-size 64
# C file header and basic definitions
-import c/header.c
+import c/header.cpp
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# common defs for the C opcodes
-import c/opcommon.c
+import c/opcommon.cpp
# opcode list; argument to op-start is default directory
op-start c
@@ -38,10 +38,10 @@
op-end
# arch-specific entry point to interpreter
-import cstubs/entry.c
+import cstubs/entry.cpp
# "helper" code
-import c/gotoTargets.c
+import c/gotoTargets.cpp
# finish
-import cstubs/enddefs.c
+import cstubs/enddefs.cpp
diff --git a/vm/mterp/config-armv5te b/vm/mterp/config-armv5te
index e00fea9..5861f8b 100644
--- a/vm/mterp/config-armv5te
+++ b/vm/mterp/config-armv5te
@@ -26,17 +26,17 @@
asm-alt-stub armv5te/alt_stub.S
# file header and basic definitions
-import c/header.c
+import c/header.cpp
import armv5te/header.S
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# highly-platform-specific defs
import armv5te/platform.S
# common defs for the C helpers; include this before the instruction handlers
-import c/opcommon.c
+import c/opcommon.cpp
# arch-specific entry point to interpreter
import armv5te/entry.S
@@ -48,11 +48,11 @@
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
-##import c/gotoTargets.c
+##import c/gotoTargets.cpp
-# end of defs; include this when cstubs/stubdefs.c is included
-import cstubs/enddefs.c
+# end of defs; include this when cstubs/stubdefs.cpp is included
+import cstubs/enddefs.cpp
# common subroutines for asm
import armv5te/footer.S
-import armv5te/debug.c
+import armv5te/debug.cpp
diff --git a/vm/mterp/config-armv5te-vfp b/vm/mterp/config-armv5te-vfp
index 70ce967..160913c 100644
--- a/vm/mterp/config-armv5te-vfp
+++ b/vm/mterp/config-armv5te-vfp
@@ -30,17 +30,17 @@
asm-alt-stub armv5te/alt_stub.S
# file header and basic definitions
-import c/header.c
+import c/header.cpp
import armv5te/header.S
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# highly-platform-specific defs
import armv5te/platform.S
# common defs for the C helpers; include this before the instruction handlers
-import c/opcommon.c
+import c/opcommon.cpp
# arch-specific entry point to interpreter
import armv5te/entry.S
@@ -98,11 +98,11 @@
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
-##import c/gotoTargets.c
+##import c/gotoTargets.cpp
-# end of defs; include this when cstubs/stubdefs.c is included
-import cstubs/enddefs.c
+# end of defs; include this when cstubs/stubdefs.cpp is included
+import cstubs/enddefs.cpp
# common subroutines for asm
import armv5te/footer.S
-import armv5te/debug.c
+import armv5te/debug.cpp
diff --git a/vm/mterp/config-armv7-a b/vm/mterp/config-armv7-a
index b9b998f..eadaeca 100644
--- a/vm/mterp/config-armv7-a
+++ b/vm/mterp/config-armv7-a
@@ -31,17 +31,17 @@
asm-alt-stub armv5te/alt_stub.S
# file header and basic definitions
-import c/header.c
+import c/header.cpp
import armv5te/header.S
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# highly-platform-specific defs
import armv7-a/platform.S
# common defs for the C helpers; include this before the instruction handlers
-import c/opcommon.c
+import c/opcommon.cpp
# arch-specific entry point to interpreter
import armv5te/entry.S
@@ -162,11 +162,11 @@
# object code, so it's normally excluded)
#
# Add this if you see linker failures for stuff like "dvmMterp_exceptionThrown".
-##import c/gotoTargets.c
+##import c/gotoTargets.cpp
-# end of defs; include this when cstubs/stubdefs.c is included
-import cstubs/enddefs.c
+# end of defs; include this when cstubs/stubdefs.cpp is included
+import cstubs/enddefs.cpp
# common subroutines for asm
import armv5te/footer.S
-import armv5te/debug.c
+import armv5te/debug.cpp
diff --git a/vm/mterp/config-armv7-a-neon b/vm/mterp/config-armv7-a-neon
index fd18f69..5f91365 100644
--- a/vm/mterp/config-armv7-a-neon
+++ b/vm/mterp/config-armv7-a-neon
@@ -31,17 +31,17 @@
asm-alt-stub armv5te/alt_stub.S
# file header and basic definitions
-import c/header.c
+import c/header.cpp
import armv5te/header.S
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# highly-platform-specific defs
import armv7-a/platform.S
# common defs for the C helpers; include this before the instruction handlers
-import c/opcommon.c
+import c/opcommon.cpp
# arch-specific entry point to interpreter
import armv5te/entry.S
@@ -160,11 +160,11 @@
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
-##import c/gotoTargets.c
+##import c/gotoTargets.cpp
-# end of defs; include this when cstubs/stubdefs.c is included
-import cstubs/enddefs.c
+# end of defs; include this when cstubs/stubdefs.cpp is included
+import cstubs/enddefs.cpp
# common subroutines for asm
import armv5te/footer.S
-import armv5te/debug.c
+import armv5te/debug.cpp
diff --git a/vm/mterp/config-portable b/vm/mterp/config-portable
index d766fee..8f696b7 100644
--- a/vm/mterp/config-portable
+++ b/vm/mterp/config-portable
@@ -19,16 +19,16 @@
handler-style all-c
# C file header and basic definitions
-import c/header.c
+import c/header.cpp
# C pre-processor defines for stub C instructions
-import portable/stubdefs.c
+import portable/stubdefs.cpp
# common defs for the C opcodes
-import c/opcommon.c
+import c/opcommon.cpp
# entry point
-import portable/entry.c
+import portable/entry.cpp
# opcode list; argument to op-start is default directory
op-start c
@@ -36,7 +36,7 @@
op-end
# "helper" code
-import c/gotoTargets.c
+import c/gotoTargets.cpp
# finish
-import portable/enddefs.c
+import portable/enddefs.cpp
diff --git a/vm/mterp/config-x86 b/vm/mterp/config-x86
index a99e5a7..cf2c7cb 100644
--- a/vm/mterp/config-x86
+++ b/vm/mterp/config-x86
@@ -25,14 +25,14 @@
asm-alt-stub x86/alt_stub.S
# C file header and basic definitions
-import c/header.c
+import c/header.cpp
import x86/header.S
# C pre-processor defines for stub C instructions
-import cstubs/stubdefs.c
+import cstubs/stubdefs.cpp
# common defs for the C opcodes
-import c/opcommon.c
+import c/opcommon.cpp
# opcode list; argument to op-start is default directory
op-start x86
@@ -66,10 +66,10 @@
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
# (asm code is currently calling into dvmMterp_exceptionThrown)
-import c/gotoTargets.c
+import c/gotoTargets.cpp
-# end of defs; include this when cstubs/stubdefs.c is included
-import cstubs/enddefs.c
+# end of defs; include this when cstubs/stubdefs.cpp is included
+import cstubs/enddefs.cpp
# common subroutines for asm
import x86/footer.S
diff --git a/vm/mterp/config-x86-atom b/vm/mterp/config-x86-atom
index 4a13d7a..b99310d 100644
--- a/vm/mterp/config-x86-atom
+++ b/vm/mterp/config-x86-atom
@@ -20,12 +20,12 @@
asm-stub x86-atom/stub.S
# file header, macros and definitions
-import c/header.c
+import c/header.cpp
import x86-atom/header.S
# common defs for the C helper; include this before the instruction handlers
-import cstubs/stubdefs.c
-import c/opcommon.c
+import cstubs/stubdefs.cpp
+import c/opcommon.cpp
# start of opcode list; command gives default directory location of instruction files
op-start x86-atom
@@ -312,8 +312,8 @@
import x86-atom/entry.S
# "helper" code for C; include this after the instruction handlers
-import c/gotoTargets.c
-import cstubs/enddefs.c
+import c/gotoTargets.cpp
+import cstubs/enddefs.cpp
# common subroutines for asm
import x86-atom/footer.S
diff --git a/vm/mterp/cstubs/enddefs.c b/vm/mterp/cstubs/enddefs.cpp
similarity index 100%
rename from vm/mterp/cstubs/enddefs.c
rename to vm/mterp/cstubs/enddefs.cpp
diff --git a/vm/mterp/cstubs/entry.c b/vm/mterp/cstubs/entry.cpp
similarity index 100%
rename from vm/mterp/cstubs/entry.c
rename to vm/mterp/cstubs/entry.cpp
diff --git a/vm/mterp/cstubs/stubdefs.c b/vm/mterp/cstubs/stubdefs.cpp
similarity index 94%
rename from vm/mterp/cstubs/stubdefs.c
rename to vm/mterp/cstubs/stubdefs.cpp
index a894f9e..2e7f1b7 100644
--- a/vm/mterp/cstubs/stubdefs.c
+++ b/vm/mterp/cstubs/stubdefs.cpp
@@ -4,7 +4,7 @@
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -20,11 +20,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -44,6 +44,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -52,6 +53,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
diff --git a/vm/mterp/gen-mterp.py b/vm/mterp/gen-mterp.py
index cf1e4e0..e0b1b2d 100755
--- a/vm/mterp/gen-mterp.py
+++ b/vm/mterp/gen-mterp.py
@@ -98,12 +98,12 @@
if len(tokens) != 2:
raise DataParseError("import requires one argument")
source = tokens[1]
- if source.endswith(".c"):
+ if source.endswith(".cpp"):
appendSourceFile(tokens[1], getGlobalSubDict(), c_fp, None)
elif source.endswith(".S"):
appendSourceFile(tokens[1], getGlobalSubDict(), asm_fp, None)
else:
- raise DataParseError("don't know how to import %s (expecting .c/.S)"
+ raise DataParseError("don't know how to import %s (expecting .cpp/.S)"
% source)
#
@@ -361,9 +361,9 @@
#
def loadAndEmitC(location, opindex):
op = opcodes[opindex]
- source = "%s/%s.c" % (location, op)
+ source = "%s/%s.cpp" % (location, op)
if verbose:
- print " emit %s --> C" % source
+ print " emit %s --> C++" % source
dict = getGlobalSubDict()
dict.update({ "opcode":op, "opnum":opindex })
@@ -536,7 +536,7 @@
# Open and prepare output files.
#
try:
- c_fp = open("%s/InterpC-%s.c" % (output_dir, target_arch), "w")
+ c_fp = open("%s/InterpC-%s.cpp" % (output_dir, target_arch), "w")
asm_fp = open("%s/InterpAsm-%s.S" % (output_dir, target_arch), "w")
except:
print "Unable to open output files"
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index d2880a4..0388a4b 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -82,8 +82,8 @@
/* save/restore the PC and/or FP from the thread struct */
#define LOAD_PC_FROM_SELF() ldr rPC, [rSELF, #offThread_pc]
#define SAVE_PC_TO_SELF() str rPC, [rSELF, #offThread_pc]
-#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_fp]
-#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_fp]
+#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_curFrame]
+#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_curFrame]
#define LOAD_PC_FP_FROM_SELF() ldmia rSELF, {rPC, rFP}
#define SAVE_PC_FP_TO_SELF() stmia rSELF, {rPC, rFP}
@@ -7298,7 +7298,7 @@
* swap if profiler/debuggger active.
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7332,7 +7332,7 @@
* us if an exception was thrown.
*/
/* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7368,7 +7368,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_RANGE_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(2+1) @ advance to next instr, load rINST
@@ -10433,7 +10433,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_JUMBO_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(4+1) @ advance to next instr, load rINST
@@ -10988,7 +10988,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_jitCheck
@@ -12116,7 +12116,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodNoRange @ no (r0=method, r9="this")
@@ -12216,7 +12216,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodRange @ no (r0=method, r9="this")
@@ -12980,7 +12980,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_JUMBO_jitCheck
@@ -14019,7 +14019,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodJumboNoThis @ no (r0=method, r9="this")
@@ -26355,10 +26355,8 @@
mov r1, #1
str r1, [rSELF,#offThread_singleStepCount] @ just step once
mov r0, rSELF
- mov r1, #kInterpSingleStep
- mov r2, #kSubModeNormal
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeCountedStep
+ bl dvmEnableSubMode @ (self, newMode)
ldr rIBASE, [rSELF,#offThread_curHandlerTable]
FETCH_INST()
GET_INST_OPCODE(ip)
@@ -26576,8 +26574,8 @@
* r2 is jit state.
*/
common_selectTrace:
- ldrb r0,[rSELF,#offThread_breakFlags]
- ands r0,#kInterpJitBreak
+ ldrh r0,[rSELF,#offThread_subMode]
+ ands r0, #(kSubModeJitTraceBuild | kSubModeJitSV)
bne 3f @ already doing JIT work, continue
str r2,[rSELF,#offThread_jitState]
mov r0, rSELF
@@ -26632,10 +26630,8 @@
beq 1f
@ Set up SV single-stepping
mov r0, rSELF
- mov r1, #kInterpJitBreak
- mov r2, #kSubModeJitSV
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeJitSV
+ bl dvmEnableSubMode @ (self, subMode)
mov r2,#kJitSelfVerification @ ask for self verification
str r2,[rSELF,#offThread_jitState]
@ intentional fallthrough
@@ -26690,7 +26686,7 @@
/* On entry: r0 is "Method* methodToCall, r9 is "this" */
.LinvokeNewJumbo:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26712,7 +26708,7 @@
common_invokeMethodRange:
.LinvokeNewRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26742,7 +26738,7 @@
common_invokeMethodNoRange:
.LinvokeNewNoRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26792,7 +26788,7 @@
ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@@ -26846,7 +26842,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
cmp r0,#0
bne common_updateProfile
GOTO_OPCODE(ip) @ jump to next instruction
@@ -26854,7 +26850,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
GOTO_OPCODE(ip) @ jump to next instruction
#endif
@@ -26862,7 +26858,6 @@
@ Profiling - record method entry. r0: methodToCall
stmfd sp!, {r0-r3} @ preserve r0-r3
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r1, r0
mov r0, rSELF
bl dvmReportInvoke @ (self, method)
@@ -26872,9 +26867,9 @@
.LinvokeNative:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFp (points to args)
@@ -26902,7 +26897,7 @@
@ equivalent to dvmPopJniLocals
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
bne common_exceptionThrown @ no, handle exception
@@ -26914,11 +26909,10 @@
11:
@ r0=newFp, r1=&retval, r2=methodToCall, r3=self, lr=subModes
stmfd sp!, {r0-r3} @ save all but subModes
- str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPreNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPreNativeInvoke @ (methodToCall, self, fp)
ldmfd sp, {r0-r3} @ refresh. NOTE: no sp autoincrement
@ Call the native method
@@ -26929,10 +26923,10 @@
ldmfd sp!, {r0-r3} @ r2<- methodToCall (others unneeded)
@ Finish up any post-invoke subMode requirements
- @ interpSave already up-to-date
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPostNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPostNativeInvoke @ (methodToCall, self, fp)
b 7b @ resume
.LstackOverflow: @ r0=methodToCall
@@ -26981,7 +26975,7 @@
*/
common_returnFromMethod:
.LreturnNew:
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r0, rFP)
ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
cmp lr, #0 @ any special subMode handling needed?
@@ -27005,7 +26999,7 @@
PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
#if defined(WITH_JIT)
ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
mov rPC, r9 @ publish new rPC
@@ -27027,7 +27021,7 @@
@ On entry, r0: StackSaveArea
ldr r1, [r0, #offStackSaveArea_prevFrame] @ r2<- prevFP
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str r1, [rSELF, #offThread_fp] @ update interpSave.fp
+ str r1, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF
bl dvmReportReturn @ (self)
SAVEAREA_FROM_FP(r0, rFP) @ restore StackSaveArea
@@ -27068,7 +27062,7 @@
mov r1, rSELF @ r1<- self
mov r0, r9 @ r0<- exception
bl dvmAddTrackedAlloc @ don't let the exception be GCed
- ldrb r2, [rSELF, #offThread_subMode] @ get subMode flags
+ ldrh r2, [rSELF, #offThread_subMode] @ get subMode flags
mov r3, #0 @ r3<- NULL
str r3, [rSELF, #offThread_exception] @ self->exception = NULL
@@ -27085,7 +27079,7 @@
ldr r1, [rSELF, #offThread_method] @ r1<- self->method
mov r0, rSELF @ r0<- self
ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
- ldrb lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
+ ldrh lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
mov r2, r9 @ r2<- exception
sub r1, rPC, r1 @ r1<- pc - method->insns
mov r1, r1, asr #1 @ r1<- offset in code units
@@ -27110,7 +27104,7 @@
add sp, sp, #8 @ restore stack
bmi .LnotCaughtLocally
- /* adjust locals to match self->curFrame and updated PC */
+ /* adjust locals to match self->interpSave.curFrame and updated PC */
SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
str r1, [rSELF, #offThread_method] @ self->method = new method
@@ -27136,7 +27130,7 @@
@ Manage debugger bookkeeping
7:
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
+ str rFP, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF @ arg0<- self
mov r1, r9 @ arg1<- exception
bl dvmReportExceptionThrow @ (self, exception)
@@ -27203,7 +27197,7 @@
* r0: field pointer (must preserve)
*/
common_verifyField:
- ldrb r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
+ ldrh r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
ands r3, #kSubModeJitTraceBuild
bxeq lr @ Not building trace, continue
ldr r1, [r10] @ r1<- reload resolved StaticField ptr
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index edb5086..b961df7 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -82,8 +82,8 @@
/* save/restore the PC and/or FP from the thread struct */
#define LOAD_PC_FROM_SELF() ldr rPC, [rSELF, #offThread_pc]
#define SAVE_PC_TO_SELF() str rPC, [rSELF, #offThread_pc]
-#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_fp]
-#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_fp]
+#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_curFrame]
+#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_curFrame]
#define LOAD_PC_FP_FROM_SELF() ldmia rSELF, {rPC, rFP}
#define SAVE_PC_FP_TO_SELF() stmia rSELF, {rPC, rFP}
@@ -7620,7 +7620,7 @@
* swap if profiler/debuggger active.
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7654,7 +7654,7 @@
* us if an exception was thrown.
*/
/* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7690,7 +7690,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_RANGE_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(2+1) @ advance to next instr, load rINST
@@ -10755,7 +10755,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_JUMBO_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(4+1) @ advance to next instr, load rINST
@@ -11310,7 +11310,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_jitCheck
@@ -12574,7 +12574,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodNoRange @ no (r0=method, r9="this")
@@ -12674,7 +12674,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodRange @ no (r0=method, r9="this")
@@ -13438,7 +13438,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_JUMBO_jitCheck
@@ -14477,7 +14477,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodJumboNoThis @ no (r0=method, r9="this")
@@ -26813,10 +26813,8 @@
mov r1, #1
str r1, [rSELF,#offThread_singleStepCount] @ just step once
mov r0, rSELF
- mov r1, #kInterpSingleStep
- mov r2, #kSubModeNormal
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeCountedStep
+ bl dvmEnableSubMode @ (self, newMode)
ldr rIBASE, [rSELF,#offThread_curHandlerTable]
FETCH_INST()
GET_INST_OPCODE(ip)
@@ -27034,8 +27032,8 @@
* r2 is jit state.
*/
common_selectTrace:
- ldrb r0,[rSELF,#offThread_breakFlags]
- ands r0,#kInterpJitBreak
+ ldrh r0,[rSELF,#offThread_subMode]
+ ands r0, #(kSubModeJitTraceBuild | kSubModeJitSV)
bne 3f @ already doing JIT work, continue
str r2,[rSELF,#offThread_jitState]
mov r0, rSELF
@@ -27090,10 +27088,8 @@
beq 1f
@ Set up SV single-stepping
mov r0, rSELF
- mov r1, #kInterpJitBreak
- mov r2, #kSubModeJitSV
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeJitSV
+ bl dvmEnableSubMode @ (self, subMode)
mov r2,#kJitSelfVerification @ ask for self verification
str r2,[rSELF,#offThread_jitState]
@ intentional fallthrough
@@ -27148,7 +27144,7 @@
/* On entry: r0 is "Method* methodToCall, r9 is "this" */
.LinvokeNewJumbo:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -27170,7 +27166,7 @@
common_invokeMethodRange:
.LinvokeNewRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -27200,7 +27196,7 @@
common_invokeMethodNoRange:
.LinvokeNewNoRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -27250,7 +27246,7 @@
ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@@ -27304,7 +27300,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
cmp r0,#0
bne common_updateProfile
GOTO_OPCODE(ip) @ jump to next instruction
@@ -27312,7 +27308,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
GOTO_OPCODE(ip) @ jump to next instruction
#endif
@@ -27320,7 +27316,6 @@
@ Profiling - record method entry. r0: methodToCall
stmfd sp!, {r0-r3} @ preserve r0-r3
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r1, r0
mov r0, rSELF
bl dvmReportInvoke @ (self, method)
@@ -27330,9 +27325,9 @@
.LinvokeNative:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFp (points to args)
@@ -27360,7 +27355,7 @@
@ equivalent to dvmPopJniLocals
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
bne common_exceptionThrown @ no, handle exception
@@ -27372,11 +27367,10 @@
11:
@ r0=newFp, r1=&retval, r2=methodToCall, r3=self, lr=subModes
stmfd sp!, {r0-r3} @ save all but subModes
- str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPreNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPreNativeInvoke @ (methodToCall, self, fp)
ldmfd sp, {r0-r3} @ refresh. NOTE: no sp autoincrement
@ Call the native method
@@ -27387,10 +27381,10 @@
ldmfd sp!, {r0-r3} @ r2<- methodToCall (others unneeded)
@ Finish up any post-invoke subMode requirements
- @ interpSave already up-to-date
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPostNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPostNativeInvoke @ (methodToCall, self, fp)
b 7b @ resume
.LstackOverflow: @ r0=methodToCall
@@ -27439,7 +27433,7 @@
*/
common_returnFromMethod:
.LreturnNew:
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r0, rFP)
ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
cmp lr, #0 @ any special subMode handling needed?
@@ -27463,7 +27457,7 @@
PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
#if defined(WITH_JIT)
ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
mov rPC, r9 @ publish new rPC
@@ -27485,7 +27479,7 @@
@ On entry, r0: StackSaveArea
ldr r1, [r0, #offStackSaveArea_prevFrame] @ r2<- prevFP
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str r1, [rSELF, #offThread_fp] @ update interpSave.fp
+ str r1, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF
bl dvmReportReturn @ (self)
SAVEAREA_FROM_FP(r0, rFP) @ restore StackSaveArea
@@ -27526,7 +27520,7 @@
mov r1, rSELF @ r1<- self
mov r0, r9 @ r0<- exception
bl dvmAddTrackedAlloc @ don't let the exception be GCed
- ldrb r2, [rSELF, #offThread_subMode] @ get subMode flags
+ ldrh r2, [rSELF, #offThread_subMode] @ get subMode flags
mov r3, #0 @ r3<- NULL
str r3, [rSELF, #offThread_exception] @ self->exception = NULL
@@ -27543,7 +27537,7 @@
ldr r1, [rSELF, #offThread_method] @ r1<- self->method
mov r0, rSELF @ r0<- self
ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
- ldrb lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
+ ldrh lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
mov r2, r9 @ r2<- exception
sub r1, rPC, r1 @ r1<- pc - method->insns
mov r1, r1, asr #1 @ r1<- offset in code units
@@ -27568,7 +27562,7 @@
add sp, sp, #8 @ restore stack
bmi .LnotCaughtLocally
- /* adjust locals to match self->curFrame and updated PC */
+ /* adjust locals to match self->interpSave.curFrame and updated PC */
SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
str r1, [rSELF, #offThread_method] @ self->method = new method
@@ -27594,7 +27588,7 @@
@ Manage debugger bookkeeping
7:
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
+ str rFP, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF @ arg0<- self
mov r1, r9 @ arg1<- exception
bl dvmReportExceptionThrow @ (self, exception)
@@ -27661,7 +27655,7 @@
* r0: field pointer (must preserve)
*/
common_verifyField:
- ldrb r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
+ ldrh r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
ands r3, #kSubModeJitTraceBuild
bxeq lr @ Not building trace, continue
ldr r1, [r10] @ r1<- reload resolved StaticField ptr
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index fa64024..c14d8c0 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -82,8 +82,8 @@
/* save/restore the PC and/or FP from the thread struct */
#define LOAD_PC_FROM_SELF() ldr rPC, [rSELF, #offThread_pc]
#define SAVE_PC_TO_SELF() str rPC, [rSELF, #offThread_pc]
-#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_fp]
-#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_fp]
+#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_curFrame]
+#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_curFrame]
#define LOAD_PC_FP_FROM_SELF() ldmia rSELF, {rPC, rFP}
#define SAVE_PC_FP_TO_SELF() stmia rSELF, {rPC, rFP}
@@ -7256,7 +7256,7 @@
* swap if profiler/debuggger active.
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7290,7 +7290,7 @@
* us if an exception was thrown.
*/
/* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7326,7 +7326,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_RANGE_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(2+1) @ advance to next instr, load rINST
@@ -10387,7 +10387,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_JUMBO_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(4+1) @ advance to next instr, load rINST
@@ -10942,7 +10942,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_jitCheck
@@ -12054,7 +12054,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodNoRange @ no (r0=method, r9="this")
@@ -12154,7 +12154,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodRange @ no (r0=method, r9="this")
@@ -12918,7 +12918,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_JUMBO_jitCheck
@@ -13957,7 +13957,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodJumboNoThis @ no (r0=method, r9="this")
@@ -26293,10 +26293,8 @@
mov r1, #1
str r1, [rSELF,#offThread_singleStepCount] @ just step once
mov r0, rSELF
- mov r1, #kInterpSingleStep
- mov r2, #kSubModeNormal
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeCountedStep
+ bl dvmEnableSubMode @ (self, newMode)
ldr rIBASE, [rSELF,#offThread_curHandlerTable]
FETCH_INST()
GET_INST_OPCODE(ip)
@@ -26514,8 +26512,8 @@
* r2 is jit state.
*/
common_selectTrace:
- ldrb r0,[rSELF,#offThread_breakFlags]
- ands r0,#kInterpJitBreak
+ ldrh r0,[rSELF,#offThread_subMode]
+ ands r0, #(kSubModeJitTraceBuild | kSubModeJitSV)
bne 3f @ already doing JIT work, continue
str r2,[rSELF,#offThread_jitState]
mov r0, rSELF
@@ -26570,10 +26568,8 @@
beq 1f
@ Set up SV single-stepping
mov r0, rSELF
- mov r1, #kInterpJitBreak
- mov r2, #kSubModeJitSV
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeJitSV
+ bl dvmEnableSubMode @ (self, subMode)
mov r2,#kJitSelfVerification @ ask for self verification
str r2,[rSELF,#offThread_jitState]
@ intentional fallthrough
@@ -26628,7 +26624,7 @@
/* On entry: r0 is "Method* methodToCall, r9 is "this" */
.LinvokeNewJumbo:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26650,7 +26646,7 @@
common_invokeMethodRange:
.LinvokeNewRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26680,7 +26676,7 @@
common_invokeMethodNoRange:
.LinvokeNewNoRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26730,7 +26726,7 @@
ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@@ -26784,7 +26780,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
cmp r0,#0
bne common_updateProfile
GOTO_OPCODE(ip) @ jump to next instruction
@@ -26792,7 +26788,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
GOTO_OPCODE(ip) @ jump to next instruction
#endif
@@ -26800,7 +26796,6 @@
@ Profiling - record method entry. r0: methodToCall
stmfd sp!, {r0-r3} @ preserve r0-r3
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r1, r0
mov r0, rSELF
bl dvmReportInvoke @ (self, method)
@@ -26810,9 +26805,9 @@
.LinvokeNative:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFp (points to args)
@@ -26840,7 +26835,7 @@
@ equivalent to dvmPopJniLocals
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
bne common_exceptionThrown @ no, handle exception
@@ -26852,11 +26847,10 @@
11:
@ r0=newFp, r1=&retval, r2=methodToCall, r3=self, lr=subModes
stmfd sp!, {r0-r3} @ save all but subModes
- str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPreNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPreNativeInvoke @ (methodToCall, self, fp)
ldmfd sp, {r0-r3} @ refresh. NOTE: no sp autoincrement
@ Call the native method
@@ -26867,10 +26861,10 @@
ldmfd sp!, {r0-r3} @ r2<- methodToCall (others unneeded)
@ Finish up any post-invoke subMode requirements
- @ interpSave already up-to-date
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPostNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPostNativeInvoke @ (methodToCall, self, fp)
b 7b @ resume
.LstackOverflow: @ r0=methodToCall
@@ -26919,7 +26913,7 @@
*/
common_returnFromMethod:
.LreturnNew:
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r0, rFP)
ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
cmp lr, #0 @ any special subMode handling needed?
@@ -26943,7 +26937,7 @@
PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
#if defined(WITH_JIT)
ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
mov rPC, r9 @ publish new rPC
@@ -26965,7 +26959,7 @@
@ On entry, r0: StackSaveArea
ldr r1, [r0, #offStackSaveArea_prevFrame] @ r2<- prevFP
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str r1, [rSELF, #offThread_fp] @ update interpSave.fp
+ str r1, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF
bl dvmReportReturn @ (self)
SAVEAREA_FROM_FP(r0, rFP) @ restore StackSaveArea
@@ -27006,7 +27000,7 @@
mov r1, rSELF @ r1<- self
mov r0, r9 @ r0<- exception
bl dvmAddTrackedAlloc @ don't let the exception be GCed
- ldrb r2, [rSELF, #offThread_subMode] @ get subMode flags
+ ldrh r2, [rSELF, #offThread_subMode] @ get subMode flags
mov r3, #0 @ r3<- NULL
str r3, [rSELF, #offThread_exception] @ self->exception = NULL
@@ -27023,7 +27017,7 @@
ldr r1, [rSELF, #offThread_method] @ r1<- self->method
mov r0, rSELF @ r0<- self
ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
- ldrb lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
+ ldrh lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
mov r2, r9 @ r2<- exception
sub r1, rPC, r1 @ r1<- pc - method->insns
mov r1, r1, asr #1 @ r1<- offset in code units
@@ -27048,7 +27042,7 @@
add sp, sp, #8 @ restore stack
bmi .LnotCaughtLocally
- /* adjust locals to match self->curFrame and updated PC */
+ /* adjust locals to match self->interpSave.curFrame and updated PC */
SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
str r1, [rSELF, #offThread_method] @ self->method = new method
@@ -27074,7 +27068,7 @@
@ Manage debugger bookkeeping
7:
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
+ str rFP, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF @ arg0<- self
mov r1, r9 @ arg1<- exception
bl dvmReportExceptionThrow @ (self, exception)
@@ -27141,7 +27135,7 @@
* r0: field pointer (must preserve)
*/
common_verifyField:
- ldrb r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
+ ldrh r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
ands r3, #kSubModeJitTraceBuild
bxeq lr @ Not building trace, continue
ldr r1, [r10] @ r1<- reload resolved StaticField ptr
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 4f9b974..3ce4b8d 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -82,8 +82,8 @@
/* save/restore the PC and/or FP from the thread struct */
#define LOAD_PC_FROM_SELF() ldr rPC, [rSELF, #offThread_pc]
#define SAVE_PC_TO_SELF() str rPC, [rSELF, #offThread_pc]
-#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_fp]
-#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_fp]
+#define LOAD_FP_FROM_SELF() ldr rFP, [rSELF, #offThread_curFrame]
+#define SAVE_FP_TO_SELF() str rFP, [rSELF, #offThread_curFrame]
#define LOAD_PC_FP_FROM_SELF() ldmia rSELF, {rPC, rFP}
#define SAVE_PC_FP_TO_SELF() stmia rSELF, {rPC, rFP}
@@ -7256,7 +7256,7 @@
* swap if profiler/debuggger active.
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7290,7 +7290,7 @@
* us if an exception was thrown.
*/
/* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
FETCH(r10, 1) @ r10<- BBBB
EXPORT_PC() @ can throw
ands r2, #kSubModeDebugProfile @ Any going on?
@@ -7326,7 +7326,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_RANGE_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_RANGE_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(2+1) @ advance to next instr, load rINST
@@ -10387,7 +10387,7 @@
tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_setFinal @ yes, go
.LOP_INVOKE_OBJECT_INIT_JUMBO_finish:
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeDebuggerActive @ debugger active?
bne .LOP_INVOKE_OBJECT_INIT_JUMBO_debugger @ Yes - skip optimization
FETCH_ADVANCE_INST(4+1) @ advance to next instr, load rINST
@@ -10942,7 +10942,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_jitCheck
@@ -12054,7 +12054,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodNoRange @ no (r0=method, r9="this")
@@ -12154,7 +12154,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodRange @ no (r0=method, r9="this")
@@ -12918,7 +12918,7 @@
* The JIT needs the class to be fully resolved before it can
* include this instruction in a trace.
*/
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ yes, handle the exception
ands r1, #kSubModeJitTraceBuild @ under construction?
bne .LOP_NEW_INSTANCE_JUMBO_jitCheck
@@ -13957,7 +13957,7 @@
* we need to keep this instruction out of it.
* r10: &resolved_methodToCall
*/
- ldrb r2, [rSELF, #offThread_subMode]
+ ldrh r2, [rSELF, #offThread_subMode]
beq common_exceptionThrown @ null, handle exception
ands r2, #kSubModeJitTraceBuild @ trace under construction?
beq common_invokeMethodJumboNoThis @ no (r0=method, r9="this")
@@ -26293,10 +26293,8 @@
mov r1, #1
str r1, [rSELF,#offThread_singleStepCount] @ just step once
mov r0, rSELF
- mov r1, #kInterpSingleStep
- mov r2, #kSubModeNormal
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeCountedStep
+ bl dvmEnableSubMode @ (self, newMode)
ldr rIBASE, [rSELF,#offThread_curHandlerTable]
FETCH_INST()
GET_INST_OPCODE(ip)
@@ -26514,8 +26512,8 @@
* r2 is jit state.
*/
common_selectTrace:
- ldrb r0,[rSELF,#offThread_breakFlags]
- ands r0,#kInterpJitBreak
+ ldrh r0,[rSELF,#offThread_subMode]
+ ands r0, #(kSubModeJitTraceBuild | kSubModeJitSV)
bne 3f @ already doing JIT work, continue
str r2,[rSELF,#offThread_jitState]
mov r0, rSELF
@@ -26570,10 +26568,8 @@
beq 1f
@ Set up SV single-stepping
mov r0, rSELF
- mov r1, #kInterpJitBreak
- mov r2, #kSubModeJitSV
- mov r3, #1 @ true
- bl dvmUpdateInterpBreak @ (self, newBreak, newMode, enable)
+ mov r1, #kSubModeJitSV
+ bl dvmEnableSubMode @ (self, subMode)
mov r2,#kJitSelfVerification @ ask for self verification
str r2,[rSELF,#offThread_jitState]
@ intentional fallthrough
@@ -26628,7 +26624,7 @@
/* On entry: r0 is "Method* methodToCall, r9 is "this" */
.LinvokeNewJumbo:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26650,7 +26646,7 @@
common_invokeMethodRange:
.LinvokeNewRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26680,7 +26676,7 @@
common_invokeMethodNoRange:
.LinvokeNewNoRange:
#if defined(WITH_JIT)
- ldrb r1, [rSELF, #offThread_subMode]
+ ldrh r1, [rSELF, #offThread_subMode]
ands r1, #kSubModeJitTraceBuild
blne save_callsiteinfo
#endif
@@ -26730,7 +26726,7 @@
ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@@ -26784,7 +26780,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
cmp r0,#0
bne common_updateProfile
GOTO_OPCODE(ip) @ jump to next instruction
@@ -26792,7 +26788,7 @@
mov rFP, r1 @ fp = newFp
GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
mov rINST, r9 @ publish new rINST
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
GOTO_OPCODE(ip) @ jump to next instruction
#endif
@@ -26800,7 +26796,6 @@
@ Profiling - record method entry. r0: methodToCall
stmfd sp!, {r0-r3} @ preserve r0-r3
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r1, r0
mov r0, rSELF
bl dvmReportInvoke @ (self, method)
@@ -26810,9 +26805,9 @@
.LinvokeNative:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- str r1, [rSELF, #offThread_curFrame] @ self->curFrame = newFp
+ str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFp (points to args)
@@ -26840,7 +26835,7 @@
@ equivalent to dvmPopJniLocals
ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
ldr r1, [rSELF, #offThread_exception] @ check for exception
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
cmp r1, #0 @ null?
str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
bne common_exceptionThrown @ no, handle exception
@@ -26852,11 +26847,10 @@
11:
@ r0=newFp, r1=&retval, r2=methodToCall, r3=self, lr=subModes
stmfd sp!, {r0-r3} @ save all but subModes
- str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPreNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPreNativeInvoke @ (methodToCall, self, fp)
ldmfd sp, {r0-r3} @ refresh. NOTE: no sp autoincrement
@ Call the native method
@@ -26867,10 +26861,10 @@
ldmfd sp!, {r0-r3} @ r2<- methodToCall (others unneeded)
@ Finish up any post-invoke subMode requirements
- @ interpSave already up-to-date
mov r0, r2 @ r0<- methodToCall
mov r1, rSELF
- bl dvmReportPostNativeInvoke @ (methodToCall, self)
+ mov r2, rFP
+ bl dvmReportPostNativeInvoke @ (methodToCall, self, fp)
b 7b @ resume
.LstackOverflow: @ r0=methodToCall
@@ -26919,7 +26913,7 @@
*/
common_returnFromMethod:
.LreturnNew:
- ldrb lr, [rSELF, #offThread_subMode]
+ ldrh lr, [rSELF, #offThread_subMode]
SAVEAREA_FROM_FP(r0, rFP)
ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
cmp lr, #0 @ any special subMode handling needed?
@@ -26943,7 +26937,7 @@
PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
str r2, [rSELF, #offThread_method]@ self->method = newSave->method
ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
- str rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
+ str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
#if defined(WITH_JIT)
ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
mov rPC, r9 @ publish new rPC
@@ -26965,7 +26959,7 @@
@ On entry, r0: StackSaveArea
ldr r1, [r0, #offStackSaveArea_prevFrame] @ r2<- prevFP
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str r1, [rSELF, #offThread_fp] @ update interpSave.fp
+ str r1, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF
bl dvmReportReturn @ (self)
SAVEAREA_FROM_FP(r0, rFP) @ restore StackSaveArea
@@ -27006,7 +27000,7 @@
mov r1, rSELF @ r1<- self
mov r0, r9 @ r0<- exception
bl dvmAddTrackedAlloc @ don't let the exception be GCed
- ldrb r2, [rSELF, #offThread_subMode] @ get subMode flags
+ ldrh r2, [rSELF, #offThread_subMode] @ get subMode flags
mov r3, #0 @ r3<- NULL
str r3, [rSELF, #offThread_exception] @ self->exception = NULL
@@ -27023,7 +27017,7 @@
ldr r1, [rSELF, #offThread_method] @ r1<- self->method
mov r0, rSELF @ r0<- self
ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
- ldrb lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
+ ldrh lr, [rSELF, #offThread_subMode] @ lr<- subMode flags
mov r2, r9 @ r2<- exception
sub r1, rPC, r1 @ r1<- pc - method->insns
mov r1, r1, asr #1 @ r1<- offset in code units
@@ -27048,7 +27042,7 @@
add sp, sp, #8 @ restore stack
bmi .LnotCaughtLocally
- /* adjust locals to match self->curFrame and updated PC */
+ /* adjust locals to match self->interpSave.curFrame and updated PC */
SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
str r1, [rSELF, #offThread_method] @ self->method = new method
@@ -27074,7 +27068,7 @@
@ Manage debugger bookkeeping
7:
str rPC, [rSELF, #offThread_pc] @ update interpSave.pc
- str rFP, [rSELF, #offThread_fp] @ update interpSave.fp
+ str rFP, [rSELF, #offThread_curFrame] @ update interpSave.curFrame
mov r0, rSELF @ arg0<- self
mov r1, r9 @ arg1<- exception
bl dvmReportExceptionThrow @ (self, exception)
@@ -27141,7 +27135,7 @@
* r0: field pointer (must preserve)
*/
common_verifyField:
- ldrb r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
+ ldrh r3, [rSELF, #offThread_subMode] @ r3 <- submode byte
ands r3, #kSubModeJitTraceBuild
bxeq lr @ Not building trace, continue
ldr r1, [r10] @ r1<- reload resolved StaticField ptr
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 68fccd1..fc253a5 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -130,13 +130,13 @@
.macro SAVE_PC_FP_TO_SELF _reg
movl rSELF,\_reg
movl rPC,offThread_pc(\_reg)
- movl rFP,offThread_fp(\_reg)
+ movl rFP,offThread_curFrame(\_reg)
.endm
.macro LOAD_PC_FP_FROM_SELF
movl rSELF,rFP
movl offThread_pc(rFP),rPC
- movl offThread_fp(rFP),rFP
+ movl offThread_curFrame(rFP),rFP
.endm
/* The interpreter assumes a properly aligned stack on entry, and
@@ -25880,7 +25880,7 @@
/* Set up "named" registers */
movl offThread_pc(%ecx),rPC
- movl offThread_fp(%ecx),rFP
+ movl offThread_curFrame(%ecx),rFP
movl offThread_curHandlerTable(%ecx),rIBASE
/* Remember %esp for future "longjmp" */
@@ -26306,7 +26306,7 @@
movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
/* Any special actions to take? */
- cmpb $0, offThread_subMode(%ecx)
+ cmpw $0, offThread_subMode(%ecx)
jne 2f # Yes - handle them
1:
testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
@@ -26324,7 +26324,7 @@
movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
movl $1, offThread_debugIsMethodEntry(%ecx)
movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
- movl rFP, offThread_curFrame(%ecx) # self->curFrame<- newFP
+ movl rFP, offThread_curFrame(%ecx) # curFrame<-newFP
movl offThread_curHandlerTable(%ecx),rIBASE
FETCH_INST
GOTO_NEXT # jump to methodToCall->insns
@@ -26339,7 +26339,6 @@
SPILL_TMP1(%eax) # preserve methodToCall
SPILL_TMP2(%edx) # preserve newSaveArea
movl rPC, offThread_pc(%ecx) # update interpSave.pc
- movl rFP, offThread_fp(%ecx) # update interpSave.fp
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
call dvmReportInvoke # (self, method)
@@ -26358,8 +26357,8 @@
movl rINST, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
movl %edx, LOCAL2_OFFSET(%ebp) # save newSaveArea
movl LOCAL1_OFFSET(%ebp), rINST # rINST<- newFP
- movl rINST, offThread_curFrame(%ecx) # self->curFrame<- newFP
- cmpb $0, offThread_subMode(%ecx) # Anything special going on?
+ movl rINST, offThread_curFrame(%ecx) # curFrame<- newFP
+ cmpw $0, offThread_subMode(%ecx) # Anything special going on?
jne 11f # yes - handle it
movl %ecx, OUT_ARG3(%esp) # push parameter self
movl %eax, OUT_ARG2(%esp) # push parameter methodToCall
@@ -26372,7 +26371,7 @@
movl rSELF, %eax # %eax<- self
movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
cmp $0, offThread_exception(%eax) # check for exception
- movl rFP, offThread_curFrame(%eax) # self->curFrame<- rFP
+ movl rFP, offThread_curFrame(%eax) # curFrame<- rFP
movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
jne common_exceptionThrown # handle exception
movl offThread_curHandlerTable(%eax),rIBASE
@@ -26387,10 +26386,10 @@
*/
SPILL_TMP1(%eax) # save methodTocall
movl rPC, offThread_pc(%ecx)
- movl rFP, offThread_fp(%ecx)
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
- call dvmReportPreNativeInvoke # (self, methodToCall)
+ movl rFP, OUT_ARG2(%esp)
+ call dvmReportPreNativeInvoke # (self, methodToCall, fp)
UNSPILL_TMP1(%eax) # restore methodToCall
movl rSELF,%ecx # restore self
@@ -26406,7 +26405,8 @@
movl rSELF, %ecx
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
- call dvmReportPostNativeInvoke # (self, methodToCall)
+ movl rFP, OUT_ARG2(%esp)
+ call dvmReportPostNativeInvoke # (self, methodToCall, fp)
jmp 7b # rejoin
.LstackOverflow: # eax=methodToCall
@@ -26423,17 +26423,17 @@
common_returnFromMethod:
movl rSELF,%ecx
SAVEAREA_FROM_FP %eax # eax<- saveArea (old)
- movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
- cmpb $0, offThread_subMode(%ecx) # special action needed?
+ cmpw $0, offThread_subMode(%ecx) # special action needed?
jne 19f # go if so
14:
+ movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST
cmpl $0,rINST # break?
je common_gotoBail # break frame, bail out completely
movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC
movl rINST,offThread_method(%ecx) # self->method = newSave->meethod
- movl rFP,offThread_curFrame(%ecx) # self->curFrame = fp
+ movl rFP,offThread_curFrame(%ecx) # curFrame = fp
movl offMethod_clazz(rINST),%eax # eax<- method->clazz
movl offThread_curHandlerTable(%ecx),rIBASE
movl offClassObject_pDvmDex(%eax),rINST # rINST<- method->clazz->pDvmDex
@@ -26447,7 +26447,7 @@
* Handle special subMode actions
* On entry, rFP: prevFP, %ecx: self, %eax: saveArea
*/
- movl rFP, offThread_fp(%ecx) # update interpSave.fp
+ movl rFP, offThread_curFrame(%ecx) # update interpSave.curFrame
movl rPC, offThread_pc(%ecx) # update interpSave.pc
movl %ecx, OUT_ARG0(%esp) # parameter self
call dvmReportReturn # (self)
@@ -26468,7 +26468,7 @@
*/
common_gotoBail:
movl rPC,offThread_pc(%ecx) # export state to self
- movl rFP,offThread_fp(%ecx)
+ movl rFP,offThread_curFrame(%ecx)
movl %ecx,OUT_ARG0(%esp) # self in arg0
movl rINST,OUT_ARG1(%esp) # changeInterp in arg1
call dvmMterpStdBail # bail out....
@@ -26481,7 +26481,7 @@
common_resumeAfterGlueCall:
movl rSELF, %eax
movl offThread_pc(%eax),rPC
- movl offThread_fp(%eax),rFP
+ movl offThread_curFrame(%eax),rFP
movl offThread_curHandlerTable(%eax),rIBASE
FETCH_INST
GOTO_NEXT
@@ -26556,7 +26556,7 @@
common_exceptionThrown:
movl rSELF,%ecx
movl rPC,offThread_pc(%ecx)
- movl rFP,offThread_fp(%ecx)
+ movl rFP,offThread_curFrame(%ecx)
movl %ecx,OUT_ARG0(%esp)
call dvmMterp_exceptionThrown
jmp common_resumeAfterGlueCall
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.cpp
similarity index 89%
rename from vm/mterp/out/InterpC-allstubs.c
rename to vm/mterp/out/InterpC-allstubs.cpp
index 8930c44..8c2d622 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.cpp
@@ -4,7 +4,7 @@
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,16 +1249,15 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: c/OP_NOP.c */
+/* File: c/OP_NOP.cpp */
HANDLE_OPCODE(OP_NOP)
FINISH(1);
OP_END
-/* File: c/OP_MOVE.c */
+/* File: c/OP_MOVE.cpp */
HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -1286,7 +1268,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_FROM16.c */
+/* File: c/OP_MOVE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1297,7 +1279,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MOVE_16.c */
+/* File: c/OP_MOVE_16.cpp */
HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1308,7 +1290,7 @@
FINISH(3);
OP_END
-/* File: c/OP_MOVE_WIDE.c */
+/* File: c/OP_MOVE_WIDE.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/)
/* IMPORTANT: must correctly handle overlapping registers, e.g. both
* "move-wide v6, v7" and "move-wide v7, v6" */
@@ -1320,7 +1302,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_WIDE_FROM16.c */
+/* File: c/OP_MOVE_WIDE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1330,7 +1312,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MOVE_WIDE_16.c */
+/* File: c/OP_MOVE_WIDE_16.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1340,8 +1322,8 @@
FINISH(3);
OP_END
-/* File: c/OP_MOVE_OBJECT.c */
-/* File: c/OP_MOVE.c */
+/* File: c/OP_MOVE_OBJECT.cpp */
+/* File: c/OP_MOVE.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -1353,8 +1335,8 @@
OP_END
-/* File: c/OP_MOVE_OBJECT_FROM16.c */
-/* File: c/OP_MOVE_FROM16.c */
+/* File: c/OP_MOVE_OBJECT_FROM16.cpp */
+/* File: c/OP_MOVE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1366,8 +1348,8 @@
OP_END
-/* File: c/OP_MOVE_OBJECT_16.c */
-/* File: c/OP_MOVE_16.c */
+/* File: c/OP_MOVE_OBJECT_16.cpp */
+/* File: c/OP_MOVE_16.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1379,7 +1361,7 @@
OP_END
-/* File: c/OP_MOVE_RESULT.c */
+/* File: c/OP_MOVE_RESULT.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
@@ -1389,7 +1371,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_RESULT_WIDE.c */
+/* File: c/OP_MOVE_RESULT_WIDE.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j);
@@ -1397,8 +1379,8 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_RESULT_OBJECT.c */
-/* File: c/OP_MOVE_RESULT.c */
+/* File: c/OP_MOVE_RESULT_OBJECT.cpp */
+/* File: c/OP_MOVE_RESULT.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
@@ -1409,7 +1391,7 @@
OP_END
-/* File: c/OP_MOVE_EXCEPTION.c */
+/* File: c/OP_MOVE_EXCEPTION.cpp */
HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-exception v%d", vdst);
@@ -1419,7 +1401,7 @@
FINISH(1);
OP_END
-/* File: c/OP_RETURN_VOID.c */
+/* File: c/OP_RETURN_VOID.cpp */
HANDLE_OPCODE(OP_RETURN_VOID /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -1428,7 +1410,7 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN.c */
+/* File: c/OP_RETURN.cpp */
HANDLE_OPCODE(OP_RETURN /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return%s v%d",
@@ -1437,7 +1419,7 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN_WIDE.c */
+/* File: c/OP_RETURN_WIDE.cpp */
HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return-wide v%d", vsrc1);
@@ -1445,8 +1427,8 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN_OBJECT.c */
-/* File: c/OP_RETURN.c */
+/* File: c/OP_RETURN_OBJECT.cpp */
+/* File: c/OP_RETURN.cpp */
HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return%s v%d",
@@ -1456,7 +1438,7 @@
OP_END
-/* File: c/OP_CONST_4.c */
+/* File: c/OP_CONST_4.cpp */
HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/)
{
s4 tmp;
@@ -1469,7 +1451,7 @@
FINISH(1);
OP_END
-/* File: c/OP_CONST_16.c */
+/* File: c/OP_CONST_16.cpp */
HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1478,7 +1460,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST.c */
+/* File: c/OP_CONST.cpp */
HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/)
{
u4 tmp;
@@ -1492,7 +1474,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_HIGH16.c */
+/* File: c/OP_CONST_HIGH16.cpp */
HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1501,7 +1483,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_WIDE_16.c */
+/* File: c/OP_CONST_WIDE_16.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1510,7 +1492,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_WIDE_32.c */
+/* File: c/OP_CONST_WIDE_32.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/)
{
u4 tmp;
@@ -1524,7 +1506,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_WIDE.c */
+/* File: c/OP_CONST_WIDE.cpp */
HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/)
{
u8 tmp;
@@ -1540,7 +1522,7 @@
FINISH(5);
OP_END
-/* File: c/OP_CONST_WIDE_HIGH16.c */
+/* File: c/OP_CONST_WIDE_HIGH16.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1549,7 +1531,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_STRING.c */
+/* File: c/OP_CONST_STRING.cpp */
HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
{
StringObject* strObj;
@@ -1569,7 +1551,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_STRING_JUMBO.c */
+/* File: c/OP_CONST_STRING_JUMBO.cpp */
HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/)
{
StringObject* strObj;
@@ -1591,7 +1573,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_CLASS.c */
+/* File: c/OP_CONST_CLASS.cpp */
HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1611,7 +1593,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MONITOR_ENTER.c */
+/* File: c/OP_MONITOR_ENTER.cpp */
HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/)
{
Object* obj;
@@ -1629,7 +1611,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MONITOR_EXIT.c */
+/* File: c/OP_MONITOR_EXIT.cpp */
HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/)
{
Object* obj;
@@ -1661,7 +1643,7 @@
FINISH(1);
OP_END
-/* File: c/OP_CHECK_CAST.c */
+/* File: c/OP_CHECK_CAST.cpp */
HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1694,7 +1676,7 @@
FINISH(2);
OP_END
-/* File: c/OP_INSTANCE_OF.c */
+/* File: c/OP_INSTANCE_OF.cpp */
HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/)
{
ClassObject* clazz;
@@ -1726,7 +1708,7 @@
FINISH(2);
OP_END
-/* File: c/OP_ARRAY_LENGTH.c */
+/* File: c/OP_ARRAY_LENGTH.cpp */
HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/)
{
ArrayObject* arrayObj;
@@ -1743,7 +1725,7 @@
FINISH(1);
OP_END
-/* File: c/OP_NEW_INSTANCE.c */
+/* File: c/OP_NEW_INSTANCE.cpp */
HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1793,7 +1775,7 @@
FINISH(2);
OP_END
-/* File: c/OP_NEW_ARRAY.c */
+/* File: c/OP_NEW_ARRAY.cpp */
HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/)
{
ClassObject* arrayClass;
@@ -1830,17 +1812,17 @@
FINISH(2);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY.c */
+/* File: c/OP_FILLED_NEW_ARRAY.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/)
GOTO_invoke(filledNewArray, false, false);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY_RANGE.c */
+/* File: c/OP_FILLED_NEW_ARRAY_RANGE.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/)
GOTO_invoke(filledNewArray, true, false);
OP_END
-/* File: c/OP_FILL_ARRAY_DATA.c */
+/* File: c/OP_FILL_ARRAY_DATA.cpp */
HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/
{
const u2* arrayData;
@@ -1869,7 +1851,7 @@
}
OP_END
-/* File: c/OP_THROW.c */
+/* File: c/OP_THROW.cpp */
HANDLE_OPCODE(OP_THROW /*vAA*/)
{
Object* obj;
@@ -1895,7 +1877,7 @@
}
OP_END
-/* File: c/OP_GOTO.c */
+/* File: c/OP_GOTO.cpp */
HANDLE_OPCODE(OP_GOTO /*+AA*/)
vdst = INST_AA(inst);
if ((s1)vdst < 0)
@@ -1908,7 +1890,7 @@
FINISH((s1)vdst);
OP_END
-/* File: c/OP_GOTO_16.c */
+/* File: c/OP_GOTO_16.cpp */
HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/)
{
s4 offset = (s2) FETCH(1); /* sign-extend next code unit */
@@ -1924,7 +1906,7 @@
}
OP_END
-/* File: c/OP_GOTO_32.c */
+/* File: c/OP_GOTO_32.cpp */
HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/)
{
s4 offset = FETCH(1); /* low-order 16 bits */
@@ -1941,7 +1923,7 @@
}
OP_END
-/* File: c/OP_PACKED_SWITCH.c */
+/* File: c/OP_PACKED_SWITCH.cpp */
HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/)
{
const u2* switchData;
@@ -1972,7 +1954,7 @@
}
OP_END
-/* File: c/OP_SPARSE_SWITCH.c */
+/* File: c/OP_SPARSE_SWITCH.cpp */
HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/)
{
const u2* switchData;
@@ -2003,135 +1985,135 @@
}
OP_END
-/* File: c/OP_CMPL_FLOAT.c */
+/* File: c/OP_CMPL_FLOAT.cpp */
HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1)
OP_END
-/* File: c/OP_CMPG_FLOAT.c */
+/* File: c/OP_CMPG_FLOAT.cpp */
HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1)
OP_END
-/* File: c/OP_CMPL_DOUBLE.c */
+/* File: c/OP_CMPL_DOUBLE.cpp */
HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1)
OP_END
-/* File: c/OP_CMPG_DOUBLE.c */
+/* File: c/OP_CMPG_DOUBLE.cpp */
HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1)
OP_END
-/* File: c/OP_CMP_LONG.c */
+/* File: c/OP_CMP_LONG.cpp */
HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0)
OP_END
-/* File: c/OP_IF_EQ.c */
+/* File: c/OP_IF_EQ.cpp */
HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==)
OP_END
-/* File: c/OP_IF_NE.c */
+/* File: c/OP_IF_NE.cpp */
HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=)
OP_END
-/* File: c/OP_IF_LT.c */
+/* File: c/OP_IF_LT.cpp */
HANDLE_OP_IF_XX(OP_IF_LT, "lt", <)
OP_END
-/* File: c/OP_IF_GE.c */
+/* File: c/OP_IF_GE.cpp */
HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=)
OP_END
-/* File: c/OP_IF_GT.c */
+/* File: c/OP_IF_GT.cpp */
HANDLE_OP_IF_XX(OP_IF_GT, "gt", >)
OP_END
-/* File: c/OP_IF_LE.c */
+/* File: c/OP_IF_LE.cpp */
HANDLE_OP_IF_XX(OP_IF_LE, "le", <=)
OP_END
-/* File: c/OP_IF_EQZ.c */
+/* File: c/OP_IF_EQZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==)
OP_END
-/* File: c/OP_IF_NEZ.c */
+/* File: c/OP_IF_NEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=)
OP_END
-/* File: c/OP_IF_LTZ.c */
+/* File: c/OP_IF_LTZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <)
OP_END
-/* File: c/OP_IF_GEZ.c */
+/* File: c/OP_IF_GEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=)
OP_END
-/* File: c/OP_IF_GTZ.c */
+/* File: c/OP_IF_GTZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >)
OP_END
-/* File: c/OP_IF_LEZ.c */
+/* File: c/OP_IF_LEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=)
OP_END
-/* File: c/OP_UNUSED_3E.c */
+/* File: c/OP_UNUSED_3E.cpp */
HANDLE_OPCODE(OP_UNUSED_3E)
OP_END
-/* File: c/OP_UNUSED_3F.c */
+/* File: c/OP_UNUSED_3F.cpp */
HANDLE_OPCODE(OP_UNUSED_3F)
OP_END
-/* File: c/OP_UNUSED_40.c */
+/* File: c/OP_UNUSED_40.cpp */
HANDLE_OPCODE(OP_UNUSED_40)
OP_END
-/* File: c/OP_UNUSED_41.c */
+/* File: c/OP_UNUSED_41.cpp */
HANDLE_OPCODE(OP_UNUSED_41)
OP_END
-/* File: c/OP_UNUSED_42.c */
+/* File: c/OP_UNUSED_42.cpp */
HANDLE_OPCODE(OP_UNUSED_42)
OP_END
-/* File: c/OP_UNUSED_43.c */
+/* File: c/OP_UNUSED_43.cpp */
HANDLE_OPCODE(OP_UNUSED_43)
OP_END
-/* File: c/OP_AGET.c */
+/* File: c/OP_AGET.cpp */
HANDLE_OP_AGET(OP_AGET, "", u4, )
OP_END
-/* File: c/OP_AGET_WIDE.c */
+/* File: c/OP_AGET_WIDE.cpp */
HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE)
OP_END
-/* File: c/OP_AGET_OBJECT.c */
+/* File: c/OP_AGET_OBJECT.cpp */
HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, )
OP_END
-/* File: c/OP_AGET_BOOLEAN.c */
+/* File: c/OP_AGET_BOOLEAN.cpp */
HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, )
OP_END
-/* File: c/OP_AGET_BYTE.c */
+/* File: c/OP_AGET_BYTE.cpp */
HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, )
OP_END
-/* File: c/OP_AGET_CHAR.c */
+/* File: c/OP_AGET_CHAR.cpp */
HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, )
OP_END
-/* File: c/OP_AGET_SHORT.c */
+/* File: c/OP_AGET_SHORT.cpp */
HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, )
OP_END
-/* File: c/OP_APUT.c */
+/* File: c/OP_APUT.cpp */
HANDLE_OP_APUT(OP_APUT, "", u4, )
OP_END
-/* File: c/OP_APUT_WIDE.c */
+/* File: c/OP_APUT_WIDE.cpp */
HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE)
OP_END
-/* File: c/OP_APUT_OBJECT.c */
+/* File: c/OP_APUT_OBJECT.cpp */
HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/)
{
ArrayObject* arrayObj;
@@ -2155,11 +2137,11 @@
if (obj != NULL) {
if (!checkForNull(obj))
GOTO_exceptionThrown();
- if (!dvmCanPutArrayElement(obj->clazz, arrayObj->obj.clazz)) {
+ if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) {
LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
obj->clazz->descriptor, obj,
arrayObj->obj.clazz->descriptor, arrayObj);
- dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->obj.clazz);
+ dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz);
GOTO_exceptionThrown();
}
}
@@ -2171,59 +2153,59 @@
FINISH(2);
OP_END
-/* File: c/OP_APUT_BOOLEAN.c */
+/* File: c/OP_APUT_BOOLEAN.cpp */
HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, )
OP_END
-/* File: c/OP_APUT_BYTE.c */
+/* File: c/OP_APUT_BYTE.cpp */
HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, )
OP_END
-/* File: c/OP_APUT_CHAR.c */
+/* File: c/OP_APUT_CHAR.cpp */
HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, )
OP_END
-/* File: c/OP_APUT_SHORT.c */
+/* File: c/OP_APUT_SHORT.cpp */
HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, )
OP_END
-/* File: c/OP_IGET.c */
+/* File: c/OP_IGET.cpp */
HANDLE_IGET_X(OP_IGET, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE.c */
+/* File: c/OP_IGET_WIDE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT.c */
+/* File: c/OP_IGET_OBJECT.cpp */
HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_BOOLEAN.c */
+/* File: c/OP_IGET_BOOLEAN.cpp */
HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_IGET_BYTE.c */
+/* File: c/OP_IGET_BYTE.cpp */
HANDLE_IGET_X(OP_IGET_BYTE, "", Int, )
OP_END
-/* File: c/OP_IGET_CHAR.c */
+/* File: c/OP_IGET_CHAR.cpp */
HANDLE_IGET_X(OP_IGET_CHAR, "", Int, )
OP_END
-/* File: c/OP_IGET_SHORT.c */
+/* File: c/OP_IGET_SHORT.cpp */
HANDLE_IGET_X(OP_IGET_SHORT, "", Int, )
OP_END
-/* File: c/OP_IPUT.c */
+/* File: c/OP_IPUT.cpp */
HANDLE_IPUT_X(OP_IPUT, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE.c */
+/* File: c/OP_IPUT_WIDE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT.c */
+/* File: c/OP_IPUT_OBJECT.cpp */
/*
* The VM spec says we should verify that the reference being stored into
* the field is assignment compatible. In practice, many popular VMs don't
@@ -2238,333 +2220,333 @@
HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_BOOLEAN.c */
+/* File: c/OP_IPUT_BOOLEAN.cpp */
HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_IPUT_BYTE.c */
+/* File: c/OP_IPUT_BYTE.cpp */
HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, )
OP_END
-/* File: c/OP_IPUT_CHAR.c */
+/* File: c/OP_IPUT_CHAR.cpp */
HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, )
OP_END
-/* File: c/OP_IPUT_SHORT.c */
+/* File: c/OP_IPUT_SHORT.cpp */
HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, )
OP_END
-/* File: c/OP_SGET.c */
+/* File: c/OP_SGET.cpp */
HANDLE_SGET_X(OP_SGET, "", Int, )
OP_END
-/* File: c/OP_SGET_WIDE.c */
+/* File: c/OP_SGET_WIDE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT.c */
+/* File: c/OP_SGET_OBJECT.cpp */
HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_BOOLEAN.c */
+/* File: c/OP_SGET_BOOLEAN.cpp */
HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_SGET_BYTE.c */
+/* File: c/OP_SGET_BYTE.cpp */
HANDLE_SGET_X(OP_SGET_BYTE, "", Int, )
OP_END
-/* File: c/OP_SGET_CHAR.c */
+/* File: c/OP_SGET_CHAR.cpp */
HANDLE_SGET_X(OP_SGET_CHAR, "", Int, )
OP_END
-/* File: c/OP_SGET_SHORT.c */
+/* File: c/OP_SGET_SHORT.cpp */
HANDLE_SGET_X(OP_SGET_SHORT, "", Int, )
OP_END
-/* File: c/OP_SPUT.c */
+/* File: c/OP_SPUT.cpp */
HANDLE_SPUT_X(OP_SPUT, "", Int, )
OP_END
-/* File: c/OP_SPUT_WIDE.c */
+/* File: c/OP_SPUT_WIDE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT.c */
+/* File: c/OP_SPUT_OBJECT.cpp */
HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_BOOLEAN.c */
+/* File: c/OP_SPUT_BOOLEAN.cpp */
HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_SPUT_BYTE.c */
+/* File: c/OP_SPUT_BYTE.cpp */
HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, )
OP_END
-/* File: c/OP_SPUT_CHAR.c */
+/* File: c/OP_SPUT_CHAR.cpp */
HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, )
OP_END
-/* File: c/OP_SPUT_SHORT.c */
+/* File: c/OP_SPUT_SHORT.cpp */
HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, )
OP_END
-/* File: c/OP_INVOKE_VIRTUAL.c */
+/* File: c/OP_INVOKE_VIRTUAL.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeVirtual, false, false);
OP_END
-/* File: c/OP_INVOKE_SUPER.c */
+/* File: c/OP_INVOKE_SUPER.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeSuper, false, false);
OP_END
-/* File: c/OP_INVOKE_DIRECT.c */
+/* File: c/OP_INVOKE_DIRECT.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeDirect, false, false);
OP_END
-/* File: c/OP_INVOKE_STATIC.c */
+/* File: c/OP_INVOKE_STATIC.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeStatic, false, false);
OP_END
-/* File: c/OP_INVOKE_INTERFACE.c */
+/* File: c/OP_INVOKE_INTERFACE.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeInterface, false, false);
OP_END
-/* File: c/OP_UNUSED_73.c */
+/* File: c/OP_UNUSED_73.cpp */
HANDLE_OPCODE(OP_UNUSED_73)
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_RANGE.c */
+/* File: c/OP_INVOKE_VIRTUAL_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeVirtual, true, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_RANGE.c */
+/* File: c/OP_INVOKE_SUPER_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeSuper, true, false);
OP_END
-/* File: c/OP_INVOKE_DIRECT_RANGE.c */
+/* File: c/OP_INVOKE_DIRECT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeDirect, true, false);
OP_END
-/* File: c/OP_INVOKE_STATIC_RANGE.c */
+/* File: c/OP_INVOKE_STATIC_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeStatic, true, false);
OP_END
-/* File: c/OP_INVOKE_INTERFACE_RANGE.c */
+/* File: c/OP_INVOKE_INTERFACE_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeInterface, true, false);
OP_END
-/* File: c/OP_UNUSED_79.c */
+/* File: c/OP_UNUSED_79.cpp */
HANDLE_OPCODE(OP_UNUSED_79)
OP_END
-/* File: c/OP_UNUSED_7A.c */
+/* File: c/OP_UNUSED_7A.cpp */
HANDLE_OPCODE(OP_UNUSED_7A)
OP_END
-/* File: c/OP_NEG_INT.c */
+/* File: c/OP_NEG_INT.cpp */
HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , )
OP_END
-/* File: c/OP_NOT_INT.c */
+/* File: c/OP_NOT_INT.cpp */
HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, )
OP_END
-/* File: c/OP_NEG_LONG.c */
+/* File: c/OP_NEG_LONG.cpp */
HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE)
OP_END
-/* File: c/OP_NOT_LONG.c */
+/* File: c/OP_NOT_LONG.cpp */
HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE)
OP_END
-/* File: c/OP_NEG_FLOAT.c */
+/* File: c/OP_NEG_FLOAT.cpp */
HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT)
OP_END
-/* File: c/OP_NEG_DOUBLE.c */
+/* File: c/OP_NEG_DOUBLE.cpp */
HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE)
OP_END
-/* File: c/OP_INT_TO_LONG.c */
+/* File: c/OP_INT_TO_LONG.cpp */
HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE)
OP_END
-/* File: c/OP_INT_TO_FLOAT.c */
+/* File: c/OP_INT_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT)
OP_END
-/* File: c/OP_INT_TO_DOUBLE.c */
+/* File: c/OP_INT_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE)
OP_END
-/* File: c/OP_LONG_TO_INT.c */
+/* File: c/OP_LONG_TO_INT.cpp */
HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT)
OP_END
-/* File: c/OP_LONG_TO_FLOAT.c */
+/* File: c/OP_LONG_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT)
OP_END
-/* File: c/OP_LONG_TO_DOUBLE.c */
+/* File: c/OP_LONG_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE)
OP_END
-/* File: c/OP_FLOAT_TO_INT.c */
+/* File: c/OP_FLOAT_TO_INT.cpp */
HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int",
float, _FLOAT, s4, _INT)
OP_END
-/* File: c/OP_FLOAT_TO_LONG.c */
+/* File: c/OP_FLOAT_TO_LONG.cpp */
HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long",
float, _FLOAT, s8, _WIDE)
OP_END
-/* File: c/OP_FLOAT_TO_DOUBLE.c */
+/* File: c/OP_FLOAT_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE)
OP_END
-/* File: c/OP_DOUBLE_TO_INT.c */
+/* File: c/OP_DOUBLE_TO_INT.cpp */
HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int",
double, _DOUBLE, s4, _INT)
OP_END
-/* File: c/OP_DOUBLE_TO_LONG.c */
+/* File: c/OP_DOUBLE_TO_LONG.cpp */
HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long",
double, _DOUBLE, s8, _WIDE)
OP_END
-/* File: c/OP_DOUBLE_TO_FLOAT.c */
+/* File: c/OP_DOUBLE_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT)
OP_END
-/* File: c/OP_INT_TO_BYTE.c */
+/* File: c/OP_INT_TO_BYTE.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1)
OP_END
-/* File: c/OP_INT_TO_CHAR.c */
+/* File: c/OP_INT_TO_CHAR.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2)
OP_END
-/* File: c/OP_INT_TO_SHORT.c */
+/* File: c/OP_INT_TO_SHORT.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */
OP_END
-/* File: c/OP_ADD_INT.c */
+/* File: c/OP_ADD_INT.cpp */
HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0)
OP_END
-/* File: c/OP_SUB_INT.c */
+/* File: c/OP_SUB_INT.cpp */
HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_INT.c */
+/* File: c/OP_MUL_INT.cpp */
HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT.c */
+/* File: c/OP_DIV_INT.cpp */
HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT.c */
+/* File: c/OP_REM_INT.cpp */
HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT.c */
+/* File: c/OP_AND_INT.cpp */
HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT.c */
+/* File: c/OP_OR_INT.cpp */
HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT.c */
+/* File: c/OP_XOR_INT.cpp */
HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT.c */
+/* File: c/OP_SHL_INT.cpp */
HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT.c */
+/* File: c/OP_SHR_INT.cpp */
HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT.c */
+/* File: c/OP_USHR_INT.cpp */
HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>)
OP_END
-/* File: c/OP_ADD_LONG.c */
+/* File: c/OP_ADD_LONG.cpp */
HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0)
OP_END
-/* File: c/OP_SUB_LONG.c */
+/* File: c/OP_SUB_LONG.cpp */
HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_LONG.c */
+/* File: c/OP_MUL_LONG.cpp */
HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_LONG.c */
+/* File: c/OP_DIV_LONG.cpp */
HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1)
OP_END
-/* File: c/OP_REM_LONG.c */
+/* File: c/OP_REM_LONG.cpp */
HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2)
OP_END
-/* File: c/OP_AND_LONG.c */
+/* File: c/OP_AND_LONG.cpp */
HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0)
OP_END
-/* File: c/OP_OR_LONG.c */
+/* File: c/OP_OR_LONG.cpp */
HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0)
OP_END
-/* File: c/OP_XOR_LONG.c */
+/* File: c/OP_XOR_LONG.cpp */
HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_LONG.c */
+/* File: c/OP_SHL_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<)
OP_END
-/* File: c/OP_SHR_LONG.c */
+/* File: c/OP_SHR_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>)
OP_END
-/* File: c/OP_USHR_LONG.c */
+/* File: c/OP_USHR_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>)
OP_END
-/* File: c/OP_ADD_FLOAT.c */
+/* File: c/OP_ADD_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +)
OP_END
-/* File: c/OP_SUB_FLOAT.c */
+/* File: c/OP_SUB_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -)
OP_END
-/* File: c/OP_MUL_FLOAT.c */
+/* File: c/OP_MUL_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *)
OP_END
-/* File: c/OP_DIV_FLOAT.c */
+/* File: c/OP_DIV_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /)
OP_END
-/* File: c/OP_REM_FLOAT.c */
+/* File: c/OP_REM_FLOAT.cpp */
HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/)
{
u2 srcRegs;
@@ -2579,23 +2561,23 @@
FINISH(2);
OP_END
-/* File: c/OP_ADD_DOUBLE.c */
+/* File: c/OP_ADD_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +)
OP_END
-/* File: c/OP_SUB_DOUBLE.c */
+/* File: c/OP_SUB_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -)
OP_END
-/* File: c/OP_MUL_DOUBLE.c */
+/* File: c/OP_MUL_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *)
OP_END
-/* File: c/OP_DIV_DOUBLE.c */
+/* File: c/OP_DIV_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /)
OP_END
-/* File: c/OP_REM_DOUBLE.c */
+/* File: c/OP_REM_DOUBLE.cpp */
HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/)
{
u2 srcRegs;
@@ -2610,111 +2592,111 @@
FINISH(2);
OP_END
-/* File: c/OP_ADD_INT_2ADDR.c */
+/* File: c/OP_ADD_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0)
OP_END
-/* File: c/OP_SUB_INT_2ADDR.c */
+/* File: c/OP_SUB_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_INT_2ADDR.c */
+/* File: c/OP_MUL_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_2ADDR.c */
+/* File: c/OP_DIV_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_2ADDR.c */
+/* File: c/OP_REM_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_2ADDR.c */
+/* File: c/OP_AND_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_2ADDR.c */
+/* File: c/OP_OR_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_2ADDR.c */
+/* File: c/OP_XOR_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT_2ADDR.c */
+/* File: c/OP_SHL_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT_2ADDR.c */
+/* File: c/OP_SHR_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT_2ADDR.c */
+/* File: c/OP_USHR_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>)
OP_END
-/* File: c/OP_ADD_LONG_2ADDR.c */
+/* File: c/OP_ADD_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0)
OP_END
-/* File: c/OP_SUB_LONG_2ADDR.c */
+/* File: c/OP_SUB_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_LONG_2ADDR.c */
+/* File: c/OP_MUL_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_LONG_2ADDR.c */
+/* File: c/OP_DIV_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1)
OP_END
-/* File: c/OP_REM_LONG_2ADDR.c */
+/* File: c/OP_REM_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2)
OP_END
-/* File: c/OP_AND_LONG_2ADDR.c */
+/* File: c/OP_AND_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0)
OP_END
-/* File: c/OP_OR_LONG_2ADDR.c */
+/* File: c/OP_OR_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0)
OP_END
-/* File: c/OP_XOR_LONG_2ADDR.c */
+/* File: c/OP_XOR_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_LONG_2ADDR.c */
+/* File: c/OP_SHL_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<)
OP_END
-/* File: c/OP_SHR_LONG_2ADDR.c */
+/* File: c/OP_SHR_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>)
OP_END
-/* File: c/OP_USHR_LONG_2ADDR.c */
+/* File: c/OP_USHR_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>)
OP_END
-/* File: c/OP_ADD_FLOAT_2ADDR.c */
+/* File: c/OP_ADD_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +)
OP_END
-/* File: c/OP_SUB_FLOAT_2ADDR.c */
+/* File: c/OP_SUB_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -)
OP_END
-/* File: c/OP_MUL_FLOAT_2ADDR.c */
+/* File: c/OP_MUL_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *)
OP_END
-/* File: c/OP_DIV_FLOAT_2ADDR.c */
+/* File: c/OP_DIV_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /)
OP_END
-/* File: c/OP_REM_FLOAT_2ADDR.c */
+/* File: c/OP_REM_FLOAT_2ADDR.cpp */
HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -2724,23 +2706,23 @@
FINISH(1);
OP_END
-/* File: c/OP_ADD_DOUBLE_2ADDR.c */
+/* File: c/OP_ADD_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +)
OP_END
-/* File: c/OP_SUB_DOUBLE_2ADDR.c */
+/* File: c/OP_SUB_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -)
OP_END
-/* File: c/OP_MUL_DOUBLE_2ADDR.c */
+/* File: c/OP_MUL_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *)
OP_END
-/* File: c/OP_DIV_DOUBLE_2ADDR.c */
+/* File: c/OP_DIV_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /)
OP_END
-/* File: c/OP_REM_DOUBLE_2ADDR.c */
+/* File: c/OP_REM_DOUBLE_2ADDR.cpp */
HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -2750,11 +2732,11 @@
FINISH(1);
OP_END
-/* File: c/OP_ADD_INT_LIT16.c */
+/* File: c/OP_ADD_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0)
OP_END
-/* File: c/OP_RSUB_INT.c */
+/* File: c/OP_RSUB_INT.cpp */
HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/)
{
vdst = INST_A(inst);
@@ -2766,35 +2748,35 @@
FINISH(2);
OP_END
-/* File: c/OP_MUL_INT_LIT16.c */
+/* File: c/OP_MUL_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_LIT16.c */
+/* File: c/OP_DIV_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_LIT16.c */
+/* File: c/OP_REM_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_LIT16.c */
+/* File: c/OP_AND_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_LIT16.c */
+/* File: c/OP_OR_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_LIT16.c */
+/* File: c/OP_XOR_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0)
OP_END
-/* File: c/OP_ADD_INT_LIT8.c */
+/* File: c/OP_ADD_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0)
OP_END
-/* File: c/OP_RSUB_INT_LIT8.c */
+/* File: c/OP_RSUB_INT_LIT8.cpp */
HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/)
{
u2 litInfo;
@@ -2808,79 +2790,79 @@
FINISH(2);
OP_END
-/* File: c/OP_MUL_INT_LIT8.c */
+/* File: c/OP_MUL_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_LIT8.c */
+/* File: c/OP_DIV_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_LIT8.c */
+/* File: c/OP_REM_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_LIT8.c */
+/* File: c/OP_AND_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_LIT8.c */
+/* File: c/OP_OR_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_LIT8.c */
+/* File: c/OP_XOR_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT_LIT8.c */
+/* File: c/OP_SHL_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT_LIT8.c */
+/* File: c/OP_SHR_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT_LIT8.c */
+/* File: c/OP_USHR_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>)
OP_END
-/* File: c/OP_IGET_VOLATILE.c */
+/* File: c/OP_IGET_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_VOLATILE.c */
+/* File: c/OP_IPUT_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SGET_VOLATILE.c */
+/* File: c/OP_SGET_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_VOLATILE.c */
+/* File: c/OP_SPUT_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE.c */
+/* File: c/OP_IGET_WIDE_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE.c */
+/* File: c/OP_SGET_WIDE_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_BREAKPOINT.c */
+/* File: c/OP_BREAKPOINT.cpp */
HANDLE_OPCODE(OP_BREAKPOINT)
{
/*
@@ -2906,7 +2888,7 @@
}
OP_END
-/* File: c/OP_THROW_VERIFICATION_ERROR.c */
+/* File: c/OP_THROW_VERIFICATION_ERROR.cpp */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
EXPORT_PC();
vsrc1 = INST_AA(inst);
@@ -2915,7 +2897,7 @@
GOTO_exceptionThrown();
OP_END
-/* File: c/OP_EXECUTE_INLINE.c */
+/* File: c/OP_EXECUTE_INLINE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
{
/*
@@ -2976,7 +2958,7 @@
FINISH(3);
OP_END
-/* File: c/OP_EXECUTE_INLINE_RANGE.c */
+/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
{
u4 arg0, arg1, arg2, arg3;
@@ -3021,7 +3003,7 @@
FINISH(3);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
{
Object* obj;
@@ -3052,7 +3034,7 @@
}
OP_END
-/* File: c/OP_RETURN_VOID_BARRIER.c */
+/* File: c/OP_RETURN_VOID_BARRIER.cpp */
HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -3062,63 +3044,63 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_IGET_QUICK.c */
+/* File: c/OP_IGET_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE_QUICK.c */
+/* File: c/OP_IGET_WIDE_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_QUICK.c */
+/* File: c/OP_IGET_OBJECT_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_QUICK.c */
+/* File: c/OP_IPUT_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE_QUICK.c */
+/* File: c/OP_IPUT_WIDE_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_QUICK.c */
+/* File: c/OP_IPUT_OBJECT_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_QUICK.c */
+/* File: c/OP_INVOKE_VIRTUAL_QUICK.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeVirtualQuick, false, false);
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c */
+/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeVirtualQuick, true, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_QUICK.c */
+/* File: c/OP_INVOKE_SUPER_QUICK.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeSuperQuick, false, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.c */
+/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeSuperQuick, true, false);
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_DISPATCH_FF.c */
+/* File: c/OP_DISPATCH_FF.cpp */
HANDLE_OPCODE(OP_DISPATCH_FF)
/*
* Indicates extended opcode. Use next 8 bits to choose where to branch.
@@ -3126,7 +3108,7 @@
DISPATCH_EXTENDED(INST_AA(inst));
OP_END
-/* File: c/OP_CONST_CLASS_JUMBO.c */
+/* File: c/OP_CONST_CLASS_JUMBO.cpp */
HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3146,7 +3128,7 @@
FINISH(4);
OP_END
-/* File: c/OP_CHECK_CAST_JUMBO.c */
+/* File: c/OP_CHECK_CAST_JUMBO.cpp */
HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3179,7 +3161,7 @@
FINISH(4);
OP_END
-/* File: c/OP_INSTANCE_OF_JUMBO.c */
+/* File: c/OP_INSTANCE_OF_JUMBO.cpp */
HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3211,7 +3193,7 @@
FINISH(5);
OP_END
-/* File: c/OP_NEW_INSTANCE_JUMBO.c */
+/* File: c/OP_NEW_INSTANCE_JUMBO.cpp */
HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3261,7 +3243,7 @@
FINISH(4);
OP_END
-/* File: c/OP_NEW_ARRAY_JUMBO.c */
+/* File: c/OP_NEW_ARRAY_JUMBO.cpp */
HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
{
ClassObject* arrayClass;
@@ -3298,48 +3280,48 @@
FINISH(5);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.c */
+/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/)
GOTO_invoke(filledNewArray, true, true);
OP_END
-/* File: c/OP_IGET_JUMBO.c */
+/* File: c/OP_IGET_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_BOOLEAN_JUMBO.c */
+/* File: c/OP_IGET_BOOLEAN_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_BYTE_JUMBO.c */
+/* File: c/OP_IGET_BYTE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_CHAR_JUMBO.c */
+/* File: c/OP_IGET_CHAR_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_SHORT_JUMBO.c */
+/* File: c/OP_IGET_SHORT_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_JUMBO.c */
+/* File: c/OP_IPUT_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_JUMBO.cpp */
/*
* The VM spec says we should verify that the reference being stored into
* the field is assignment compatible. In practice, many popular VMs don't
@@ -3354,912 +3336,912 @@
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_BOOLEAN_JUMBO.c */
+/* File: c/OP_IPUT_BOOLEAN_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_BYTE_JUMBO.c */
+/* File: c/OP_IPUT_BYTE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_CHAR_JUMBO.c */
+/* File: c/OP_IPUT_CHAR_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_SHORT_JUMBO.c */
+/* File: c/OP_IPUT_SHORT_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_JUMBO.c */
+/* File: c/OP_SGET_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_WIDE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_BOOLEAN_JUMBO.c */
+/* File: c/OP_SGET_BOOLEAN_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_BYTE_JUMBO.c */
+/* File: c/OP_SGET_BYTE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_CHAR_JUMBO.c */
+/* File: c/OP_SGET_CHAR_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_SHORT_JUMBO.c */
+/* File: c/OP_SGET_SHORT_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_JUMBO.c */
+/* File: c/OP_SPUT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_WIDE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_BOOLEAN_JUMBO.c */
+/* File: c/OP_SPUT_BOOLEAN_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_BYTE_JUMBO.c */
+/* File: c/OP_SPUT_BYTE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_CHAR_JUMBO.c */
+/* File: c/OP_SPUT_CHAR_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_SHORT_JUMBO.c */
+/* File: c/OP_SPUT_SHORT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_JUMBO.c */
+/* File: c/OP_INVOKE_VIRTUAL_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeVirtual, true, true);
OP_END
-/* File: c/OP_INVOKE_SUPER_JUMBO.c */
+/* File: c/OP_INVOKE_SUPER_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeSuper, true, true);
OP_END
-/* File: c/OP_INVOKE_DIRECT_JUMBO.c */
+/* File: c/OP_INVOKE_DIRECT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeDirect, true, true);
OP_END
-/* File: c/OP_INVOKE_STATIC_JUMBO.c */
+/* File: c/OP_INVOKE_STATIC_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeStatic, true, true);
OP_END
-/* File: c/OP_INVOKE_INTERFACE_JUMBO.c */
+/* File: c/OP_INVOKE_INTERFACE_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeInterface, true, true);
OP_END
-/* File: c/OP_UNUSED_27FF.c */
+/* File: c/OP_UNUSED_27FF.cpp */
HANDLE_OPCODE(OP_UNUSED_27FF)
OP_END
-/* File: c/OP_UNUSED_28FF.c */
+/* File: c/OP_UNUSED_28FF.cpp */
HANDLE_OPCODE(OP_UNUSED_28FF)
OP_END
-/* File: c/OP_UNUSED_29FF.c */
+/* File: c/OP_UNUSED_29FF.cpp */
HANDLE_OPCODE(OP_UNUSED_29FF)
OP_END
-/* File: c/OP_UNUSED_2AFF.c */
+/* File: c/OP_UNUSED_2AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2AFF)
OP_END
-/* File: c/OP_UNUSED_2BFF.c */
+/* File: c/OP_UNUSED_2BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2BFF)
OP_END
-/* File: c/OP_UNUSED_2CFF.c */
+/* File: c/OP_UNUSED_2CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2CFF)
OP_END
-/* File: c/OP_UNUSED_2DFF.c */
+/* File: c/OP_UNUSED_2DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2DFF)
OP_END
-/* File: c/OP_UNUSED_2EFF.c */
+/* File: c/OP_UNUSED_2EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2EFF)
OP_END
-/* File: c/OP_UNUSED_2FFF.c */
+/* File: c/OP_UNUSED_2FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2FFF)
OP_END
-/* File: c/OP_UNUSED_30FF.c */
+/* File: c/OP_UNUSED_30FF.cpp */
HANDLE_OPCODE(OP_UNUSED_30FF)
OP_END
-/* File: c/OP_UNUSED_31FF.c */
+/* File: c/OP_UNUSED_31FF.cpp */
HANDLE_OPCODE(OP_UNUSED_31FF)
OP_END
-/* File: c/OP_UNUSED_32FF.c */
+/* File: c/OP_UNUSED_32FF.cpp */
HANDLE_OPCODE(OP_UNUSED_32FF)
OP_END
-/* File: c/OP_UNUSED_33FF.c */
+/* File: c/OP_UNUSED_33FF.cpp */
HANDLE_OPCODE(OP_UNUSED_33FF)
OP_END
-/* File: c/OP_UNUSED_34FF.c */
+/* File: c/OP_UNUSED_34FF.cpp */
HANDLE_OPCODE(OP_UNUSED_34FF)
OP_END
-/* File: c/OP_UNUSED_35FF.c */
+/* File: c/OP_UNUSED_35FF.cpp */
HANDLE_OPCODE(OP_UNUSED_35FF)
OP_END
-/* File: c/OP_UNUSED_36FF.c */
+/* File: c/OP_UNUSED_36FF.cpp */
HANDLE_OPCODE(OP_UNUSED_36FF)
OP_END
-/* File: c/OP_UNUSED_37FF.c */
+/* File: c/OP_UNUSED_37FF.cpp */
HANDLE_OPCODE(OP_UNUSED_37FF)
OP_END
-/* File: c/OP_UNUSED_38FF.c */
+/* File: c/OP_UNUSED_38FF.cpp */
HANDLE_OPCODE(OP_UNUSED_38FF)
OP_END
-/* File: c/OP_UNUSED_39FF.c */
+/* File: c/OP_UNUSED_39FF.cpp */
HANDLE_OPCODE(OP_UNUSED_39FF)
OP_END
-/* File: c/OP_UNUSED_3AFF.c */
+/* File: c/OP_UNUSED_3AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3AFF)
OP_END
-/* File: c/OP_UNUSED_3BFF.c */
+/* File: c/OP_UNUSED_3BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3BFF)
OP_END
-/* File: c/OP_UNUSED_3CFF.c */
+/* File: c/OP_UNUSED_3CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3CFF)
OP_END
-/* File: c/OP_UNUSED_3DFF.c */
+/* File: c/OP_UNUSED_3DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3DFF)
OP_END
-/* File: c/OP_UNUSED_3EFF.c */
+/* File: c/OP_UNUSED_3EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3EFF)
OP_END
-/* File: c/OP_UNUSED_3FFF.c */
+/* File: c/OP_UNUSED_3FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3FFF)
OP_END
-/* File: c/OP_UNUSED_40FF.c */
+/* File: c/OP_UNUSED_40FF.cpp */
HANDLE_OPCODE(OP_UNUSED_40FF)
OP_END
-/* File: c/OP_UNUSED_41FF.c */
+/* File: c/OP_UNUSED_41FF.cpp */
HANDLE_OPCODE(OP_UNUSED_41FF)
OP_END
-/* File: c/OP_UNUSED_42FF.c */
+/* File: c/OP_UNUSED_42FF.cpp */
HANDLE_OPCODE(OP_UNUSED_42FF)
OP_END
-/* File: c/OP_UNUSED_43FF.c */
+/* File: c/OP_UNUSED_43FF.cpp */
HANDLE_OPCODE(OP_UNUSED_43FF)
OP_END
-/* File: c/OP_UNUSED_44FF.c */
+/* File: c/OP_UNUSED_44FF.cpp */
HANDLE_OPCODE(OP_UNUSED_44FF)
OP_END
-/* File: c/OP_UNUSED_45FF.c */
+/* File: c/OP_UNUSED_45FF.cpp */
HANDLE_OPCODE(OP_UNUSED_45FF)
OP_END
-/* File: c/OP_UNUSED_46FF.c */
+/* File: c/OP_UNUSED_46FF.cpp */
HANDLE_OPCODE(OP_UNUSED_46FF)
OP_END
-/* File: c/OP_UNUSED_47FF.c */
+/* File: c/OP_UNUSED_47FF.cpp */
HANDLE_OPCODE(OP_UNUSED_47FF)
OP_END
-/* File: c/OP_UNUSED_48FF.c */
+/* File: c/OP_UNUSED_48FF.cpp */
HANDLE_OPCODE(OP_UNUSED_48FF)
OP_END
-/* File: c/OP_UNUSED_49FF.c */
+/* File: c/OP_UNUSED_49FF.cpp */
HANDLE_OPCODE(OP_UNUSED_49FF)
OP_END
-/* File: c/OP_UNUSED_4AFF.c */
+/* File: c/OP_UNUSED_4AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4AFF)
OP_END
-/* File: c/OP_UNUSED_4BFF.c */
+/* File: c/OP_UNUSED_4BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4BFF)
OP_END
-/* File: c/OP_UNUSED_4CFF.c */
+/* File: c/OP_UNUSED_4CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4CFF)
OP_END
-/* File: c/OP_UNUSED_4DFF.c */
+/* File: c/OP_UNUSED_4DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4DFF)
OP_END
-/* File: c/OP_UNUSED_4EFF.c */
+/* File: c/OP_UNUSED_4EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4EFF)
OP_END
-/* File: c/OP_UNUSED_4FFF.c */
+/* File: c/OP_UNUSED_4FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4FFF)
OP_END
-/* File: c/OP_UNUSED_50FF.c */
+/* File: c/OP_UNUSED_50FF.cpp */
HANDLE_OPCODE(OP_UNUSED_50FF)
OP_END
-/* File: c/OP_UNUSED_51FF.c */
+/* File: c/OP_UNUSED_51FF.cpp */
HANDLE_OPCODE(OP_UNUSED_51FF)
OP_END
-/* File: c/OP_UNUSED_52FF.c */
+/* File: c/OP_UNUSED_52FF.cpp */
HANDLE_OPCODE(OP_UNUSED_52FF)
OP_END
-/* File: c/OP_UNUSED_53FF.c */
+/* File: c/OP_UNUSED_53FF.cpp */
HANDLE_OPCODE(OP_UNUSED_53FF)
OP_END
-/* File: c/OP_UNUSED_54FF.c */
+/* File: c/OP_UNUSED_54FF.cpp */
HANDLE_OPCODE(OP_UNUSED_54FF)
OP_END
-/* File: c/OP_UNUSED_55FF.c */
+/* File: c/OP_UNUSED_55FF.cpp */
HANDLE_OPCODE(OP_UNUSED_55FF)
OP_END
-/* File: c/OP_UNUSED_56FF.c */
+/* File: c/OP_UNUSED_56FF.cpp */
HANDLE_OPCODE(OP_UNUSED_56FF)
OP_END
-/* File: c/OP_UNUSED_57FF.c */
+/* File: c/OP_UNUSED_57FF.cpp */
HANDLE_OPCODE(OP_UNUSED_57FF)
OP_END
-/* File: c/OP_UNUSED_58FF.c */
+/* File: c/OP_UNUSED_58FF.cpp */
HANDLE_OPCODE(OP_UNUSED_58FF)
OP_END
-/* File: c/OP_UNUSED_59FF.c */
+/* File: c/OP_UNUSED_59FF.cpp */
HANDLE_OPCODE(OP_UNUSED_59FF)
OP_END
-/* File: c/OP_UNUSED_5AFF.c */
+/* File: c/OP_UNUSED_5AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5AFF)
OP_END
-/* File: c/OP_UNUSED_5BFF.c */
+/* File: c/OP_UNUSED_5BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5BFF)
OP_END
-/* File: c/OP_UNUSED_5CFF.c */
+/* File: c/OP_UNUSED_5CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5CFF)
OP_END
-/* File: c/OP_UNUSED_5DFF.c */
+/* File: c/OP_UNUSED_5DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5DFF)
OP_END
-/* File: c/OP_UNUSED_5EFF.c */
+/* File: c/OP_UNUSED_5EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5EFF)
OP_END
-/* File: c/OP_UNUSED_5FFF.c */
+/* File: c/OP_UNUSED_5FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5FFF)
OP_END
-/* File: c/OP_UNUSED_60FF.c */
+/* File: c/OP_UNUSED_60FF.cpp */
HANDLE_OPCODE(OP_UNUSED_60FF)
OP_END
-/* File: c/OP_UNUSED_61FF.c */
+/* File: c/OP_UNUSED_61FF.cpp */
HANDLE_OPCODE(OP_UNUSED_61FF)
OP_END
-/* File: c/OP_UNUSED_62FF.c */
+/* File: c/OP_UNUSED_62FF.cpp */
HANDLE_OPCODE(OP_UNUSED_62FF)
OP_END
-/* File: c/OP_UNUSED_63FF.c */
+/* File: c/OP_UNUSED_63FF.cpp */
HANDLE_OPCODE(OP_UNUSED_63FF)
OP_END
-/* File: c/OP_UNUSED_64FF.c */
+/* File: c/OP_UNUSED_64FF.cpp */
HANDLE_OPCODE(OP_UNUSED_64FF)
OP_END
-/* File: c/OP_UNUSED_65FF.c */
+/* File: c/OP_UNUSED_65FF.cpp */
HANDLE_OPCODE(OP_UNUSED_65FF)
OP_END
-/* File: c/OP_UNUSED_66FF.c */
+/* File: c/OP_UNUSED_66FF.cpp */
HANDLE_OPCODE(OP_UNUSED_66FF)
OP_END
-/* File: c/OP_UNUSED_67FF.c */
+/* File: c/OP_UNUSED_67FF.cpp */
HANDLE_OPCODE(OP_UNUSED_67FF)
OP_END
-/* File: c/OP_UNUSED_68FF.c */
+/* File: c/OP_UNUSED_68FF.cpp */
HANDLE_OPCODE(OP_UNUSED_68FF)
OP_END
-/* File: c/OP_UNUSED_69FF.c */
+/* File: c/OP_UNUSED_69FF.cpp */
HANDLE_OPCODE(OP_UNUSED_69FF)
OP_END
-/* File: c/OP_UNUSED_6AFF.c */
+/* File: c/OP_UNUSED_6AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6AFF)
OP_END
-/* File: c/OP_UNUSED_6BFF.c */
+/* File: c/OP_UNUSED_6BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6BFF)
OP_END
-/* File: c/OP_UNUSED_6CFF.c */
+/* File: c/OP_UNUSED_6CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6CFF)
OP_END
-/* File: c/OP_UNUSED_6DFF.c */
+/* File: c/OP_UNUSED_6DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6DFF)
OP_END
-/* File: c/OP_UNUSED_6EFF.c */
+/* File: c/OP_UNUSED_6EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6EFF)
OP_END
-/* File: c/OP_UNUSED_6FFF.c */
+/* File: c/OP_UNUSED_6FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6FFF)
OP_END
-/* File: c/OP_UNUSED_70FF.c */
+/* File: c/OP_UNUSED_70FF.cpp */
HANDLE_OPCODE(OP_UNUSED_70FF)
OP_END
-/* File: c/OP_UNUSED_71FF.c */
+/* File: c/OP_UNUSED_71FF.cpp */
HANDLE_OPCODE(OP_UNUSED_71FF)
OP_END
-/* File: c/OP_UNUSED_72FF.c */
+/* File: c/OP_UNUSED_72FF.cpp */
HANDLE_OPCODE(OP_UNUSED_72FF)
OP_END
-/* File: c/OP_UNUSED_73FF.c */
+/* File: c/OP_UNUSED_73FF.cpp */
HANDLE_OPCODE(OP_UNUSED_73FF)
OP_END
-/* File: c/OP_UNUSED_74FF.c */
+/* File: c/OP_UNUSED_74FF.cpp */
HANDLE_OPCODE(OP_UNUSED_74FF)
OP_END
-/* File: c/OP_UNUSED_75FF.c */
+/* File: c/OP_UNUSED_75FF.cpp */
HANDLE_OPCODE(OP_UNUSED_75FF)
OP_END
-/* File: c/OP_UNUSED_76FF.c */
+/* File: c/OP_UNUSED_76FF.cpp */
HANDLE_OPCODE(OP_UNUSED_76FF)
OP_END
-/* File: c/OP_UNUSED_77FF.c */
+/* File: c/OP_UNUSED_77FF.cpp */
HANDLE_OPCODE(OP_UNUSED_77FF)
OP_END
-/* File: c/OP_UNUSED_78FF.c */
+/* File: c/OP_UNUSED_78FF.cpp */
HANDLE_OPCODE(OP_UNUSED_78FF)
OP_END
-/* File: c/OP_UNUSED_79FF.c */
+/* File: c/OP_UNUSED_79FF.cpp */
HANDLE_OPCODE(OP_UNUSED_79FF)
OP_END
-/* File: c/OP_UNUSED_7AFF.c */
+/* File: c/OP_UNUSED_7AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7AFF)
OP_END
-/* File: c/OP_UNUSED_7BFF.c */
+/* File: c/OP_UNUSED_7BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7BFF)
OP_END
-/* File: c/OP_UNUSED_7CFF.c */
+/* File: c/OP_UNUSED_7CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7CFF)
OP_END
-/* File: c/OP_UNUSED_7DFF.c */
+/* File: c/OP_UNUSED_7DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7DFF)
OP_END
-/* File: c/OP_UNUSED_7EFF.c */
+/* File: c/OP_UNUSED_7EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7EFF)
OP_END
-/* File: c/OP_UNUSED_7FFF.c */
+/* File: c/OP_UNUSED_7FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7FFF)
OP_END
-/* File: c/OP_UNUSED_80FF.c */
+/* File: c/OP_UNUSED_80FF.cpp */
HANDLE_OPCODE(OP_UNUSED_80FF)
OP_END
-/* File: c/OP_UNUSED_81FF.c */
+/* File: c/OP_UNUSED_81FF.cpp */
HANDLE_OPCODE(OP_UNUSED_81FF)
OP_END
-/* File: c/OP_UNUSED_82FF.c */
+/* File: c/OP_UNUSED_82FF.cpp */
HANDLE_OPCODE(OP_UNUSED_82FF)
OP_END
-/* File: c/OP_UNUSED_83FF.c */
+/* File: c/OP_UNUSED_83FF.cpp */
HANDLE_OPCODE(OP_UNUSED_83FF)
OP_END
-/* File: c/OP_UNUSED_84FF.c */
+/* File: c/OP_UNUSED_84FF.cpp */
HANDLE_OPCODE(OP_UNUSED_84FF)
OP_END
-/* File: c/OP_UNUSED_85FF.c */
+/* File: c/OP_UNUSED_85FF.cpp */
HANDLE_OPCODE(OP_UNUSED_85FF)
OP_END
-/* File: c/OP_UNUSED_86FF.c */
+/* File: c/OP_UNUSED_86FF.cpp */
HANDLE_OPCODE(OP_UNUSED_86FF)
OP_END
-/* File: c/OP_UNUSED_87FF.c */
+/* File: c/OP_UNUSED_87FF.cpp */
HANDLE_OPCODE(OP_UNUSED_87FF)
OP_END
-/* File: c/OP_UNUSED_88FF.c */
+/* File: c/OP_UNUSED_88FF.cpp */
HANDLE_OPCODE(OP_UNUSED_88FF)
OP_END
-/* File: c/OP_UNUSED_89FF.c */
+/* File: c/OP_UNUSED_89FF.cpp */
HANDLE_OPCODE(OP_UNUSED_89FF)
OP_END
-/* File: c/OP_UNUSED_8AFF.c */
+/* File: c/OP_UNUSED_8AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8AFF)
OP_END
-/* File: c/OP_UNUSED_8BFF.c */
+/* File: c/OP_UNUSED_8BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8BFF)
OP_END
-/* File: c/OP_UNUSED_8CFF.c */
+/* File: c/OP_UNUSED_8CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8CFF)
OP_END
-/* File: c/OP_UNUSED_8DFF.c */
+/* File: c/OP_UNUSED_8DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8DFF)
OP_END
-/* File: c/OP_UNUSED_8EFF.c */
+/* File: c/OP_UNUSED_8EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8EFF)
OP_END
-/* File: c/OP_UNUSED_8FFF.c */
+/* File: c/OP_UNUSED_8FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8FFF)
OP_END
-/* File: c/OP_UNUSED_90FF.c */
+/* File: c/OP_UNUSED_90FF.cpp */
HANDLE_OPCODE(OP_UNUSED_90FF)
OP_END
-/* File: c/OP_UNUSED_91FF.c */
+/* File: c/OP_UNUSED_91FF.cpp */
HANDLE_OPCODE(OP_UNUSED_91FF)
OP_END
-/* File: c/OP_UNUSED_92FF.c */
+/* File: c/OP_UNUSED_92FF.cpp */
HANDLE_OPCODE(OP_UNUSED_92FF)
OP_END
-/* File: c/OP_UNUSED_93FF.c */
+/* File: c/OP_UNUSED_93FF.cpp */
HANDLE_OPCODE(OP_UNUSED_93FF)
OP_END
-/* File: c/OP_UNUSED_94FF.c */
+/* File: c/OP_UNUSED_94FF.cpp */
HANDLE_OPCODE(OP_UNUSED_94FF)
OP_END
-/* File: c/OP_UNUSED_95FF.c */
+/* File: c/OP_UNUSED_95FF.cpp */
HANDLE_OPCODE(OP_UNUSED_95FF)
OP_END
-/* File: c/OP_UNUSED_96FF.c */
+/* File: c/OP_UNUSED_96FF.cpp */
HANDLE_OPCODE(OP_UNUSED_96FF)
OP_END
-/* File: c/OP_UNUSED_97FF.c */
+/* File: c/OP_UNUSED_97FF.cpp */
HANDLE_OPCODE(OP_UNUSED_97FF)
OP_END
-/* File: c/OP_UNUSED_98FF.c */
+/* File: c/OP_UNUSED_98FF.cpp */
HANDLE_OPCODE(OP_UNUSED_98FF)
OP_END
-/* File: c/OP_UNUSED_99FF.c */
+/* File: c/OP_UNUSED_99FF.cpp */
HANDLE_OPCODE(OP_UNUSED_99FF)
OP_END
-/* File: c/OP_UNUSED_9AFF.c */
+/* File: c/OP_UNUSED_9AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9AFF)
OP_END
-/* File: c/OP_UNUSED_9BFF.c */
+/* File: c/OP_UNUSED_9BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9BFF)
OP_END
-/* File: c/OP_UNUSED_9CFF.c */
+/* File: c/OP_UNUSED_9CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9CFF)
OP_END
-/* File: c/OP_UNUSED_9DFF.c */
+/* File: c/OP_UNUSED_9DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9DFF)
OP_END
-/* File: c/OP_UNUSED_9EFF.c */
+/* File: c/OP_UNUSED_9EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9EFF)
OP_END
-/* File: c/OP_UNUSED_9FFF.c */
+/* File: c/OP_UNUSED_9FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9FFF)
OP_END
-/* File: c/OP_UNUSED_A0FF.c */
+/* File: c/OP_UNUSED_A0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A0FF)
OP_END
-/* File: c/OP_UNUSED_A1FF.c */
+/* File: c/OP_UNUSED_A1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A1FF)
OP_END
-/* File: c/OP_UNUSED_A2FF.c */
+/* File: c/OP_UNUSED_A2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A2FF)
OP_END
-/* File: c/OP_UNUSED_A3FF.c */
+/* File: c/OP_UNUSED_A3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A3FF)
OP_END
-/* File: c/OP_UNUSED_A4FF.c */
+/* File: c/OP_UNUSED_A4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A4FF)
OP_END
-/* File: c/OP_UNUSED_A5FF.c */
+/* File: c/OP_UNUSED_A5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A5FF)
OP_END
-/* File: c/OP_UNUSED_A6FF.c */
+/* File: c/OP_UNUSED_A6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A6FF)
OP_END
-/* File: c/OP_UNUSED_A7FF.c */
+/* File: c/OP_UNUSED_A7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A7FF)
OP_END
-/* File: c/OP_UNUSED_A8FF.c */
+/* File: c/OP_UNUSED_A8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A8FF)
OP_END
-/* File: c/OP_UNUSED_A9FF.c */
+/* File: c/OP_UNUSED_A9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A9FF)
OP_END
-/* File: c/OP_UNUSED_AAFF.c */
+/* File: c/OP_UNUSED_AAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AAFF)
OP_END
-/* File: c/OP_UNUSED_ABFF.c */
+/* File: c/OP_UNUSED_ABFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ABFF)
OP_END
-/* File: c/OP_UNUSED_ACFF.c */
+/* File: c/OP_UNUSED_ACFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ACFF)
OP_END
-/* File: c/OP_UNUSED_ADFF.c */
+/* File: c/OP_UNUSED_ADFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ADFF)
OP_END
-/* File: c/OP_UNUSED_AEFF.c */
+/* File: c/OP_UNUSED_AEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AEFF)
OP_END
-/* File: c/OP_UNUSED_AFFF.c */
+/* File: c/OP_UNUSED_AFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AFFF)
OP_END
-/* File: c/OP_UNUSED_B0FF.c */
+/* File: c/OP_UNUSED_B0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B0FF)
OP_END
-/* File: c/OP_UNUSED_B1FF.c */
+/* File: c/OP_UNUSED_B1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B1FF)
OP_END
-/* File: c/OP_UNUSED_B2FF.c */
+/* File: c/OP_UNUSED_B2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B2FF)
OP_END
-/* File: c/OP_UNUSED_B3FF.c */
+/* File: c/OP_UNUSED_B3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B3FF)
OP_END
-/* File: c/OP_UNUSED_B4FF.c */
+/* File: c/OP_UNUSED_B4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B4FF)
OP_END
-/* File: c/OP_UNUSED_B5FF.c */
+/* File: c/OP_UNUSED_B5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B5FF)
OP_END
-/* File: c/OP_UNUSED_B6FF.c */
+/* File: c/OP_UNUSED_B6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B6FF)
OP_END
-/* File: c/OP_UNUSED_B7FF.c */
+/* File: c/OP_UNUSED_B7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B7FF)
OP_END
-/* File: c/OP_UNUSED_B8FF.c */
+/* File: c/OP_UNUSED_B8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B8FF)
OP_END
-/* File: c/OP_UNUSED_B9FF.c */
+/* File: c/OP_UNUSED_B9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B9FF)
OP_END
-/* File: c/OP_UNUSED_BAFF.c */
+/* File: c/OP_UNUSED_BAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BAFF)
OP_END
-/* File: c/OP_UNUSED_BBFF.c */
+/* File: c/OP_UNUSED_BBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BBFF)
OP_END
-/* File: c/OP_UNUSED_BCFF.c */
+/* File: c/OP_UNUSED_BCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BCFF)
OP_END
-/* File: c/OP_UNUSED_BDFF.c */
+/* File: c/OP_UNUSED_BDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BDFF)
OP_END
-/* File: c/OP_UNUSED_BEFF.c */
+/* File: c/OP_UNUSED_BEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BEFF)
OP_END
-/* File: c/OP_UNUSED_BFFF.c */
+/* File: c/OP_UNUSED_BFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BFFF)
OP_END
-/* File: c/OP_UNUSED_C0FF.c */
+/* File: c/OP_UNUSED_C0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C0FF)
OP_END
-/* File: c/OP_UNUSED_C1FF.c */
+/* File: c/OP_UNUSED_C1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C1FF)
OP_END
-/* File: c/OP_UNUSED_C2FF.c */
+/* File: c/OP_UNUSED_C2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C2FF)
OP_END
-/* File: c/OP_UNUSED_C3FF.c */
+/* File: c/OP_UNUSED_C3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C3FF)
OP_END
-/* File: c/OP_UNUSED_C4FF.c */
+/* File: c/OP_UNUSED_C4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C4FF)
OP_END
-/* File: c/OP_UNUSED_C5FF.c */
+/* File: c/OP_UNUSED_C5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C5FF)
OP_END
-/* File: c/OP_UNUSED_C6FF.c */
+/* File: c/OP_UNUSED_C6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C6FF)
OP_END
-/* File: c/OP_UNUSED_C7FF.c */
+/* File: c/OP_UNUSED_C7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C7FF)
OP_END
-/* File: c/OP_UNUSED_C8FF.c */
+/* File: c/OP_UNUSED_C8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C8FF)
OP_END
-/* File: c/OP_UNUSED_C9FF.c */
+/* File: c/OP_UNUSED_C9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C9FF)
OP_END
-/* File: c/OP_UNUSED_CAFF.c */
+/* File: c/OP_UNUSED_CAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CAFF)
OP_END
-/* File: c/OP_UNUSED_CBFF.c */
+/* File: c/OP_UNUSED_CBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CBFF)
OP_END
-/* File: c/OP_UNUSED_CCFF.c */
+/* File: c/OP_UNUSED_CCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CCFF)
OP_END
-/* File: c/OP_UNUSED_CDFF.c */
+/* File: c/OP_UNUSED_CDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CDFF)
OP_END
-/* File: c/OP_UNUSED_CEFF.c */
+/* File: c/OP_UNUSED_CEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CEFF)
OP_END
-/* File: c/OP_UNUSED_CFFF.c */
+/* File: c/OP_UNUSED_CFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CFFF)
OP_END
-/* File: c/OP_UNUSED_D0FF.c */
+/* File: c/OP_UNUSED_D0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D0FF)
OP_END
-/* File: c/OP_UNUSED_D1FF.c */
+/* File: c/OP_UNUSED_D1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D1FF)
OP_END
-/* File: c/OP_UNUSED_D2FF.c */
+/* File: c/OP_UNUSED_D2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D2FF)
OP_END
-/* File: c/OP_UNUSED_D3FF.c */
+/* File: c/OP_UNUSED_D3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D3FF)
OP_END
-/* File: c/OP_UNUSED_D4FF.c */
+/* File: c/OP_UNUSED_D4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D4FF)
OP_END
-/* File: c/OP_UNUSED_D5FF.c */
+/* File: c/OP_UNUSED_D5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D5FF)
OP_END
-/* File: c/OP_UNUSED_D6FF.c */
+/* File: c/OP_UNUSED_D6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D6FF)
OP_END
-/* File: c/OP_UNUSED_D7FF.c */
+/* File: c/OP_UNUSED_D7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D7FF)
OP_END
-/* File: c/OP_UNUSED_D8FF.c */
+/* File: c/OP_UNUSED_D8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D8FF)
OP_END
-/* File: c/OP_UNUSED_D9FF.c */
+/* File: c/OP_UNUSED_D9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D9FF)
OP_END
-/* File: c/OP_UNUSED_DAFF.c */
+/* File: c/OP_UNUSED_DAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DAFF)
OP_END
-/* File: c/OP_UNUSED_DBFF.c */
+/* File: c/OP_UNUSED_DBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DBFF)
OP_END
-/* File: c/OP_UNUSED_DCFF.c */
+/* File: c/OP_UNUSED_DCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DCFF)
OP_END
-/* File: c/OP_UNUSED_DDFF.c */
+/* File: c/OP_UNUSED_DDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DDFF)
OP_END
-/* File: c/OP_UNUSED_DEFF.c */
+/* File: c/OP_UNUSED_DEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DEFF)
OP_END
-/* File: c/OP_UNUSED_DFFF.c */
+/* File: c/OP_UNUSED_DFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DFFF)
OP_END
-/* File: c/OP_UNUSED_E0FF.c */
+/* File: c/OP_UNUSED_E0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E0FF)
OP_END
-/* File: c/OP_UNUSED_E1FF.c */
+/* File: c/OP_UNUSED_E1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E1FF)
OP_END
-/* File: c/OP_UNUSED_E2FF.c */
+/* File: c/OP_UNUSED_E2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E2FF)
OP_END
-/* File: c/OP_UNUSED_E3FF.c */
+/* File: c/OP_UNUSED_E3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E3FF)
OP_END
-/* File: c/OP_UNUSED_E4FF.c */
+/* File: c/OP_UNUSED_E4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E4FF)
OP_END
-/* File: c/OP_UNUSED_E5FF.c */
+/* File: c/OP_UNUSED_E5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E5FF)
OP_END
-/* File: c/OP_UNUSED_E6FF.c */
+/* File: c/OP_UNUSED_E6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E6FF)
OP_END
-/* File: c/OP_UNUSED_E7FF.c */
+/* File: c/OP_UNUSED_E7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E7FF)
OP_END
-/* File: c/OP_UNUSED_E8FF.c */
+/* File: c/OP_UNUSED_E8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E8FF)
OP_END
-/* File: c/OP_UNUSED_E9FF.c */
+/* File: c/OP_UNUSED_E9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E9FF)
OP_END
-/* File: c/OP_UNUSED_EAFF.c */
+/* File: c/OP_UNUSED_EAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EAFF)
OP_END
-/* File: c/OP_UNUSED_EBFF.c */
+/* File: c/OP_UNUSED_EBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EBFF)
OP_END
-/* File: c/OP_UNUSED_ECFF.c */
+/* File: c/OP_UNUSED_ECFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ECFF)
OP_END
-/* File: c/OP_UNUSED_EDFF.c */
+/* File: c/OP_UNUSED_EDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EDFF)
OP_END
-/* File: c/OP_UNUSED_EEFF.c */
+/* File: c/OP_UNUSED_EEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EEFF)
OP_END
-/* File: c/OP_UNUSED_EFFF.c */
+/* File: c/OP_UNUSED_EFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EFFF)
OP_END
-/* File: c/OP_UNUSED_F0FF.c */
+/* File: c/OP_UNUSED_F0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_F0FF)
OP_END
-/* File: c/OP_UNUSED_F1FF.c */
+/* File: c/OP_UNUSED_F1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_F1FF)
/*
* In portable interp, most unused opcodes will fall through to here.
@@ -4269,7 +4251,7 @@
FINISH(1);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
{
Object* obj;
@@ -4300,55 +4282,55 @@
}
OP_END
-/* File: c/OP_IGET_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
+/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
vsrc1 = FETCH(3);
@@ -4357,7 +4339,7 @@
GOTO_exceptionThrown();
OP_END
-/* File: cstubs/entry.c */
+/* File: cstubs/entry.cpp */
/*
* Handler function table, one entry per opcode.
*/
@@ -4420,7 +4402,7 @@
longjmp(*pJmpBuf, 1);
}
-/* File: c/gotoTargets.c */
+/* File: c/gotoTargets.cpp */
/*
* C footer. This has some common code shared by the various targets.
*/
@@ -4510,7 +4492,7 @@
/*
* Fill in the elements. It's legal for vsrc1 to be zero.
*/
- contents = (u4*) newArray->contents;
+ contents = (u4*)(void*)newArray->contents;
if (methodCallRange) {
for (i = 0; i < vsrc1; i++)
contents[i] = GET_REGISTER(vdst+i);
@@ -4529,7 +4511,7 @@
dvmWriteBarrierArray(newArray, 0, newArray->length);
}
- retval.l = newArray;
+ retval.l = (Object*)newArray;
}
if (jumboFormat) {
FINISH(5);
@@ -5052,7 +5034,7 @@
}
/* update thread FP, and reset local variables */
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -5189,10 +5171,10 @@
#endif
/*
- * Adjust local variables to match self->curFrame and the
+ * Adjust local variables to match self->interpSave.curFrame and the
* updated PC.
*/
- //fp = (u4*) self->curFrame;
+ //fp = (u4*) self->interpSave.curFrame;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -5371,7 +5353,7 @@
* calls. For native calls, we'll mark EXIT on return.
* For non-native calls, EXIT is marked in the RETURN op.
*/
- PC_FP_TO_SELF();
+ PC_TO_SELF();
dvmReportInvoke(self, methodToCall);
}
@@ -5384,7 +5366,7 @@
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
- self->curFrame = fp = newFp;
+ self->interpSave.curFrame = fp = newFp;
#ifdef EASY_GDB
debugSaveArea = SAVEAREA_FROM_FP(newFp);
#endif
@@ -5397,13 +5379,12 @@
/* set this up for JNI locals, even if not a JNI native */
newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
- self->curFrame = newFp;
+ self->interpSave.curFrame = newFp;
DUMP_REGS(methodToCall, newFp, true); // show input args
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
+ dvmReportPreNativeInvoke(methodToCall, self, fp);
}
ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
@@ -5417,13 +5398,12 @@
(*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
+ dvmReportPostNativeInvoke(methodToCall, self, fp);
}
/* pop frame off */
dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* If the native code threw an exception, or interpreted code
@@ -5456,7 +5436,7 @@
assert(false); // should not get here
GOTO_TARGET_END
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv5te-vfp.cpp
similarity index 97%
copy from vm/mterp/out/InterpC-armv5te-vfp.c
copy to vm/mterp/out/InterpC-armv5te-vfp.cpp
index bcf03c1..246b16c 100644
--- a/vm/mterp/out/InterpC-armv5te-vfp.c
+++ b/vm/mterp/out/InterpC-armv5te-vfp.cpp
@@ -4,7 +4,7 @@
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,11 +1249,10 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
@@ -1281,7 +1263,7 @@
#undef self
#undef debugTrackedRefStart
-/* File: armv5te/debug.c */
+/* File: armv5te/debug.cpp */
#include <inttypes.h>
/*
diff --git a/vm/mterp/out/InterpC-armv5te.c b/vm/mterp/out/InterpC-armv5te.c
deleted file mode 100644
index 9d6e486..0000000
--- a/vm/mterp/out/InterpC-armv5te.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * This file was generated automatically by gen-mterp.py for 'armv5te'.
- *
- * --> DO NOT EDIT <--
- */
-
-/* File: c/header.c */
-/*
- * Copyright (C) 2008 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.
- */
-
-/* common includes */
-#include "Dalvik.h"
-#include "interp/InterpDefs.h"
-#include "mterp/Mterp.h"
-#include <math.h> // needed for fmod, fmodf
-#include "mterp/common/FindInterface.h"
-
-/*
- * Configuration defines. These affect the C implementations, i.e. the
- * portable interpreter(s) and C stubs.
- *
- * Some defines are controlled by the Makefile, e.g.:
- * WITH_INSTR_CHECKS
- * WITH_TRACKREF_CHECKS
- * EASY_GDB
- * NDEBUG
- */
-
-#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */
-# define CHECK_BRANCH_OFFSETS
-# define CHECK_REGISTER_INDICES
-#endif
-
-/*
- * Some architectures require 64-bit alignment for access to 64-bit data
- * types. We can't just use pointers to copy 64-bit values out of our
- * interpreted register set, because gcc may assume the pointer target is
- * aligned and generate invalid code.
- *
- * There are two common approaches:
- * (1) Use a union that defines a 32-bit pair and a 64-bit value.
- * (2) Call memcpy().
- *
- * Depending upon what compiler you're using and what options are specified,
- * one may be faster than the other. For example, the compiler might
- * convert a memcpy() of 8 bytes into a series of instructions and omit
- * the call. The union version could cause some strange side-effects,
- * e.g. for a while ARM gcc thought it needed separate storage for each
- * inlined instance, and generated instructions to zero out ~700 bytes of
- * stack space at the top of the interpreter.
- *
- * The default is to use memcpy(). The current gcc for ARM seems to do
- * better with the union.
- */
-#if defined(__ARM_EABI__)
-# define NO_UNALIGN_64__UNION
-#endif
-
-
-//#define LOG_INSTR /* verbose debugging */
-/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
-
-/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
- * Export another copy of the PC on every instruction; this is largely
- * redundant with EXPORT_PC and the debugger code. This value can be
- * compared against what we have stored on the stack with EXPORT_PC to
- * help ensure that we aren't missing any export calls.
- */
-#if WITH_EXTRA_GC_CHECKS > 1
-# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
-#else
-# define EXPORT_EXTRA_PC()
-#endif
-
-/*
- * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
- *
- * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
- *
- * We don't advance the program counter until we finish an instruction or
- * branch, because we do want to have to unroll the PC if there's an
- * exception.
- */
-#ifdef CHECK_BRANCH_OFFSETS
-# define ADJUST_PC(_offset) do { \
- int myoff = _offset; /* deref only once */ \
- if (pc + myoff < curMethod->insns || \
- pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
- { \
- char* desc; \
- desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
- LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
- myoff, (int) (pc - curMethod->insns), \
- curMethod->clazz->descriptor, curMethod->name, desc); \
- free(desc); \
- dvmAbort(); \
- } \
- pc += myoff; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#else
-# define ADJUST_PC(_offset) do { \
- pc += _offset; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#endif
-
-/*
- * If enabled, log instructions as we execute them.
- */
-#ifdef LOG_INSTR
-# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
-# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
-# define ILOG(_level, ...) do { \
- char debugStrBuf[128]; \
- snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
- if (curMethod != NULL) \
- LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
- self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
- else \
- LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
- self->threadId, debugStrBuf); \
- } while(false)
-void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
-# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
-static const char kSpacing[] = " ";
-#else
-# define ILOGD(...) ((void)0)
-# define ILOGV(...) ((void)0)
-# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
-#endif
-
-/* get a long from an array of u4 */
-static inline s8 getLongFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.ll;
-#else
- s8 val;
- memcpy(&val, &ptr[idx], 8);
- return val;
-#endif
-}
-
-/* store a long into an array of u4 */
-static inline void putLongToArray(u4* ptr, int idx, s8 val)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.ll = val;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &val, 8);
-#endif
-}
-
-/* get a double from an array of u4 */
-static inline double getDoubleFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.d;
-#else
- double dval;
- memcpy(&dval, &ptr[idx], 8);
- return dval;
-#endif
-}
-
-/* store a double into an array of u4 */
-static inline void putDoubleToArray(u4* ptr, int idx, double dval)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.d = dval;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &dval, 8);
-#endif
-}
-
-/*
- * If enabled, validate the register number on every access. Otherwise,
- * just do an array access.
- *
- * Assumes the existence of "u4* fp".
- *
- * "_idx" may be referenced more than once.
- */
-#ifdef CHECK_REGISTER_INDICES
-# define GET_REGISTER(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)]) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
-# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER_WIDE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_FLOAT(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
-# define SET_REGISTER_FLOAT(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
-# define GET_REGISTER_DOUBLE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
-# define SET_REGISTER_DOUBLE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
-#else
-# define GET_REGISTER(_idx) (fp[(_idx)])
-# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
-# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
-# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
-# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
-# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
-# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
-# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
-# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
-#endif
-
-/*
- * Get 16 bits from the specified offset of the program counter. We always
- * want to load 16 bits at a time from the instruction stream -- it's more
- * efficient than 8 and won't have the alignment problems that 32 might.
- *
- * Assumes existence of "const u2* pc".
- */
-#define FETCH(_offset) (pc[(_offset)])
-
-/*
- * Extract instruction byte from 16-bit fetch (_inst is a u2).
- */
-#define INST_INST(_inst) ((_inst) & 0xff)
-
-/*
- * Replace the opcode (used when handling breakpoints). _opcode is a u1.
- */
-#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
-
-/*
- * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
- */
-#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
-#define INST_B(_inst) ((_inst) >> 12)
-
-/*
- * Get the 8-bit "vAA" 8-bit register index from the instruction word.
- * (_inst is u2)
- */
-#define INST_AA(_inst) ((_inst) >> 8)
-
-/*
- * The current PC must be available to Throwable constructors, e.g.
- * those created by the various exception throw routines, so that the
- * exception stack trace can be generated correctly. If we don't do this,
- * the offset within the current method won't be shown correctly. See the
- * notes in Exception.c.
- *
- * This is also used to determine the address for precise GC.
- *
- * Assumes existence of "u4* fp" and "const u2* pc".
- */
-#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
-
-/*
- * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
- * pc has already been exported to the stack.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler calls into
- * something that could throw an exception (so we have already called
- * EXPORT_PC at the top).
- */
-static inline bool checkForNull(Object* obj)
-{
- if (obj == NULL) {
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/*
- * Check to see if "obj" is NULL. If so, export the PC into the stack
- * frame and throw an exception.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler doesn't do
- * anything else that can throw an exception.
- */
-static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
-{
- if (obj == NULL) {
- EXPORT_PC();
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/* File: cstubs/stubdefs.c */
-/*
- * In the C mterp stubs, "goto" is a function call followed immediately
- * by a return.
- */
-
-#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
-
-/* (void)xxx to quiet unused variable compiler warnings. */
-#define GOTO_TARGET(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \
- u2 ref, vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- const Method* methodToCall; \
- StackSaveArea* debugSaveArea; \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \
- (void)methodToCall; (void)debugSaveArea;
-
-#define GOTO_TARGET_END }
-
-/*
- * Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
- */
-#define retval self->retval
-#define pc self->interpSave.pc
-#define fp self->interpSave.fp
-#define curMethod self->interpSave.method
-#define methodClassDex self->interpSave.methodClassDex
-#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
-
-/* ugh */
-#define STUB_HACK(x) x
-#if defined(WITH_JIT)
-#define JIT_STUB_HACK(x) x
-#else
-#define JIT_STUB_HACK(x)
-#endif
-
-/*
- * InterpSave's pc and fp must be valid when breaking out to a
- * "Reportxxx" routine. Because the portable interpreter uses local
- * variables for these, we must flush prior. Stubs, however, use
- * the interpSave vars directly, so this is a nop for stubs.
- */
-#define PC_FP_TO_SELF()
-
-/*
- * Opcode handler framing macros. Here, each opcode is a separate function
- * that takes a "self" argument and returns void. We can't declare
- * these "static" because they may be called from an assembly stub.
- * (void)xxx to quiet unused variable compiler warnings.
- */
-#define HANDLE_OPCODE(_op) \
- void dvmMterp_##_op(Thread* self) { \
- u4 ref; \
- u2 vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
-
-#define OP_END }
-
-/*
- * Like the "portable" FINISH, but don't reload "inst", and return to caller
- * when done. Further, debugger/profiler checks are handled
- * before handler execution in mterp, so we don't do them here either.
- */
-#if defined(WITH_JIT)
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \
- dvmCheckJit(pc, self); \
- } \
- return; \
- }
-#else
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- return; \
- }
-#endif
-
-
-/*
- * The "goto label" statements turn into function calls followed by
- * return statements. Some of the functions take arguments, which in the
- * portable interpreter are handled by assigning values to globals.
- */
-
-#define GOTO_exceptionThrown() \
- do { \
- dvmMterp_exceptionThrown(self); \
- return; \
- } while(false)
-
-#define GOTO_returnFromMethod() \
- do { \
- dvmMterp_returnFromMethod(self); \
- return; \
- } while(false)
-
-#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
- do { \
- dvmMterp_##_target(self, _methodCallRange, _jumboFormat); \
- return; \
- } while(false)
-
-#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \
- do { \
- dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \
- _vsrc1, _vdst); \
- return; \
- } while(false)
-
-/*
- * As a special case, "goto bail" turns into a longjmp.
- */
-#define GOTO_bail() \
- dvmMterpStdBail(self, false);
-
-/*
- * Periodically check for thread suspension.
- *
- * While we're at it, see if a debugger has attached or the profiler has
- * started.
- */
-#define PERIODIC_CHECKS(_pcadj) { \
- if (dvmCheckSuspendQuick(self)) { \
- EXPORT_PC(); /* need for precise GC */ \
- dvmCheckSuspendPending(self); \
- } \
- }
-
-/* File: c/opcommon.c */
-/* forward declarations of goto targets */
-GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
- u2 count, u2 regs);
-GOTO_TARGET_DECL(returnFromMethod);
-GOTO_TARGET_DECL(exceptionThrown);
-
-/*
- * ===========================================================================
- *
- * What follows are opcode definitions shared between multiple opcodes with
- * minor substitutions handled by the C pre-processor. These should probably
- * use the mterp substitution mechanism instead, with the code here moved
- * into common fragment files (like the asm "binop.S"), although it's hard
- * to give up the C preprocessor in favor of the much simpler text subst.
- *
- * ===========================================================================
- */
-
-#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_totype(vdst, \
- GET_REGISTER##_fromtype(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
- _tovtype, _tortype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- { \
- /* spec defines specific handling for +/- inf and NaN values */ \
- _fromvtype val; \
- _tovtype intMin, intMax, result; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- val = GET_REGISTER##_fromrtype(vsrc1); \
- intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
- intMax = ~intMin; \
- result = (_tovtype) val; \
- if (val >= intMax) /* +inf */ \
- result = intMax; \
- else if (val <= intMin) /* -inf */ \
- result = intMin; \
- else if (val != val) /* NaN */ \
- result = 0; \
- else \
- result = (_tovtype) val; \
- SET_REGISTER##_tortype(vdst, result); \
- } \
- FINISH(1);
-
-#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
- FINISH(1);
-
-/* NOTE: the comparison result is always a signed 4-byte integer */
-#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- int result; \
- u2 regs; \
- _varType val1, val2; \
- vdst = INST_AA(inst); \
- regs = FETCH(1); \
- vsrc1 = regs & 0xff; \
- vsrc2 = regs >> 8; \
- ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- val1 = GET_REGISTER##_type(vsrc1); \
- val2 = GET_REGISTER##_type(vsrc2); \
- if (val1 == val2) \
- result = 0; \
- else if (val1 < val2) \
- result = -1; \
- else if (val1 > val2) \
- result = 1; \
- else \
- result = (_nanVal); \
- ILOGV("+ result=%d\n", result); \
- SET_REGISTER(vdst, result); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
- vsrc1 = INST_A(inst); \
- vsrc2 = INST_B(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
- branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
- FINISH(2); \
- }
-
-#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
- vsrc1 = INST_AA(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
- FINISH(2); \
- }
-
-#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
- FINISH(1);
-
-#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- secondVal = GET_REGISTER(vsrc2); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- vsrc2 = FETCH(1); \
- ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s2) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
- /* won't generate /lit16 instr for this; check anyway */ \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op (s2) vsrc2; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s1) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op ((s1) vsrc2); \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vdst); \
- secondVal = GET_REGISTER(vsrc1); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vsrc1); \
- secondVal = GET_REGISTER_WIDE(vsrc2); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vdst); \
- secondVal = GET_REGISTER_WIDE(vsrc1); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* array ptr */ \
- vsrc2 = arrayInfo >> 8; /* index */ \
- ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
- ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); /* AA: source value */ \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
- vsrc2 = arrayInfo >> 8; /* CC: index */ \
- ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
- GET_REGISTER##_regsize(vdst); \
- } \
- FINISH(2);
-
-/*
- * It's possible to get a bad value out of a field with sub-32-bit stores
- * because the -quick versions always operate on 32 bits. Consider:
- * short foo = -1 (sets a 32-bit register to 0xffffffff)
- * iput-quick foo (writes all 32 bits to the field)
- * short bar = 1 (sets a 32-bit register to 0x00000001)
- * iput-short (writes the low 16 bits to the field)
- * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
- * This can only happen when optimized and non-optimized code has interleaved
- * access to the same field. This is unlikely but possible.
- *
- * The easiest way to fix this is to always read/write 32 bits at a time. On
- * a device with a 16-bit data bus this is sub-optimal. (The alternative
- * approach is to have sub-int versions of iget-quick, but now we're wasting
- * Dalvik instruction space and making it less likely that handler code will
- * already be in the CPU i-cache.)
- */
-#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
- ILOGV("+ IGETQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUTQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-/*
- * The JIT needs dvmDexGetResolvedField() to return non-null.
- * Because the portable interpreter is not involved with the JIT
- * and trace building, we only need the extra check here when this
- * code is massaged into a stub called from an assembly interpreter.
- * This is controlled by the JIT_STUB_HACK maco.
- */
-
-#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(4);
-
-#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(4);
-
-/* File: cstubs/enddefs.c */
-
-/* undefine "magic" name remapping */
-#undef retval
-#undef pc
-#undef fp
-#undef curMethod
-#undef methodClassDex
-#undef self
-#undef debugTrackedRefStart
-
-/* File: armv5te/debug.c */
-#include <inttypes.h>
-
-/*
- * Dump the fixed-purpose ARM registers, along with some other info.
- *
- * This function MUST be compiled in ARM mode -- THUMB will yield bogus
- * results.
- *
- * This will NOT preserve r0-r3/ip.
- */
-void dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
-{
- register uint32_t rPC asm("r4");
- register uint32_t rFP asm("r5");
- register uint32_t rSELF asm("r6");
- register uint32_t rINST asm("r7");
- register uint32_t rIBASE asm("r8");
- register uint32_t r9 asm("r9");
- register uint32_t r10 asm("r10");
-
- //extern char dvmAsmInstructionStart[];
-
- printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
- printf(" : rPC=%08x rFP=%08x rSELF=%08x rINST=%08x\n",
- rPC, rFP, rSELF, rINST);
- printf(" : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
-
- //Thread* self = (Thread*) rSELF;
- //const Method* method = self->method;
- printf(" + self is %p\n", dvmThreadSelf());
- //printf(" + currently in %s.%s %s\n",
- // method->clazz->descriptor, method->name, method->shorty);
- //printf(" + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
- //printf(" + next handler for 0x%02x = %p\n",
- // rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
-}
-
-/*
- * Dump the StackSaveArea for the specified frame pointer.
- */
-void dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
-{
- StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
- printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
-#ifdef EASY_GDB
- printf(" prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
- saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc);
-#else
- printf(" prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
- saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc,
- *(u4*)fp);
-#endif
-}
-
-/*
- * Does the bulk of the work for common_printMethod().
- */
-void dvmMterpPrintMethod(Method* method)
-{
- /*
- * It is a direct (non-virtual) method if it is static, private,
- * or a constructor.
- */
- bool isDirect =
- ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
- (method->name[0] == '<');
-
- char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-
- printf("<%c:%s.%s %s> ",
- isDirect ? 'D' : 'V',
- method->clazz->descriptor,
- method->name,
- desc);
-
- free(desc);
-}
-
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv5te.cpp
similarity index 97%
copy from vm/mterp/out/InterpC-armv5te-vfp.c
copy to vm/mterp/out/InterpC-armv5te.cpp
index bcf03c1..38ad1b3 100644
--- a/vm/mterp/out/InterpC-armv5te-vfp.c
+++ b/vm/mterp/out/InterpC-armv5te.cpp
@@ -1,10 +1,10 @@
/*
- * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
+ * This file was generated automatically by gen-mterp.py for 'armv5te'.
*
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,11 +1249,10 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
@@ -1281,7 +1263,7 @@
#undef self
#undef debugTrackedRefStart
-/* File: armv5te/debug.c */
+/* File: armv5te/debug.cpp */
#include <inttypes.h>
/*
diff --git a/vm/mterp/out/InterpC-armv7-a-neon.c b/vm/mterp/out/InterpC-armv7-a-neon.c
deleted file mode 100644
index c83d470..0000000
--- a/vm/mterp/out/InterpC-armv7-a-neon.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * This file was generated automatically by gen-mterp.py for 'armv7-a-neon'.
- *
- * --> DO NOT EDIT <--
- */
-
-/* File: c/header.c */
-/*
- * Copyright (C) 2008 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.
- */
-
-/* common includes */
-#include "Dalvik.h"
-#include "interp/InterpDefs.h"
-#include "mterp/Mterp.h"
-#include <math.h> // needed for fmod, fmodf
-#include "mterp/common/FindInterface.h"
-
-/*
- * Configuration defines. These affect the C implementations, i.e. the
- * portable interpreter(s) and C stubs.
- *
- * Some defines are controlled by the Makefile, e.g.:
- * WITH_INSTR_CHECKS
- * WITH_TRACKREF_CHECKS
- * EASY_GDB
- * NDEBUG
- */
-
-#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */
-# define CHECK_BRANCH_OFFSETS
-# define CHECK_REGISTER_INDICES
-#endif
-
-/*
- * Some architectures require 64-bit alignment for access to 64-bit data
- * types. We can't just use pointers to copy 64-bit values out of our
- * interpreted register set, because gcc may assume the pointer target is
- * aligned and generate invalid code.
- *
- * There are two common approaches:
- * (1) Use a union that defines a 32-bit pair and a 64-bit value.
- * (2) Call memcpy().
- *
- * Depending upon what compiler you're using and what options are specified,
- * one may be faster than the other. For example, the compiler might
- * convert a memcpy() of 8 bytes into a series of instructions and omit
- * the call. The union version could cause some strange side-effects,
- * e.g. for a while ARM gcc thought it needed separate storage for each
- * inlined instance, and generated instructions to zero out ~700 bytes of
- * stack space at the top of the interpreter.
- *
- * The default is to use memcpy(). The current gcc for ARM seems to do
- * better with the union.
- */
-#if defined(__ARM_EABI__)
-# define NO_UNALIGN_64__UNION
-#endif
-
-
-//#define LOG_INSTR /* verbose debugging */
-/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
-
-/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
- * Export another copy of the PC on every instruction; this is largely
- * redundant with EXPORT_PC and the debugger code. This value can be
- * compared against what we have stored on the stack with EXPORT_PC to
- * help ensure that we aren't missing any export calls.
- */
-#if WITH_EXTRA_GC_CHECKS > 1
-# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
-#else
-# define EXPORT_EXTRA_PC()
-#endif
-
-/*
- * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
- *
- * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
- *
- * We don't advance the program counter until we finish an instruction or
- * branch, because we do want to have to unroll the PC if there's an
- * exception.
- */
-#ifdef CHECK_BRANCH_OFFSETS
-# define ADJUST_PC(_offset) do { \
- int myoff = _offset; /* deref only once */ \
- if (pc + myoff < curMethod->insns || \
- pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
- { \
- char* desc; \
- desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
- LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
- myoff, (int) (pc - curMethod->insns), \
- curMethod->clazz->descriptor, curMethod->name, desc); \
- free(desc); \
- dvmAbort(); \
- } \
- pc += myoff; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#else
-# define ADJUST_PC(_offset) do { \
- pc += _offset; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#endif
-
-/*
- * If enabled, log instructions as we execute them.
- */
-#ifdef LOG_INSTR
-# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
-# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
-# define ILOG(_level, ...) do { \
- char debugStrBuf[128]; \
- snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
- if (curMethod != NULL) \
- LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
- self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
- else \
- LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
- self->threadId, debugStrBuf); \
- } while(false)
-void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
-# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
-static const char kSpacing[] = " ";
-#else
-# define ILOGD(...) ((void)0)
-# define ILOGV(...) ((void)0)
-# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
-#endif
-
-/* get a long from an array of u4 */
-static inline s8 getLongFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.ll;
-#else
- s8 val;
- memcpy(&val, &ptr[idx], 8);
- return val;
-#endif
-}
-
-/* store a long into an array of u4 */
-static inline void putLongToArray(u4* ptr, int idx, s8 val)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.ll = val;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &val, 8);
-#endif
-}
-
-/* get a double from an array of u4 */
-static inline double getDoubleFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.d;
-#else
- double dval;
- memcpy(&dval, &ptr[idx], 8);
- return dval;
-#endif
-}
-
-/* store a double into an array of u4 */
-static inline void putDoubleToArray(u4* ptr, int idx, double dval)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.d = dval;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &dval, 8);
-#endif
-}
-
-/*
- * If enabled, validate the register number on every access. Otherwise,
- * just do an array access.
- *
- * Assumes the existence of "u4* fp".
- *
- * "_idx" may be referenced more than once.
- */
-#ifdef CHECK_REGISTER_INDICES
-# define GET_REGISTER(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)]) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
-# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER_WIDE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_FLOAT(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
-# define SET_REGISTER_FLOAT(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
-# define GET_REGISTER_DOUBLE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
-# define SET_REGISTER_DOUBLE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
-#else
-# define GET_REGISTER(_idx) (fp[(_idx)])
-# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
-# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
-# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
-# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
-# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
-# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
-# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
-# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
-#endif
-
-/*
- * Get 16 bits from the specified offset of the program counter. We always
- * want to load 16 bits at a time from the instruction stream -- it's more
- * efficient than 8 and won't have the alignment problems that 32 might.
- *
- * Assumes existence of "const u2* pc".
- */
-#define FETCH(_offset) (pc[(_offset)])
-
-/*
- * Extract instruction byte from 16-bit fetch (_inst is a u2).
- */
-#define INST_INST(_inst) ((_inst) & 0xff)
-
-/*
- * Replace the opcode (used when handling breakpoints). _opcode is a u1.
- */
-#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
-
-/*
- * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
- */
-#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
-#define INST_B(_inst) ((_inst) >> 12)
-
-/*
- * Get the 8-bit "vAA" 8-bit register index from the instruction word.
- * (_inst is u2)
- */
-#define INST_AA(_inst) ((_inst) >> 8)
-
-/*
- * The current PC must be available to Throwable constructors, e.g.
- * those created by the various exception throw routines, so that the
- * exception stack trace can be generated correctly. If we don't do this,
- * the offset within the current method won't be shown correctly. See the
- * notes in Exception.c.
- *
- * This is also used to determine the address for precise GC.
- *
- * Assumes existence of "u4* fp" and "const u2* pc".
- */
-#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
-
-/*
- * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
- * pc has already been exported to the stack.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler calls into
- * something that could throw an exception (so we have already called
- * EXPORT_PC at the top).
- */
-static inline bool checkForNull(Object* obj)
-{
- if (obj == NULL) {
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/*
- * Check to see if "obj" is NULL. If so, export the PC into the stack
- * frame and throw an exception.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler doesn't do
- * anything else that can throw an exception.
- */
-static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
-{
- if (obj == NULL) {
- EXPORT_PC();
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/* File: cstubs/stubdefs.c */
-/*
- * In the C mterp stubs, "goto" is a function call followed immediately
- * by a return.
- */
-
-#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
-
-/* (void)xxx to quiet unused variable compiler warnings. */
-#define GOTO_TARGET(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \
- u2 ref, vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- const Method* methodToCall; \
- StackSaveArea* debugSaveArea; \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \
- (void)methodToCall; (void)debugSaveArea;
-
-#define GOTO_TARGET_END }
-
-/*
- * Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
- */
-#define retval self->retval
-#define pc self->interpSave.pc
-#define fp self->interpSave.fp
-#define curMethod self->interpSave.method
-#define methodClassDex self->interpSave.methodClassDex
-#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
-
-/* ugh */
-#define STUB_HACK(x) x
-#if defined(WITH_JIT)
-#define JIT_STUB_HACK(x) x
-#else
-#define JIT_STUB_HACK(x)
-#endif
-
-/*
- * InterpSave's pc and fp must be valid when breaking out to a
- * "Reportxxx" routine. Because the portable interpreter uses local
- * variables for these, we must flush prior. Stubs, however, use
- * the interpSave vars directly, so this is a nop for stubs.
- */
-#define PC_FP_TO_SELF()
-
-/*
- * Opcode handler framing macros. Here, each opcode is a separate function
- * that takes a "self" argument and returns void. We can't declare
- * these "static" because they may be called from an assembly stub.
- * (void)xxx to quiet unused variable compiler warnings.
- */
-#define HANDLE_OPCODE(_op) \
- void dvmMterp_##_op(Thread* self) { \
- u4 ref; \
- u2 vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
-
-#define OP_END }
-
-/*
- * Like the "portable" FINISH, but don't reload "inst", and return to caller
- * when done. Further, debugger/profiler checks are handled
- * before handler execution in mterp, so we don't do them here either.
- */
-#if defined(WITH_JIT)
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \
- dvmCheckJit(pc, self); \
- } \
- return; \
- }
-#else
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- return; \
- }
-#endif
-
-
-/*
- * The "goto label" statements turn into function calls followed by
- * return statements. Some of the functions take arguments, which in the
- * portable interpreter are handled by assigning values to globals.
- */
-
-#define GOTO_exceptionThrown() \
- do { \
- dvmMterp_exceptionThrown(self); \
- return; \
- } while(false)
-
-#define GOTO_returnFromMethod() \
- do { \
- dvmMterp_returnFromMethod(self); \
- return; \
- } while(false)
-
-#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
- do { \
- dvmMterp_##_target(self, _methodCallRange, _jumboFormat); \
- return; \
- } while(false)
-
-#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \
- do { \
- dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \
- _vsrc1, _vdst); \
- return; \
- } while(false)
-
-/*
- * As a special case, "goto bail" turns into a longjmp.
- */
-#define GOTO_bail() \
- dvmMterpStdBail(self, false);
-
-/*
- * Periodically check for thread suspension.
- *
- * While we're at it, see if a debugger has attached or the profiler has
- * started.
- */
-#define PERIODIC_CHECKS(_pcadj) { \
- if (dvmCheckSuspendQuick(self)) { \
- EXPORT_PC(); /* need for precise GC */ \
- dvmCheckSuspendPending(self); \
- } \
- }
-
-/* File: c/opcommon.c */
-/* forward declarations of goto targets */
-GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
- u2 count, u2 regs);
-GOTO_TARGET_DECL(returnFromMethod);
-GOTO_TARGET_DECL(exceptionThrown);
-
-/*
- * ===========================================================================
- *
- * What follows are opcode definitions shared between multiple opcodes with
- * minor substitutions handled by the C pre-processor. These should probably
- * use the mterp substitution mechanism instead, with the code here moved
- * into common fragment files (like the asm "binop.S"), although it's hard
- * to give up the C preprocessor in favor of the much simpler text subst.
- *
- * ===========================================================================
- */
-
-#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_totype(vdst, \
- GET_REGISTER##_fromtype(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
- _tovtype, _tortype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- { \
- /* spec defines specific handling for +/- inf and NaN values */ \
- _fromvtype val; \
- _tovtype intMin, intMax, result; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- val = GET_REGISTER##_fromrtype(vsrc1); \
- intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
- intMax = ~intMin; \
- result = (_tovtype) val; \
- if (val >= intMax) /* +inf */ \
- result = intMax; \
- else if (val <= intMin) /* -inf */ \
- result = intMin; \
- else if (val != val) /* NaN */ \
- result = 0; \
- else \
- result = (_tovtype) val; \
- SET_REGISTER##_tortype(vdst, result); \
- } \
- FINISH(1);
-
-#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
- FINISH(1);
-
-/* NOTE: the comparison result is always a signed 4-byte integer */
-#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- int result; \
- u2 regs; \
- _varType val1, val2; \
- vdst = INST_AA(inst); \
- regs = FETCH(1); \
- vsrc1 = regs & 0xff; \
- vsrc2 = regs >> 8; \
- ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- val1 = GET_REGISTER##_type(vsrc1); \
- val2 = GET_REGISTER##_type(vsrc2); \
- if (val1 == val2) \
- result = 0; \
- else if (val1 < val2) \
- result = -1; \
- else if (val1 > val2) \
- result = 1; \
- else \
- result = (_nanVal); \
- ILOGV("+ result=%d\n", result); \
- SET_REGISTER(vdst, result); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
- vsrc1 = INST_A(inst); \
- vsrc2 = INST_B(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
- branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
- FINISH(2); \
- }
-
-#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
- vsrc1 = INST_AA(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
- FINISH(2); \
- }
-
-#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
- FINISH(1);
-
-#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- secondVal = GET_REGISTER(vsrc2); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- vsrc2 = FETCH(1); \
- ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s2) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
- /* won't generate /lit16 instr for this; check anyway */ \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op (s2) vsrc2; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s1) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op ((s1) vsrc2); \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vdst); \
- secondVal = GET_REGISTER(vsrc1); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vsrc1); \
- secondVal = GET_REGISTER_WIDE(vsrc2); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vdst); \
- secondVal = GET_REGISTER_WIDE(vsrc1); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* array ptr */ \
- vsrc2 = arrayInfo >> 8; /* index */ \
- ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
- ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); /* AA: source value */ \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
- vsrc2 = arrayInfo >> 8; /* CC: index */ \
- ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
- GET_REGISTER##_regsize(vdst); \
- } \
- FINISH(2);
-
-/*
- * It's possible to get a bad value out of a field with sub-32-bit stores
- * because the -quick versions always operate on 32 bits. Consider:
- * short foo = -1 (sets a 32-bit register to 0xffffffff)
- * iput-quick foo (writes all 32 bits to the field)
- * short bar = 1 (sets a 32-bit register to 0x00000001)
- * iput-short (writes the low 16 bits to the field)
- * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
- * This can only happen when optimized and non-optimized code has interleaved
- * access to the same field. This is unlikely but possible.
- *
- * The easiest way to fix this is to always read/write 32 bits at a time. On
- * a device with a 16-bit data bus this is sub-optimal. (The alternative
- * approach is to have sub-int versions of iget-quick, but now we're wasting
- * Dalvik instruction space and making it less likely that handler code will
- * already be in the CPU i-cache.)
- */
-#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
- ILOGV("+ IGETQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUTQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-/*
- * The JIT needs dvmDexGetResolvedField() to return non-null.
- * Because the portable interpreter is not involved with the JIT
- * and trace building, we only need the extra check here when this
- * code is massaged into a stub called from an assembly interpreter.
- * This is controlled by the JIT_STUB_HACK maco.
- */
-
-#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(4);
-
-#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(4);
-
-/* File: cstubs/enddefs.c */
-
-/* undefine "magic" name remapping */
-#undef retval
-#undef pc
-#undef fp
-#undef curMethod
-#undef methodClassDex
-#undef self
-#undef debugTrackedRefStart
-
-/* File: armv5te/debug.c */
-#include <inttypes.h>
-
-/*
- * Dump the fixed-purpose ARM registers, along with some other info.
- *
- * This function MUST be compiled in ARM mode -- THUMB will yield bogus
- * results.
- *
- * This will NOT preserve r0-r3/ip.
- */
-void dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
-{
- register uint32_t rPC asm("r4");
- register uint32_t rFP asm("r5");
- register uint32_t rSELF asm("r6");
- register uint32_t rINST asm("r7");
- register uint32_t rIBASE asm("r8");
- register uint32_t r9 asm("r9");
- register uint32_t r10 asm("r10");
-
- //extern char dvmAsmInstructionStart[];
-
- printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
- printf(" : rPC=%08x rFP=%08x rSELF=%08x rINST=%08x\n",
- rPC, rFP, rSELF, rINST);
- printf(" : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
-
- //Thread* self = (Thread*) rSELF;
- //const Method* method = self->method;
- printf(" + self is %p\n", dvmThreadSelf());
- //printf(" + currently in %s.%s %s\n",
- // method->clazz->descriptor, method->name, method->shorty);
- //printf(" + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
- //printf(" + next handler for 0x%02x = %p\n",
- // rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
-}
-
-/*
- * Dump the StackSaveArea for the specified frame pointer.
- */
-void dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
-{
- StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
- printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
-#ifdef EASY_GDB
- printf(" prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
- saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc);
-#else
- printf(" prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
- saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc,
- *(u4*)fp);
-#endif
-}
-
-/*
- * Does the bulk of the work for common_printMethod().
- */
-void dvmMterpPrintMethod(Method* method)
-{
- /*
- * It is a direct (non-virtual) method if it is static, private,
- * or a constructor.
- */
- bool isDirect =
- ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
- (method->name[0] == '<');
-
- char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-
- printf("<%c:%s.%s %s> ",
- isDirect ? 'D' : 'V',
- method->clazz->descriptor,
- method->name,
- desc);
-
- free(desc);
-}
-
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv7-a-neon.cpp
similarity index 97%
rename from vm/mterp/out/InterpC-armv5te-vfp.c
rename to vm/mterp/out/InterpC-armv7-a-neon.cpp
index bcf03c1..097bcc8 100644
--- a/vm/mterp/out/InterpC-armv5te-vfp.c
+++ b/vm/mterp/out/InterpC-armv7-a-neon.cpp
@@ -1,10 +1,10 @@
/*
- * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
+ * This file was generated automatically by gen-mterp.py for 'armv7-a-neon'.
*
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,11 +1249,10 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
@@ -1281,7 +1263,7 @@
#undef self
#undef debugTrackedRefStart
-/* File: armv5te/debug.c */
+/* File: armv5te/debug.cpp */
#include <inttypes.h>
/*
diff --git a/vm/mterp/out/InterpC-armv7-a.c b/vm/mterp/out/InterpC-armv7-a.c
deleted file mode 100644
index 98b8a7d..0000000
--- a/vm/mterp/out/InterpC-armv7-a.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * This file was generated automatically by gen-mterp.py for 'armv7-a'.
- *
- * --> DO NOT EDIT <--
- */
-
-/* File: c/header.c */
-/*
- * Copyright (C) 2008 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.
- */
-
-/* common includes */
-#include "Dalvik.h"
-#include "interp/InterpDefs.h"
-#include "mterp/Mterp.h"
-#include <math.h> // needed for fmod, fmodf
-#include "mterp/common/FindInterface.h"
-
-/*
- * Configuration defines. These affect the C implementations, i.e. the
- * portable interpreter(s) and C stubs.
- *
- * Some defines are controlled by the Makefile, e.g.:
- * WITH_INSTR_CHECKS
- * WITH_TRACKREF_CHECKS
- * EASY_GDB
- * NDEBUG
- */
-
-#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */
-# define CHECK_BRANCH_OFFSETS
-# define CHECK_REGISTER_INDICES
-#endif
-
-/*
- * Some architectures require 64-bit alignment for access to 64-bit data
- * types. We can't just use pointers to copy 64-bit values out of our
- * interpreted register set, because gcc may assume the pointer target is
- * aligned and generate invalid code.
- *
- * There are two common approaches:
- * (1) Use a union that defines a 32-bit pair and a 64-bit value.
- * (2) Call memcpy().
- *
- * Depending upon what compiler you're using and what options are specified,
- * one may be faster than the other. For example, the compiler might
- * convert a memcpy() of 8 bytes into a series of instructions and omit
- * the call. The union version could cause some strange side-effects,
- * e.g. for a while ARM gcc thought it needed separate storage for each
- * inlined instance, and generated instructions to zero out ~700 bytes of
- * stack space at the top of the interpreter.
- *
- * The default is to use memcpy(). The current gcc for ARM seems to do
- * better with the union.
- */
-#if defined(__ARM_EABI__)
-# define NO_UNALIGN_64__UNION
-#endif
-
-
-//#define LOG_INSTR /* verbose debugging */
-/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
-
-/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
- * Export another copy of the PC on every instruction; this is largely
- * redundant with EXPORT_PC and the debugger code. This value can be
- * compared against what we have stored on the stack with EXPORT_PC to
- * help ensure that we aren't missing any export calls.
- */
-#if WITH_EXTRA_GC_CHECKS > 1
-# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
-#else
-# define EXPORT_EXTRA_PC()
-#endif
-
-/*
- * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
- *
- * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
- *
- * We don't advance the program counter until we finish an instruction or
- * branch, because we do want to have to unroll the PC if there's an
- * exception.
- */
-#ifdef CHECK_BRANCH_OFFSETS
-# define ADJUST_PC(_offset) do { \
- int myoff = _offset; /* deref only once */ \
- if (pc + myoff < curMethod->insns || \
- pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
- { \
- char* desc; \
- desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
- LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
- myoff, (int) (pc - curMethod->insns), \
- curMethod->clazz->descriptor, curMethod->name, desc); \
- free(desc); \
- dvmAbort(); \
- } \
- pc += myoff; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#else
-# define ADJUST_PC(_offset) do { \
- pc += _offset; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#endif
-
-/*
- * If enabled, log instructions as we execute them.
- */
-#ifdef LOG_INSTR
-# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
-# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
-# define ILOG(_level, ...) do { \
- char debugStrBuf[128]; \
- snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
- if (curMethod != NULL) \
- LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
- self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
- else \
- LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
- self->threadId, debugStrBuf); \
- } while(false)
-void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
-# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
-static const char kSpacing[] = " ";
-#else
-# define ILOGD(...) ((void)0)
-# define ILOGV(...) ((void)0)
-# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
-#endif
-
-/* get a long from an array of u4 */
-static inline s8 getLongFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.ll;
-#else
- s8 val;
- memcpy(&val, &ptr[idx], 8);
- return val;
-#endif
-}
-
-/* store a long into an array of u4 */
-static inline void putLongToArray(u4* ptr, int idx, s8 val)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.ll = val;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &val, 8);
-#endif
-}
-
-/* get a double from an array of u4 */
-static inline double getDoubleFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.d;
-#else
- double dval;
- memcpy(&dval, &ptr[idx], 8);
- return dval;
-#endif
-}
-
-/* store a double into an array of u4 */
-static inline void putDoubleToArray(u4* ptr, int idx, double dval)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.d = dval;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &dval, 8);
-#endif
-}
-
-/*
- * If enabled, validate the register number on every access. Otherwise,
- * just do an array access.
- *
- * Assumes the existence of "u4* fp".
- *
- * "_idx" may be referenced more than once.
- */
-#ifdef CHECK_REGISTER_INDICES
-# define GET_REGISTER(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)]) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
-# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER_WIDE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_FLOAT(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
-# define SET_REGISTER_FLOAT(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
-# define GET_REGISTER_DOUBLE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
-# define SET_REGISTER_DOUBLE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
-#else
-# define GET_REGISTER(_idx) (fp[(_idx)])
-# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
-# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
-# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
-# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
-# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
-# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
-# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
-# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
-#endif
-
-/*
- * Get 16 bits from the specified offset of the program counter. We always
- * want to load 16 bits at a time from the instruction stream -- it's more
- * efficient than 8 and won't have the alignment problems that 32 might.
- *
- * Assumes existence of "const u2* pc".
- */
-#define FETCH(_offset) (pc[(_offset)])
-
-/*
- * Extract instruction byte from 16-bit fetch (_inst is a u2).
- */
-#define INST_INST(_inst) ((_inst) & 0xff)
-
-/*
- * Replace the opcode (used when handling breakpoints). _opcode is a u1.
- */
-#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
-
-/*
- * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
- */
-#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
-#define INST_B(_inst) ((_inst) >> 12)
-
-/*
- * Get the 8-bit "vAA" 8-bit register index from the instruction word.
- * (_inst is u2)
- */
-#define INST_AA(_inst) ((_inst) >> 8)
-
-/*
- * The current PC must be available to Throwable constructors, e.g.
- * those created by the various exception throw routines, so that the
- * exception stack trace can be generated correctly. If we don't do this,
- * the offset within the current method won't be shown correctly. See the
- * notes in Exception.c.
- *
- * This is also used to determine the address for precise GC.
- *
- * Assumes existence of "u4* fp" and "const u2* pc".
- */
-#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
-
-/*
- * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
- * pc has already been exported to the stack.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler calls into
- * something that could throw an exception (so we have already called
- * EXPORT_PC at the top).
- */
-static inline bool checkForNull(Object* obj)
-{
- if (obj == NULL) {
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/*
- * Check to see if "obj" is NULL. If so, export the PC into the stack
- * frame and throw an exception.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler doesn't do
- * anything else that can throw an exception.
- */
-static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
-{
- if (obj == NULL) {
- EXPORT_PC();
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/* File: cstubs/stubdefs.c */
-/*
- * In the C mterp stubs, "goto" is a function call followed immediately
- * by a return.
- */
-
-#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
-
-/* (void)xxx to quiet unused variable compiler warnings. */
-#define GOTO_TARGET(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \
- u2 ref, vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- const Method* methodToCall; \
- StackSaveArea* debugSaveArea; \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \
- (void)methodToCall; (void)debugSaveArea;
-
-#define GOTO_TARGET_END }
-
-/*
- * Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
- */
-#define retval self->retval
-#define pc self->interpSave.pc
-#define fp self->interpSave.fp
-#define curMethod self->interpSave.method
-#define methodClassDex self->interpSave.methodClassDex
-#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
-
-/* ugh */
-#define STUB_HACK(x) x
-#if defined(WITH_JIT)
-#define JIT_STUB_HACK(x) x
-#else
-#define JIT_STUB_HACK(x)
-#endif
-
-/*
- * InterpSave's pc and fp must be valid when breaking out to a
- * "Reportxxx" routine. Because the portable interpreter uses local
- * variables for these, we must flush prior. Stubs, however, use
- * the interpSave vars directly, so this is a nop for stubs.
- */
-#define PC_FP_TO_SELF()
-
-/*
- * Opcode handler framing macros. Here, each opcode is a separate function
- * that takes a "self" argument and returns void. We can't declare
- * these "static" because they may be called from an assembly stub.
- * (void)xxx to quiet unused variable compiler warnings.
- */
-#define HANDLE_OPCODE(_op) \
- void dvmMterp_##_op(Thread* self) { \
- u4 ref; \
- u2 vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
-
-#define OP_END }
-
-/*
- * Like the "portable" FINISH, but don't reload "inst", and return to caller
- * when done. Further, debugger/profiler checks are handled
- * before handler execution in mterp, so we don't do them here either.
- */
-#if defined(WITH_JIT)
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \
- dvmCheckJit(pc, self); \
- } \
- return; \
- }
-#else
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- return; \
- }
-#endif
-
-
-/*
- * The "goto label" statements turn into function calls followed by
- * return statements. Some of the functions take arguments, which in the
- * portable interpreter are handled by assigning values to globals.
- */
-
-#define GOTO_exceptionThrown() \
- do { \
- dvmMterp_exceptionThrown(self); \
- return; \
- } while(false)
-
-#define GOTO_returnFromMethod() \
- do { \
- dvmMterp_returnFromMethod(self); \
- return; \
- } while(false)
-
-#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
- do { \
- dvmMterp_##_target(self, _methodCallRange, _jumboFormat); \
- return; \
- } while(false)
-
-#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \
- do { \
- dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \
- _vsrc1, _vdst); \
- return; \
- } while(false)
-
-/*
- * As a special case, "goto bail" turns into a longjmp.
- */
-#define GOTO_bail() \
- dvmMterpStdBail(self, false);
-
-/*
- * Periodically check for thread suspension.
- *
- * While we're at it, see if a debugger has attached or the profiler has
- * started.
- */
-#define PERIODIC_CHECKS(_pcadj) { \
- if (dvmCheckSuspendQuick(self)) { \
- EXPORT_PC(); /* need for precise GC */ \
- dvmCheckSuspendPending(self); \
- } \
- }
-
-/* File: c/opcommon.c */
-/* forward declarations of goto targets */
-GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
- u2 count, u2 regs);
-GOTO_TARGET_DECL(returnFromMethod);
-GOTO_TARGET_DECL(exceptionThrown);
-
-/*
- * ===========================================================================
- *
- * What follows are opcode definitions shared between multiple opcodes with
- * minor substitutions handled by the C pre-processor. These should probably
- * use the mterp substitution mechanism instead, with the code here moved
- * into common fragment files (like the asm "binop.S"), although it's hard
- * to give up the C preprocessor in favor of the much simpler text subst.
- *
- * ===========================================================================
- */
-
-#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_totype(vdst, \
- GET_REGISTER##_fromtype(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
- _tovtype, _tortype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- { \
- /* spec defines specific handling for +/- inf and NaN values */ \
- _fromvtype val; \
- _tovtype intMin, intMax, result; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- val = GET_REGISTER##_fromrtype(vsrc1); \
- intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
- intMax = ~intMin; \
- result = (_tovtype) val; \
- if (val >= intMax) /* +inf */ \
- result = intMax; \
- else if (val <= intMin) /* -inf */ \
- result = intMin; \
- else if (val != val) /* NaN */ \
- result = 0; \
- else \
- result = (_tovtype) val; \
- SET_REGISTER##_tortype(vdst, result); \
- } \
- FINISH(1);
-
-#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
- FINISH(1);
-
-/* NOTE: the comparison result is always a signed 4-byte integer */
-#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- int result; \
- u2 regs; \
- _varType val1, val2; \
- vdst = INST_AA(inst); \
- regs = FETCH(1); \
- vsrc1 = regs & 0xff; \
- vsrc2 = regs >> 8; \
- ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- val1 = GET_REGISTER##_type(vsrc1); \
- val2 = GET_REGISTER##_type(vsrc2); \
- if (val1 == val2) \
- result = 0; \
- else if (val1 < val2) \
- result = -1; \
- else if (val1 > val2) \
- result = 1; \
- else \
- result = (_nanVal); \
- ILOGV("+ result=%d\n", result); \
- SET_REGISTER(vdst, result); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
- vsrc1 = INST_A(inst); \
- vsrc2 = INST_B(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
- branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
- FINISH(2); \
- }
-
-#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
- vsrc1 = INST_AA(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
- FINISH(2); \
- }
-
-#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
- FINISH(1);
-
-#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- secondVal = GET_REGISTER(vsrc2); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- vsrc2 = FETCH(1); \
- ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s2) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
- /* won't generate /lit16 instr for this; check anyway */ \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op (s2) vsrc2; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s1) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op ((s1) vsrc2); \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vdst); \
- secondVal = GET_REGISTER(vsrc1); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vsrc1); \
- secondVal = GET_REGISTER_WIDE(vsrc2); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vdst); \
- secondVal = GET_REGISTER_WIDE(vsrc1); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* array ptr */ \
- vsrc2 = arrayInfo >> 8; /* index */ \
- ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
- ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); /* AA: source value */ \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
- vsrc2 = arrayInfo >> 8; /* CC: index */ \
- ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
- GET_REGISTER##_regsize(vdst); \
- } \
- FINISH(2);
-
-/*
- * It's possible to get a bad value out of a field with sub-32-bit stores
- * because the -quick versions always operate on 32 bits. Consider:
- * short foo = -1 (sets a 32-bit register to 0xffffffff)
- * iput-quick foo (writes all 32 bits to the field)
- * short bar = 1 (sets a 32-bit register to 0x00000001)
- * iput-short (writes the low 16 bits to the field)
- * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
- * This can only happen when optimized and non-optimized code has interleaved
- * access to the same field. This is unlikely but possible.
- *
- * The easiest way to fix this is to always read/write 32 bits at a time. On
- * a device with a 16-bit data bus this is sub-optimal. (The alternative
- * approach is to have sub-int versions of iget-quick, but now we're wasting
- * Dalvik instruction space and making it less likely that handler code will
- * already be in the CPU i-cache.)
- */
-#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
- ILOGV("+ IGETQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUTQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-/*
- * The JIT needs dvmDexGetResolvedField() to return non-null.
- * Because the portable interpreter is not involved with the JIT
- * and trace building, we only need the extra check here when this
- * code is massaged into a stub called from an assembly interpreter.
- * This is controlled by the JIT_STUB_HACK maco.
- */
-
-#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(4);
-
-#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(4);
-
-/* File: cstubs/enddefs.c */
-
-/* undefine "magic" name remapping */
-#undef retval
-#undef pc
-#undef fp
-#undef curMethod
-#undef methodClassDex
-#undef self
-#undef debugTrackedRefStart
-
-/* File: armv5te/debug.c */
-#include <inttypes.h>
-
-/*
- * Dump the fixed-purpose ARM registers, along with some other info.
- *
- * This function MUST be compiled in ARM mode -- THUMB will yield bogus
- * results.
- *
- * This will NOT preserve r0-r3/ip.
- */
-void dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
-{
- register uint32_t rPC asm("r4");
- register uint32_t rFP asm("r5");
- register uint32_t rSELF asm("r6");
- register uint32_t rINST asm("r7");
- register uint32_t rIBASE asm("r8");
- register uint32_t r9 asm("r9");
- register uint32_t r10 asm("r10");
-
- //extern char dvmAsmInstructionStart[];
-
- printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
- printf(" : rPC=%08x rFP=%08x rSELF=%08x rINST=%08x\n",
- rPC, rFP, rSELF, rINST);
- printf(" : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
-
- //Thread* self = (Thread*) rSELF;
- //const Method* method = self->method;
- printf(" + self is %p\n", dvmThreadSelf());
- //printf(" + currently in %s.%s %s\n",
- // method->clazz->descriptor, method->name, method->shorty);
- //printf(" + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
- //printf(" + next handler for 0x%02x = %p\n",
- // rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
-}
-
-/*
- * Dump the StackSaveArea for the specified frame pointer.
- */
-void dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
-{
- StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
- printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
-#ifdef EASY_GDB
- printf(" prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
- saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc);
-#else
- printf(" prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
- saveArea->prevFrame, saveArea->savedPc,
- saveArea->method, saveArea->xtra.currentPc,
- *(u4*)fp);
-#endif
-}
-
-/*
- * Does the bulk of the work for common_printMethod().
- */
-void dvmMterpPrintMethod(Method* method)
-{
- /*
- * It is a direct (non-virtual) method if it is static, private,
- * or a constructor.
- */
- bool isDirect =
- ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
- (method->name[0] == '<');
-
- char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-
- printf("<%c:%s.%s %s> ",
- isDirect ? 'D' : 'V',
- method->clazz->descriptor,
- method->name,
- desc);
-
- free(desc);
-}
-
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv7-a.cpp
similarity index 97%
copy from vm/mterp/out/InterpC-armv5te-vfp.c
copy to vm/mterp/out/InterpC-armv7-a.cpp
index bcf03c1..dfbc45d 100644
--- a/vm/mterp/out/InterpC-armv5te-vfp.c
+++ b/vm/mterp/out/InterpC-armv7-a.cpp
@@ -1,10 +1,10 @@
/*
- * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
+ * This file was generated automatically by gen-mterp.py for 'armv7-a'.
*
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,11 +1249,10 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
@@ -1281,7 +1263,7 @@
#undef self
#undef debugTrackedRefStart
-/* File: armv5te/debug.c */
+/* File: armv5te/debug.cpp */
#include <inttypes.h>
/*
diff --git a/vm/mterp/out/InterpC-portable.c b/vm/mterp/out/InterpC-portable.cpp
similarity index 89%
rename from vm/mterp/out/InterpC-portable.c
rename to vm/mterp/out/InterpC-portable.cpp
index 425885e..6c6da98 100644
--- a/vm/mterp/out/InterpC-portable.c
+++ b/vm/mterp/out/InterpC-portable.cpp
@@ -4,7 +4,7 @@
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,7 +367,7 @@
return true;
}
-/* File: portable/stubdefs.c */
+/* File: portable/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
@@ -403,7 +391,8 @@
*/
#define PC_FP_TO_SELF() \
self->interpSave.pc = pc; \
- self->interpSave.fp = fp;
+ self->interpSave.curFrame = fp;
+#define PC_TO_SELF() self->interpSave.pc = pc;
/*
* Instruction framing. For a switch-oriented implementation this is
@@ -466,7 +455,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -926,7 +915,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -951,7 +940,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -996,7 +985,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1024,7 +1012,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1069,7 +1056,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1097,7 +1083,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1147,7 +1132,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1171,7 +1155,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1195,7 +1178,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1219,11 +1201,10 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: portable/entry.c */
+/* File: portable/entry.cpp */
/*
* Main interpreter loop.
*
@@ -1232,7 +1213,7 @@
void dvmInterpretPortable(Thread* self)
{
#if defined(EASY_GDB)
- StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
#endif
#if defined(WITH_TRACKREF_CHECKS)
int debugTrackedRefStart = self->interpSave.debugTrackedRefStart;
@@ -1260,7 +1241,7 @@
/* copy state in */
curMethod = self->interpSave.method;
pc = self->interpSave.pc;
- fp = self->interpSave.fp;
+ fp = self->interpSave.curFrame;
retval = self->retval; /* only need for kInterpEntryReturn? */
methodClassDex = curMethod->clazz->pDvmDex;
@@ -1285,7 +1266,7 @@
if (self->debugIsMethodEntry) {
ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
curMethod->name);
- DUMP_REGS(curMethod, self->interpSave.fp, false);
+ DUMP_REGS(curMethod, self->interpSave.curFrame, false);
}
#endif
@@ -1293,12 +1274,12 @@
/*--- start of opcodes ---*/
-/* File: c/OP_NOP.c */
+/* File: c/OP_NOP.cpp */
HANDLE_OPCODE(OP_NOP)
FINISH(1);
OP_END
-/* File: c/OP_MOVE.c */
+/* File: c/OP_MOVE.cpp */
HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -1309,7 +1290,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_FROM16.c */
+/* File: c/OP_MOVE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1320,7 +1301,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MOVE_16.c */
+/* File: c/OP_MOVE_16.cpp */
HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1331,7 +1312,7 @@
FINISH(3);
OP_END
-/* File: c/OP_MOVE_WIDE.c */
+/* File: c/OP_MOVE_WIDE.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/)
/* IMPORTANT: must correctly handle overlapping registers, e.g. both
* "move-wide v6, v7" and "move-wide v7, v6" */
@@ -1343,7 +1324,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_WIDE_FROM16.c */
+/* File: c/OP_MOVE_WIDE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1353,7 +1334,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MOVE_WIDE_16.c */
+/* File: c/OP_MOVE_WIDE_16.cpp */
HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1363,8 +1344,8 @@
FINISH(3);
OP_END
-/* File: c/OP_MOVE_OBJECT.c */
-/* File: c/OP_MOVE.c */
+/* File: c/OP_MOVE_OBJECT.cpp */
+/* File: c/OP_MOVE.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -1376,8 +1357,8 @@
OP_END
-/* File: c/OP_MOVE_OBJECT_FROM16.c */
-/* File: c/OP_MOVE_FROM16.c */
+/* File: c/OP_MOVE_OBJECT_FROM16.cpp */
+/* File: c/OP_MOVE_FROM16.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1389,8 +1370,8 @@
OP_END
-/* File: c/OP_MOVE_OBJECT_16.c */
-/* File: c/OP_MOVE_16.c */
+/* File: c/OP_MOVE_OBJECT_16.cpp */
+/* File: c/OP_MOVE_16.cpp */
HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/)
vdst = FETCH(1);
vsrc1 = FETCH(2);
@@ -1402,7 +1383,7 @@
OP_END
-/* File: c/OP_MOVE_RESULT.c */
+/* File: c/OP_MOVE_RESULT.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
@@ -1412,7 +1393,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_RESULT_WIDE.c */
+/* File: c/OP_MOVE_RESULT_WIDE.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j);
@@ -1420,8 +1401,8 @@
FINISH(1);
OP_END
-/* File: c/OP_MOVE_RESULT_OBJECT.c */
-/* File: c/OP_MOVE_RESULT.c */
+/* File: c/OP_MOVE_RESULT_OBJECT.cpp */
+/* File: c/OP_MOVE_RESULT.cpp */
HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
@@ -1432,7 +1413,7 @@
OP_END
-/* File: c/OP_MOVE_EXCEPTION.c */
+/* File: c/OP_MOVE_EXCEPTION.cpp */
HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/)
vdst = INST_AA(inst);
ILOGV("|move-exception v%d", vdst);
@@ -1442,7 +1423,7 @@
FINISH(1);
OP_END
-/* File: c/OP_RETURN_VOID.c */
+/* File: c/OP_RETURN_VOID.cpp */
HANDLE_OPCODE(OP_RETURN_VOID /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -1451,7 +1432,7 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN.c */
+/* File: c/OP_RETURN.cpp */
HANDLE_OPCODE(OP_RETURN /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return%s v%d",
@@ -1460,7 +1441,7 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN_WIDE.c */
+/* File: c/OP_RETURN_WIDE.cpp */
HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return-wide v%d", vsrc1);
@@ -1468,8 +1449,8 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_RETURN_OBJECT.c */
-/* File: c/OP_RETURN.c */
+/* File: c/OP_RETURN_OBJECT.cpp */
+/* File: c/OP_RETURN.cpp */
HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/)
vsrc1 = INST_AA(inst);
ILOGV("|return%s v%d",
@@ -1479,7 +1460,7 @@
OP_END
-/* File: c/OP_CONST_4.c */
+/* File: c/OP_CONST_4.cpp */
HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/)
{
s4 tmp;
@@ -1492,7 +1473,7 @@
FINISH(1);
OP_END
-/* File: c/OP_CONST_16.c */
+/* File: c/OP_CONST_16.cpp */
HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1501,7 +1482,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST.c */
+/* File: c/OP_CONST.cpp */
HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/)
{
u4 tmp;
@@ -1515,7 +1496,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_HIGH16.c */
+/* File: c/OP_CONST_HIGH16.cpp */
HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1524,7 +1505,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_WIDE_16.c */
+/* File: c/OP_CONST_WIDE_16.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1533,7 +1514,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_WIDE_32.c */
+/* File: c/OP_CONST_WIDE_32.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/)
{
u4 tmp;
@@ -1547,7 +1528,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_WIDE.c */
+/* File: c/OP_CONST_WIDE.cpp */
HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/)
{
u8 tmp;
@@ -1563,7 +1544,7 @@
FINISH(5);
OP_END
-/* File: c/OP_CONST_WIDE_HIGH16.c */
+/* File: c/OP_CONST_WIDE_HIGH16.cpp */
HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/)
vdst = INST_AA(inst);
vsrc1 = FETCH(1);
@@ -1572,7 +1553,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_STRING.c */
+/* File: c/OP_CONST_STRING.cpp */
HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
{
StringObject* strObj;
@@ -1592,7 +1573,7 @@
FINISH(2);
OP_END
-/* File: c/OP_CONST_STRING_JUMBO.c */
+/* File: c/OP_CONST_STRING_JUMBO.cpp */
HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/)
{
StringObject* strObj;
@@ -1614,7 +1595,7 @@
FINISH(3);
OP_END
-/* File: c/OP_CONST_CLASS.c */
+/* File: c/OP_CONST_CLASS.cpp */
HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1634,7 +1615,7 @@
FINISH(2);
OP_END
-/* File: c/OP_MONITOR_ENTER.c */
+/* File: c/OP_MONITOR_ENTER.cpp */
HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/)
{
Object* obj;
@@ -1652,7 +1633,7 @@
FINISH(1);
OP_END
-/* File: c/OP_MONITOR_EXIT.c */
+/* File: c/OP_MONITOR_EXIT.cpp */
HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/)
{
Object* obj;
@@ -1684,7 +1665,7 @@
FINISH(1);
OP_END
-/* File: c/OP_CHECK_CAST.c */
+/* File: c/OP_CHECK_CAST.cpp */
HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1717,7 +1698,7 @@
FINISH(2);
OP_END
-/* File: c/OP_INSTANCE_OF.c */
+/* File: c/OP_INSTANCE_OF.cpp */
HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/)
{
ClassObject* clazz;
@@ -1749,7 +1730,7 @@
FINISH(2);
OP_END
-/* File: c/OP_ARRAY_LENGTH.c */
+/* File: c/OP_ARRAY_LENGTH.cpp */
HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/)
{
ArrayObject* arrayObj;
@@ -1766,7 +1747,7 @@
FINISH(1);
OP_END
-/* File: c/OP_NEW_INSTANCE.c */
+/* File: c/OP_NEW_INSTANCE.cpp */
HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/)
{
ClassObject* clazz;
@@ -1816,7 +1797,7 @@
FINISH(2);
OP_END
-/* File: c/OP_NEW_ARRAY.c */
+/* File: c/OP_NEW_ARRAY.cpp */
HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/)
{
ClassObject* arrayClass;
@@ -1853,17 +1834,17 @@
FINISH(2);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY.c */
+/* File: c/OP_FILLED_NEW_ARRAY.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/)
GOTO_invoke(filledNewArray, false, false);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY_RANGE.c */
+/* File: c/OP_FILLED_NEW_ARRAY_RANGE.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/)
GOTO_invoke(filledNewArray, true, false);
OP_END
-/* File: c/OP_FILL_ARRAY_DATA.c */
+/* File: c/OP_FILL_ARRAY_DATA.cpp */
HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/
{
const u2* arrayData;
@@ -1892,7 +1873,7 @@
}
OP_END
-/* File: c/OP_THROW.c */
+/* File: c/OP_THROW.cpp */
HANDLE_OPCODE(OP_THROW /*vAA*/)
{
Object* obj;
@@ -1918,7 +1899,7 @@
}
OP_END
-/* File: c/OP_GOTO.c */
+/* File: c/OP_GOTO.cpp */
HANDLE_OPCODE(OP_GOTO /*+AA*/)
vdst = INST_AA(inst);
if ((s1)vdst < 0)
@@ -1931,7 +1912,7 @@
FINISH((s1)vdst);
OP_END
-/* File: c/OP_GOTO_16.c */
+/* File: c/OP_GOTO_16.cpp */
HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/)
{
s4 offset = (s2) FETCH(1); /* sign-extend next code unit */
@@ -1947,7 +1928,7 @@
}
OP_END
-/* File: c/OP_GOTO_32.c */
+/* File: c/OP_GOTO_32.cpp */
HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/)
{
s4 offset = FETCH(1); /* low-order 16 bits */
@@ -1964,7 +1945,7 @@
}
OP_END
-/* File: c/OP_PACKED_SWITCH.c */
+/* File: c/OP_PACKED_SWITCH.cpp */
HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/)
{
const u2* switchData;
@@ -1995,7 +1976,7 @@
}
OP_END
-/* File: c/OP_SPARSE_SWITCH.c */
+/* File: c/OP_SPARSE_SWITCH.cpp */
HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/)
{
const u2* switchData;
@@ -2026,135 +2007,135 @@
}
OP_END
-/* File: c/OP_CMPL_FLOAT.c */
+/* File: c/OP_CMPL_FLOAT.cpp */
HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1)
OP_END
-/* File: c/OP_CMPG_FLOAT.c */
+/* File: c/OP_CMPG_FLOAT.cpp */
HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1)
OP_END
-/* File: c/OP_CMPL_DOUBLE.c */
+/* File: c/OP_CMPL_DOUBLE.cpp */
HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1)
OP_END
-/* File: c/OP_CMPG_DOUBLE.c */
+/* File: c/OP_CMPG_DOUBLE.cpp */
HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1)
OP_END
-/* File: c/OP_CMP_LONG.c */
+/* File: c/OP_CMP_LONG.cpp */
HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0)
OP_END
-/* File: c/OP_IF_EQ.c */
+/* File: c/OP_IF_EQ.cpp */
HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==)
OP_END
-/* File: c/OP_IF_NE.c */
+/* File: c/OP_IF_NE.cpp */
HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=)
OP_END
-/* File: c/OP_IF_LT.c */
+/* File: c/OP_IF_LT.cpp */
HANDLE_OP_IF_XX(OP_IF_LT, "lt", <)
OP_END
-/* File: c/OP_IF_GE.c */
+/* File: c/OP_IF_GE.cpp */
HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=)
OP_END
-/* File: c/OP_IF_GT.c */
+/* File: c/OP_IF_GT.cpp */
HANDLE_OP_IF_XX(OP_IF_GT, "gt", >)
OP_END
-/* File: c/OP_IF_LE.c */
+/* File: c/OP_IF_LE.cpp */
HANDLE_OP_IF_XX(OP_IF_LE, "le", <=)
OP_END
-/* File: c/OP_IF_EQZ.c */
+/* File: c/OP_IF_EQZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==)
OP_END
-/* File: c/OP_IF_NEZ.c */
+/* File: c/OP_IF_NEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=)
OP_END
-/* File: c/OP_IF_LTZ.c */
+/* File: c/OP_IF_LTZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <)
OP_END
-/* File: c/OP_IF_GEZ.c */
+/* File: c/OP_IF_GEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=)
OP_END
-/* File: c/OP_IF_GTZ.c */
+/* File: c/OP_IF_GTZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >)
OP_END
-/* File: c/OP_IF_LEZ.c */
+/* File: c/OP_IF_LEZ.cpp */
HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=)
OP_END
-/* File: c/OP_UNUSED_3E.c */
+/* File: c/OP_UNUSED_3E.cpp */
HANDLE_OPCODE(OP_UNUSED_3E)
OP_END
-/* File: c/OP_UNUSED_3F.c */
+/* File: c/OP_UNUSED_3F.cpp */
HANDLE_OPCODE(OP_UNUSED_3F)
OP_END
-/* File: c/OP_UNUSED_40.c */
+/* File: c/OP_UNUSED_40.cpp */
HANDLE_OPCODE(OP_UNUSED_40)
OP_END
-/* File: c/OP_UNUSED_41.c */
+/* File: c/OP_UNUSED_41.cpp */
HANDLE_OPCODE(OP_UNUSED_41)
OP_END
-/* File: c/OP_UNUSED_42.c */
+/* File: c/OP_UNUSED_42.cpp */
HANDLE_OPCODE(OP_UNUSED_42)
OP_END
-/* File: c/OP_UNUSED_43.c */
+/* File: c/OP_UNUSED_43.cpp */
HANDLE_OPCODE(OP_UNUSED_43)
OP_END
-/* File: c/OP_AGET.c */
+/* File: c/OP_AGET.cpp */
HANDLE_OP_AGET(OP_AGET, "", u4, )
OP_END
-/* File: c/OP_AGET_WIDE.c */
+/* File: c/OP_AGET_WIDE.cpp */
HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE)
OP_END
-/* File: c/OP_AGET_OBJECT.c */
+/* File: c/OP_AGET_OBJECT.cpp */
HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, )
OP_END
-/* File: c/OP_AGET_BOOLEAN.c */
+/* File: c/OP_AGET_BOOLEAN.cpp */
HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, )
OP_END
-/* File: c/OP_AGET_BYTE.c */
+/* File: c/OP_AGET_BYTE.cpp */
HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, )
OP_END
-/* File: c/OP_AGET_CHAR.c */
+/* File: c/OP_AGET_CHAR.cpp */
HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, )
OP_END
-/* File: c/OP_AGET_SHORT.c */
+/* File: c/OP_AGET_SHORT.cpp */
HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, )
OP_END
-/* File: c/OP_APUT.c */
+/* File: c/OP_APUT.cpp */
HANDLE_OP_APUT(OP_APUT, "", u4, )
OP_END
-/* File: c/OP_APUT_WIDE.c */
+/* File: c/OP_APUT_WIDE.cpp */
HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE)
OP_END
-/* File: c/OP_APUT_OBJECT.c */
+/* File: c/OP_APUT_OBJECT.cpp */
HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/)
{
ArrayObject* arrayObj;
@@ -2178,11 +2159,11 @@
if (obj != NULL) {
if (!checkForNull(obj))
GOTO_exceptionThrown();
- if (!dvmCanPutArrayElement(obj->clazz, arrayObj->obj.clazz)) {
+ if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) {
LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
obj->clazz->descriptor, obj,
arrayObj->obj.clazz->descriptor, arrayObj);
- dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->obj.clazz);
+ dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz);
GOTO_exceptionThrown();
}
}
@@ -2194,59 +2175,59 @@
FINISH(2);
OP_END
-/* File: c/OP_APUT_BOOLEAN.c */
+/* File: c/OP_APUT_BOOLEAN.cpp */
HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, )
OP_END
-/* File: c/OP_APUT_BYTE.c */
+/* File: c/OP_APUT_BYTE.cpp */
HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, )
OP_END
-/* File: c/OP_APUT_CHAR.c */
+/* File: c/OP_APUT_CHAR.cpp */
HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, )
OP_END
-/* File: c/OP_APUT_SHORT.c */
+/* File: c/OP_APUT_SHORT.cpp */
HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, )
OP_END
-/* File: c/OP_IGET.c */
+/* File: c/OP_IGET.cpp */
HANDLE_IGET_X(OP_IGET, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE.c */
+/* File: c/OP_IGET_WIDE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT.c */
+/* File: c/OP_IGET_OBJECT.cpp */
HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_BOOLEAN.c */
+/* File: c/OP_IGET_BOOLEAN.cpp */
HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_IGET_BYTE.c */
+/* File: c/OP_IGET_BYTE.cpp */
HANDLE_IGET_X(OP_IGET_BYTE, "", Int, )
OP_END
-/* File: c/OP_IGET_CHAR.c */
+/* File: c/OP_IGET_CHAR.cpp */
HANDLE_IGET_X(OP_IGET_CHAR, "", Int, )
OP_END
-/* File: c/OP_IGET_SHORT.c */
+/* File: c/OP_IGET_SHORT.cpp */
HANDLE_IGET_X(OP_IGET_SHORT, "", Int, )
OP_END
-/* File: c/OP_IPUT.c */
+/* File: c/OP_IPUT.cpp */
HANDLE_IPUT_X(OP_IPUT, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE.c */
+/* File: c/OP_IPUT_WIDE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT.c */
+/* File: c/OP_IPUT_OBJECT.cpp */
/*
* The VM spec says we should verify that the reference being stored into
* the field is assignment compatible. In practice, many popular VMs don't
@@ -2261,333 +2242,333 @@
HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_BOOLEAN.c */
+/* File: c/OP_IPUT_BOOLEAN.cpp */
HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_IPUT_BYTE.c */
+/* File: c/OP_IPUT_BYTE.cpp */
HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, )
OP_END
-/* File: c/OP_IPUT_CHAR.c */
+/* File: c/OP_IPUT_CHAR.cpp */
HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, )
OP_END
-/* File: c/OP_IPUT_SHORT.c */
+/* File: c/OP_IPUT_SHORT.cpp */
HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, )
OP_END
-/* File: c/OP_SGET.c */
+/* File: c/OP_SGET.cpp */
HANDLE_SGET_X(OP_SGET, "", Int, )
OP_END
-/* File: c/OP_SGET_WIDE.c */
+/* File: c/OP_SGET_WIDE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT.c */
+/* File: c/OP_SGET_OBJECT.cpp */
HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_BOOLEAN.c */
+/* File: c/OP_SGET_BOOLEAN.cpp */
HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_SGET_BYTE.c */
+/* File: c/OP_SGET_BYTE.cpp */
HANDLE_SGET_X(OP_SGET_BYTE, "", Int, )
OP_END
-/* File: c/OP_SGET_CHAR.c */
+/* File: c/OP_SGET_CHAR.cpp */
HANDLE_SGET_X(OP_SGET_CHAR, "", Int, )
OP_END
-/* File: c/OP_SGET_SHORT.c */
+/* File: c/OP_SGET_SHORT.cpp */
HANDLE_SGET_X(OP_SGET_SHORT, "", Int, )
OP_END
-/* File: c/OP_SPUT.c */
+/* File: c/OP_SPUT.cpp */
HANDLE_SPUT_X(OP_SPUT, "", Int, )
OP_END
-/* File: c/OP_SPUT_WIDE.c */
+/* File: c/OP_SPUT_WIDE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT.c */
+/* File: c/OP_SPUT_OBJECT.cpp */
HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_BOOLEAN.c */
+/* File: c/OP_SPUT_BOOLEAN.cpp */
HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, )
OP_END
-/* File: c/OP_SPUT_BYTE.c */
+/* File: c/OP_SPUT_BYTE.cpp */
HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, )
OP_END
-/* File: c/OP_SPUT_CHAR.c */
+/* File: c/OP_SPUT_CHAR.cpp */
HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, )
OP_END
-/* File: c/OP_SPUT_SHORT.c */
+/* File: c/OP_SPUT_SHORT.cpp */
HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, )
OP_END
-/* File: c/OP_INVOKE_VIRTUAL.c */
+/* File: c/OP_INVOKE_VIRTUAL.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeVirtual, false, false);
OP_END
-/* File: c/OP_INVOKE_SUPER.c */
+/* File: c/OP_INVOKE_SUPER.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeSuper, false, false);
OP_END
-/* File: c/OP_INVOKE_DIRECT.c */
+/* File: c/OP_INVOKE_DIRECT.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeDirect, false, false);
OP_END
-/* File: c/OP_INVOKE_STATIC.c */
+/* File: c/OP_INVOKE_STATIC.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeStatic, false, false);
OP_END
-/* File: c/OP_INVOKE_INTERFACE.c */
+/* File: c/OP_INVOKE_INTERFACE.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeInterface, false, false);
OP_END
-/* File: c/OP_UNUSED_73.c */
+/* File: c/OP_UNUSED_73.cpp */
HANDLE_OPCODE(OP_UNUSED_73)
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_RANGE.c */
+/* File: c/OP_INVOKE_VIRTUAL_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeVirtual, true, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_RANGE.c */
+/* File: c/OP_INVOKE_SUPER_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeSuper, true, false);
OP_END
-/* File: c/OP_INVOKE_DIRECT_RANGE.c */
+/* File: c/OP_INVOKE_DIRECT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeDirect, true, false);
OP_END
-/* File: c/OP_INVOKE_STATIC_RANGE.c */
+/* File: c/OP_INVOKE_STATIC_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeStatic, true, false);
OP_END
-/* File: c/OP_INVOKE_INTERFACE_RANGE.c */
+/* File: c/OP_INVOKE_INTERFACE_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeInterface, true, false);
OP_END
-/* File: c/OP_UNUSED_79.c */
+/* File: c/OP_UNUSED_79.cpp */
HANDLE_OPCODE(OP_UNUSED_79)
OP_END
-/* File: c/OP_UNUSED_7A.c */
+/* File: c/OP_UNUSED_7A.cpp */
HANDLE_OPCODE(OP_UNUSED_7A)
OP_END
-/* File: c/OP_NEG_INT.c */
+/* File: c/OP_NEG_INT.cpp */
HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , )
OP_END
-/* File: c/OP_NOT_INT.c */
+/* File: c/OP_NOT_INT.cpp */
HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, )
OP_END
-/* File: c/OP_NEG_LONG.c */
+/* File: c/OP_NEG_LONG.cpp */
HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE)
OP_END
-/* File: c/OP_NOT_LONG.c */
+/* File: c/OP_NOT_LONG.cpp */
HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE)
OP_END
-/* File: c/OP_NEG_FLOAT.c */
+/* File: c/OP_NEG_FLOAT.cpp */
HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT)
OP_END
-/* File: c/OP_NEG_DOUBLE.c */
+/* File: c/OP_NEG_DOUBLE.cpp */
HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE)
OP_END
-/* File: c/OP_INT_TO_LONG.c */
+/* File: c/OP_INT_TO_LONG.cpp */
HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE)
OP_END
-/* File: c/OP_INT_TO_FLOAT.c */
+/* File: c/OP_INT_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT)
OP_END
-/* File: c/OP_INT_TO_DOUBLE.c */
+/* File: c/OP_INT_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE)
OP_END
-/* File: c/OP_LONG_TO_INT.c */
+/* File: c/OP_LONG_TO_INT.cpp */
HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT)
OP_END
-/* File: c/OP_LONG_TO_FLOAT.c */
+/* File: c/OP_LONG_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT)
OP_END
-/* File: c/OP_LONG_TO_DOUBLE.c */
+/* File: c/OP_LONG_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE)
OP_END
-/* File: c/OP_FLOAT_TO_INT.c */
+/* File: c/OP_FLOAT_TO_INT.cpp */
HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int",
float, _FLOAT, s4, _INT)
OP_END
-/* File: c/OP_FLOAT_TO_LONG.c */
+/* File: c/OP_FLOAT_TO_LONG.cpp */
HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long",
float, _FLOAT, s8, _WIDE)
OP_END
-/* File: c/OP_FLOAT_TO_DOUBLE.c */
+/* File: c/OP_FLOAT_TO_DOUBLE.cpp */
HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE)
OP_END
-/* File: c/OP_DOUBLE_TO_INT.c */
+/* File: c/OP_DOUBLE_TO_INT.cpp */
HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int",
double, _DOUBLE, s4, _INT)
OP_END
-/* File: c/OP_DOUBLE_TO_LONG.c */
+/* File: c/OP_DOUBLE_TO_LONG.cpp */
HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long",
double, _DOUBLE, s8, _WIDE)
OP_END
-/* File: c/OP_DOUBLE_TO_FLOAT.c */
+/* File: c/OP_DOUBLE_TO_FLOAT.cpp */
HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT)
OP_END
-/* File: c/OP_INT_TO_BYTE.c */
+/* File: c/OP_INT_TO_BYTE.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1)
OP_END
-/* File: c/OP_INT_TO_CHAR.c */
+/* File: c/OP_INT_TO_CHAR.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2)
OP_END
-/* File: c/OP_INT_TO_SHORT.c */
+/* File: c/OP_INT_TO_SHORT.cpp */
HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */
OP_END
-/* File: c/OP_ADD_INT.c */
+/* File: c/OP_ADD_INT.cpp */
HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0)
OP_END
-/* File: c/OP_SUB_INT.c */
+/* File: c/OP_SUB_INT.cpp */
HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_INT.c */
+/* File: c/OP_MUL_INT.cpp */
HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT.c */
+/* File: c/OP_DIV_INT.cpp */
HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT.c */
+/* File: c/OP_REM_INT.cpp */
HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT.c */
+/* File: c/OP_AND_INT.cpp */
HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT.c */
+/* File: c/OP_OR_INT.cpp */
HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT.c */
+/* File: c/OP_XOR_INT.cpp */
HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT.c */
+/* File: c/OP_SHL_INT.cpp */
HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT.c */
+/* File: c/OP_SHR_INT.cpp */
HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT.c */
+/* File: c/OP_USHR_INT.cpp */
HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>)
OP_END
-/* File: c/OP_ADD_LONG.c */
+/* File: c/OP_ADD_LONG.cpp */
HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0)
OP_END
-/* File: c/OP_SUB_LONG.c */
+/* File: c/OP_SUB_LONG.cpp */
HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_LONG.c */
+/* File: c/OP_MUL_LONG.cpp */
HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_LONG.c */
+/* File: c/OP_DIV_LONG.cpp */
HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1)
OP_END
-/* File: c/OP_REM_LONG.c */
+/* File: c/OP_REM_LONG.cpp */
HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2)
OP_END
-/* File: c/OP_AND_LONG.c */
+/* File: c/OP_AND_LONG.cpp */
HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0)
OP_END
-/* File: c/OP_OR_LONG.c */
+/* File: c/OP_OR_LONG.cpp */
HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0)
OP_END
-/* File: c/OP_XOR_LONG.c */
+/* File: c/OP_XOR_LONG.cpp */
HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_LONG.c */
+/* File: c/OP_SHL_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<)
OP_END
-/* File: c/OP_SHR_LONG.c */
+/* File: c/OP_SHR_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>)
OP_END
-/* File: c/OP_USHR_LONG.c */
+/* File: c/OP_USHR_LONG.cpp */
HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>)
OP_END
-/* File: c/OP_ADD_FLOAT.c */
+/* File: c/OP_ADD_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +)
OP_END
-/* File: c/OP_SUB_FLOAT.c */
+/* File: c/OP_SUB_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -)
OP_END
-/* File: c/OP_MUL_FLOAT.c */
+/* File: c/OP_MUL_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *)
OP_END
-/* File: c/OP_DIV_FLOAT.c */
+/* File: c/OP_DIV_FLOAT.cpp */
HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /)
OP_END
-/* File: c/OP_REM_FLOAT.c */
+/* File: c/OP_REM_FLOAT.cpp */
HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/)
{
u2 srcRegs;
@@ -2602,23 +2583,23 @@
FINISH(2);
OP_END
-/* File: c/OP_ADD_DOUBLE.c */
+/* File: c/OP_ADD_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +)
OP_END
-/* File: c/OP_SUB_DOUBLE.c */
+/* File: c/OP_SUB_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -)
OP_END
-/* File: c/OP_MUL_DOUBLE.c */
+/* File: c/OP_MUL_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *)
OP_END
-/* File: c/OP_DIV_DOUBLE.c */
+/* File: c/OP_DIV_DOUBLE.cpp */
HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /)
OP_END
-/* File: c/OP_REM_DOUBLE.c */
+/* File: c/OP_REM_DOUBLE.cpp */
HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/)
{
u2 srcRegs;
@@ -2633,111 +2614,111 @@
FINISH(2);
OP_END
-/* File: c/OP_ADD_INT_2ADDR.c */
+/* File: c/OP_ADD_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0)
OP_END
-/* File: c/OP_SUB_INT_2ADDR.c */
+/* File: c/OP_SUB_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_INT_2ADDR.c */
+/* File: c/OP_MUL_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_2ADDR.c */
+/* File: c/OP_DIV_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_2ADDR.c */
+/* File: c/OP_REM_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_2ADDR.c */
+/* File: c/OP_AND_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_2ADDR.c */
+/* File: c/OP_OR_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_2ADDR.c */
+/* File: c/OP_XOR_INT_2ADDR.cpp */
HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT_2ADDR.c */
+/* File: c/OP_SHL_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT_2ADDR.c */
+/* File: c/OP_SHR_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT_2ADDR.c */
+/* File: c/OP_USHR_INT_2ADDR.cpp */
HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>)
OP_END
-/* File: c/OP_ADD_LONG_2ADDR.c */
+/* File: c/OP_ADD_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0)
OP_END
-/* File: c/OP_SUB_LONG_2ADDR.c */
+/* File: c/OP_SUB_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0)
OP_END
-/* File: c/OP_MUL_LONG_2ADDR.c */
+/* File: c/OP_MUL_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_LONG_2ADDR.c */
+/* File: c/OP_DIV_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1)
OP_END
-/* File: c/OP_REM_LONG_2ADDR.c */
+/* File: c/OP_REM_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2)
OP_END
-/* File: c/OP_AND_LONG_2ADDR.c */
+/* File: c/OP_AND_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0)
OP_END
-/* File: c/OP_OR_LONG_2ADDR.c */
+/* File: c/OP_OR_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0)
OP_END
-/* File: c/OP_XOR_LONG_2ADDR.c */
+/* File: c/OP_XOR_LONG_2ADDR.cpp */
HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_LONG_2ADDR.c */
+/* File: c/OP_SHL_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<)
OP_END
-/* File: c/OP_SHR_LONG_2ADDR.c */
+/* File: c/OP_SHR_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>)
OP_END
-/* File: c/OP_USHR_LONG_2ADDR.c */
+/* File: c/OP_USHR_LONG_2ADDR.cpp */
HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>)
OP_END
-/* File: c/OP_ADD_FLOAT_2ADDR.c */
+/* File: c/OP_ADD_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +)
OP_END
-/* File: c/OP_SUB_FLOAT_2ADDR.c */
+/* File: c/OP_SUB_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -)
OP_END
-/* File: c/OP_MUL_FLOAT_2ADDR.c */
+/* File: c/OP_MUL_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *)
OP_END
-/* File: c/OP_DIV_FLOAT_2ADDR.c */
+/* File: c/OP_DIV_FLOAT_2ADDR.cpp */
HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /)
OP_END
-/* File: c/OP_REM_FLOAT_2ADDR.c */
+/* File: c/OP_REM_FLOAT_2ADDR.cpp */
HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -2747,23 +2728,23 @@
FINISH(1);
OP_END
-/* File: c/OP_ADD_DOUBLE_2ADDR.c */
+/* File: c/OP_ADD_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +)
OP_END
-/* File: c/OP_SUB_DOUBLE_2ADDR.c */
+/* File: c/OP_SUB_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -)
OP_END
-/* File: c/OP_MUL_DOUBLE_2ADDR.c */
+/* File: c/OP_MUL_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *)
OP_END
-/* File: c/OP_DIV_DOUBLE_2ADDR.c */
+/* File: c/OP_DIV_DOUBLE_2ADDR.cpp */
HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /)
OP_END
-/* File: c/OP_REM_DOUBLE_2ADDR.c */
+/* File: c/OP_REM_DOUBLE_2ADDR.cpp */
HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/)
vdst = INST_A(inst);
vsrc1 = INST_B(inst);
@@ -2773,11 +2754,11 @@
FINISH(1);
OP_END
-/* File: c/OP_ADD_INT_LIT16.c */
+/* File: c/OP_ADD_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0)
OP_END
-/* File: c/OP_RSUB_INT.c */
+/* File: c/OP_RSUB_INT.cpp */
HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/)
{
vdst = INST_A(inst);
@@ -2789,35 +2770,35 @@
FINISH(2);
OP_END
-/* File: c/OP_MUL_INT_LIT16.c */
+/* File: c/OP_MUL_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_LIT16.c */
+/* File: c/OP_DIV_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_LIT16.c */
+/* File: c/OP_REM_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_LIT16.c */
+/* File: c/OP_AND_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_LIT16.c */
+/* File: c/OP_OR_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_LIT16.c */
+/* File: c/OP_XOR_INT_LIT16.cpp */
HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0)
OP_END
-/* File: c/OP_ADD_INT_LIT8.c */
+/* File: c/OP_ADD_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0)
OP_END
-/* File: c/OP_RSUB_INT_LIT8.c */
+/* File: c/OP_RSUB_INT_LIT8.cpp */
HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/)
{
u2 litInfo;
@@ -2831,79 +2812,79 @@
FINISH(2);
OP_END
-/* File: c/OP_MUL_INT_LIT8.c */
+/* File: c/OP_MUL_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0)
OP_END
-/* File: c/OP_DIV_INT_LIT8.c */
+/* File: c/OP_DIV_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1)
OP_END
-/* File: c/OP_REM_INT_LIT8.c */
+/* File: c/OP_REM_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2)
OP_END
-/* File: c/OP_AND_INT_LIT8.c */
+/* File: c/OP_AND_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0)
OP_END
-/* File: c/OP_OR_INT_LIT8.c */
+/* File: c/OP_OR_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0)
OP_END
-/* File: c/OP_XOR_INT_LIT8.c */
+/* File: c/OP_XOR_INT_LIT8.cpp */
HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0)
OP_END
-/* File: c/OP_SHL_INT_LIT8.c */
+/* File: c/OP_SHL_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<)
OP_END
-/* File: c/OP_SHR_INT_LIT8.c */
+/* File: c/OP_SHR_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>)
OP_END
-/* File: c/OP_USHR_INT_LIT8.c */
+/* File: c/OP_USHR_INT_LIT8.cpp */
HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>)
OP_END
-/* File: c/OP_IGET_VOLATILE.c */
+/* File: c/OP_IGET_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_VOLATILE.c */
+/* File: c/OP_IPUT_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SGET_VOLATILE.c */
+/* File: c/OP_SGET_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_VOLATILE.c */
+/* File: c/OP_SPUT_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE.c */
+/* File: c/OP_IGET_WIDE_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE.c */
+/* File: c/OP_SGET_WIDE_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_BREAKPOINT.c */
+/* File: c/OP_BREAKPOINT.cpp */
HANDLE_OPCODE(OP_BREAKPOINT)
{
/*
@@ -2929,7 +2910,7 @@
}
OP_END
-/* File: c/OP_THROW_VERIFICATION_ERROR.c */
+/* File: c/OP_THROW_VERIFICATION_ERROR.cpp */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
EXPORT_PC();
vsrc1 = INST_AA(inst);
@@ -2938,7 +2919,7 @@
GOTO_exceptionThrown();
OP_END
-/* File: c/OP_EXECUTE_INLINE.c */
+/* File: c/OP_EXECUTE_INLINE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
{
/*
@@ -2999,7 +2980,7 @@
FINISH(3);
OP_END
-/* File: c/OP_EXECUTE_INLINE_RANGE.c */
+/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
{
u4 arg0, arg1, arg2, arg3;
@@ -3044,7 +3025,7 @@
FINISH(3);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
{
Object* obj;
@@ -3075,7 +3056,7 @@
}
OP_END
-/* File: c/OP_RETURN_VOID_BARRIER.c */
+/* File: c/OP_RETURN_VOID_BARRIER.cpp */
HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -3085,63 +3066,63 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_IGET_QUICK.c */
+/* File: c/OP_IGET_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE_QUICK.c */
+/* File: c/OP_IGET_WIDE_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_QUICK.c */
+/* File: c/OP_IGET_OBJECT_QUICK.cpp */
HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_QUICK.c */
+/* File: c/OP_IPUT_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE_QUICK.c */
+/* File: c/OP_IPUT_WIDE_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_QUICK.c */
+/* File: c/OP_IPUT_OBJECT_QUICK.cpp */
HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_QUICK.c */
+/* File: c/OP_INVOKE_VIRTUAL_QUICK.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeVirtualQuick, false, false);
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c */
+/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeVirtualQuick, true, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_QUICK.c */
+/* File: c/OP_INVOKE_SUPER_QUICK.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
GOTO_invoke(invokeSuperQuick, false, false);
OP_END
-/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.c */
+/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
GOTO_invoke(invokeSuperQuick, true, false);
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_DISPATCH_FF.c */
+/* File: c/OP_DISPATCH_FF.cpp */
HANDLE_OPCODE(OP_DISPATCH_FF)
/*
* Indicates extended opcode. Use next 8 bits to choose where to branch.
@@ -3149,7 +3130,7 @@
DISPATCH_EXTENDED(INST_AA(inst));
OP_END
-/* File: c/OP_CONST_CLASS_JUMBO.c */
+/* File: c/OP_CONST_CLASS_JUMBO.cpp */
HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3169,7 +3150,7 @@
FINISH(4);
OP_END
-/* File: c/OP_CHECK_CAST_JUMBO.c */
+/* File: c/OP_CHECK_CAST_JUMBO.cpp */
HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3202,7 +3183,7 @@
FINISH(4);
OP_END
-/* File: c/OP_INSTANCE_OF_JUMBO.c */
+/* File: c/OP_INSTANCE_OF_JUMBO.cpp */
HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3234,7 +3215,7 @@
FINISH(5);
OP_END
-/* File: c/OP_NEW_INSTANCE_JUMBO.c */
+/* File: c/OP_NEW_INSTANCE_JUMBO.cpp */
HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/)
{
ClassObject* clazz;
@@ -3284,7 +3265,7 @@
FINISH(4);
OP_END
-/* File: c/OP_NEW_ARRAY_JUMBO.c */
+/* File: c/OP_NEW_ARRAY_JUMBO.cpp */
HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
{
ClassObject* arrayClass;
@@ -3321,48 +3302,48 @@
FINISH(5);
OP_END
-/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.c */
+/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.cpp */
HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/)
GOTO_invoke(filledNewArray, true, true);
OP_END
-/* File: c/OP_IGET_JUMBO.c */
+/* File: c/OP_IGET_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_WIDE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IGET_BOOLEAN_JUMBO.c */
+/* File: c/OP_IGET_BOOLEAN_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_BYTE_JUMBO.c */
+/* File: c/OP_IGET_BYTE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_CHAR_JUMBO.c */
+/* File: c/OP_IGET_CHAR_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IGET_SHORT_JUMBO.c */
+/* File: c/OP_IGET_SHORT_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_JUMBO.c */
+/* File: c/OP_IPUT_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_WIDE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_JUMBO.cpp */
/*
* The VM spec says we should verify that the reference being stored into
* the field is assignment compatible. In practice, many popular VMs don't
@@ -3377,912 +3358,912 @@
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_BOOLEAN_JUMBO.c */
+/* File: c/OP_IPUT_BOOLEAN_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_BYTE_JUMBO.c */
+/* File: c/OP_IPUT_BYTE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_CHAR_JUMBO.c */
+/* File: c/OP_IPUT_CHAR_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_IPUT_SHORT_JUMBO.c */
+/* File: c/OP_IPUT_SHORT_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_JUMBO.c */
+/* File: c/OP_SGET_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_WIDE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_BOOLEAN_JUMBO.c */
+/* File: c/OP_SGET_BOOLEAN_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_BYTE_JUMBO.c */
+/* File: c/OP_SGET_BYTE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_CHAR_JUMBO.c */
+/* File: c/OP_SGET_CHAR_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SGET_SHORT_JUMBO.c */
+/* File: c/OP_SGET_SHORT_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_JUMBO.c */
+/* File: c/OP_SPUT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_WIDE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_BOOLEAN_JUMBO.c */
+/* File: c/OP_SPUT_BOOLEAN_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_BYTE_JUMBO.c */
+/* File: c/OP_SPUT_BYTE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_CHAR_JUMBO.c */
+/* File: c/OP_SPUT_CHAR_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, )
OP_END
-/* File: c/OP_SPUT_SHORT_JUMBO.c */
+/* File: c/OP_SPUT_SHORT_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, )
OP_END
-/* File: c/OP_INVOKE_VIRTUAL_JUMBO.c */
+/* File: c/OP_INVOKE_VIRTUAL_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeVirtual, true, true);
OP_END
-/* File: c/OP_INVOKE_SUPER_JUMBO.c */
+/* File: c/OP_INVOKE_SUPER_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeSuper, true, true);
OP_END
-/* File: c/OP_INVOKE_DIRECT_JUMBO.c */
+/* File: c/OP_INVOKE_DIRECT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeDirect, true, true);
OP_END
-/* File: c/OP_INVOKE_STATIC_JUMBO.c */
+/* File: c/OP_INVOKE_STATIC_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeStatic, true, true);
OP_END
-/* File: c/OP_INVOKE_INTERFACE_JUMBO.c */
+/* File: c/OP_INVOKE_INTERFACE_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
GOTO_invoke(invokeInterface, true, true);
OP_END
-/* File: c/OP_UNUSED_27FF.c */
+/* File: c/OP_UNUSED_27FF.cpp */
HANDLE_OPCODE(OP_UNUSED_27FF)
OP_END
-/* File: c/OP_UNUSED_28FF.c */
+/* File: c/OP_UNUSED_28FF.cpp */
HANDLE_OPCODE(OP_UNUSED_28FF)
OP_END
-/* File: c/OP_UNUSED_29FF.c */
+/* File: c/OP_UNUSED_29FF.cpp */
HANDLE_OPCODE(OP_UNUSED_29FF)
OP_END
-/* File: c/OP_UNUSED_2AFF.c */
+/* File: c/OP_UNUSED_2AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2AFF)
OP_END
-/* File: c/OP_UNUSED_2BFF.c */
+/* File: c/OP_UNUSED_2BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2BFF)
OP_END
-/* File: c/OP_UNUSED_2CFF.c */
+/* File: c/OP_UNUSED_2CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2CFF)
OP_END
-/* File: c/OP_UNUSED_2DFF.c */
+/* File: c/OP_UNUSED_2DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2DFF)
OP_END
-/* File: c/OP_UNUSED_2EFF.c */
+/* File: c/OP_UNUSED_2EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2EFF)
OP_END
-/* File: c/OP_UNUSED_2FFF.c */
+/* File: c/OP_UNUSED_2FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_2FFF)
OP_END
-/* File: c/OP_UNUSED_30FF.c */
+/* File: c/OP_UNUSED_30FF.cpp */
HANDLE_OPCODE(OP_UNUSED_30FF)
OP_END
-/* File: c/OP_UNUSED_31FF.c */
+/* File: c/OP_UNUSED_31FF.cpp */
HANDLE_OPCODE(OP_UNUSED_31FF)
OP_END
-/* File: c/OP_UNUSED_32FF.c */
+/* File: c/OP_UNUSED_32FF.cpp */
HANDLE_OPCODE(OP_UNUSED_32FF)
OP_END
-/* File: c/OP_UNUSED_33FF.c */
+/* File: c/OP_UNUSED_33FF.cpp */
HANDLE_OPCODE(OP_UNUSED_33FF)
OP_END
-/* File: c/OP_UNUSED_34FF.c */
+/* File: c/OP_UNUSED_34FF.cpp */
HANDLE_OPCODE(OP_UNUSED_34FF)
OP_END
-/* File: c/OP_UNUSED_35FF.c */
+/* File: c/OP_UNUSED_35FF.cpp */
HANDLE_OPCODE(OP_UNUSED_35FF)
OP_END
-/* File: c/OP_UNUSED_36FF.c */
+/* File: c/OP_UNUSED_36FF.cpp */
HANDLE_OPCODE(OP_UNUSED_36FF)
OP_END
-/* File: c/OP_UNUSED_37FF.c */
+/* File: c/OP_UNUSED_37FF.cpp */
HANDLE_OPCODE(OP_UNUSED_37FF)
OP_END
-/* File: c/OP_UNUSED_38FF.c */
+/* File: c/OP_UNUSED_38FF.cpp */
HANDLE_OPCODE(OP_UNUSED_38FF)
OP_END
-/* File: c/OP_UNUSED_39FF.c */
+/* File: c/OP_UNUSED_39FF.cpp */
HANDLE_OPCODE(OP_UNUSED_39FF)
OP_END
-/* File: c/OP_UNUSED_3AFF.c */
+/* File: c/OP_UNUSED_3AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3AFF)
OP_END
-/* File: c/OP_UNUSED_3BFF.c */
+/* File: c/OP_UNUSED_3BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3BFF)
OP_END
-/* File: c/OP_UNUSED_3CFF.c */
+/* File: c/OP_UNUSED_3CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3CFF)
OP_END
-/* File: c/OP_UNUSED_3DFF.c */
+/* File: c/OP_UNUSED_3DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3DFF)
OP_END
-/* File: c/OP_UNUSED_3EFF.c */
+/* File: c/OP_UNUSED_3EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3EFF)
OP_END
-/* File: c/OP_UNUSED_3FFF.c */
+/* File: c/OP_UNUSED_3FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_3FFF)
OP_END
-/* File: c/OP_UNUSED_40FF.c */
+/* File: c/OP_UNUSED_40FF.cpp */
HANDLE_OPCODE(OP_UNUSED_40FF)
OP_END
-/* File: c/OP_UNUSED_41FF.c */
+/* File: c/OP_UNUSED_41FF.cpp */
HANDLE_OPCODE(OP_UNUSED_41FF)
OP_END
-/* File: c/OP_UNUSED_42FF.c */
+/* File: c/OP_UNUSED_42FF.cpp */
HANDLE_OPCODE(OP_UNUSED_42FF)
OP_END
-/* File: c/OP_UNUSED_43FF.c */
+/* File: c/OP_UNUSED_43FF.cpp */
HANDLE_OPCODE(OP_UNUSED_43FF)
OP_END
-/* File: c/OP_UNUSED_44FF.c */
+/* File: c/OP_UNUSED_44FF.cpp */
HANDLE_OPCODE(OP_UNUSED_44FF)
OP_END
-/* File: c/OP_UNUSED_45FF.c */
+/* File: c/OP_UNUSED_45FF.cpp */
HANDLE_OPCODE(OP_UNUSED_45FF)
OP_END
-/* File: c/OP_UNUSED_46FF.c */
+/* File: c/OP_UNUSED_46FF.cpp */
HANDLE_OPCODE(OP_UNUSED_46FF)
OP_END
-/* File: c/OP_UNUSED_47FF.c */
+/* File: c/OP_UNUSED_47FF.cpp */
HANDLE_OPCODE(OP_UNUSED_47FF)
OP_END
-/* File: c/OP_UNUSED_48FF.c */
+/* File: c/OP_UNUSED_48FF.cpp */
HANDLE_OPCODE(OP_UNUSED_48FF)
OP_END
-/* File: c/OP_UNUSED_49FF.c */
+/* File: c/OP_UNUSED_49FF.cpp */
HANDLE_OPCODE(OP_UNUSED_49FF)
OP_END
-/* File: c/OP_UNUSED_4AFF.c */
+/* File: c/OP_UNUSED_4AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4AFF)
OP_END
-/* File: c/OP_UNUSED_4BFF.c */
+/* File: c/OP_UNUSED_4BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4BFF)
OP_END
-/* File: c/OP_UNUSED_4CFF.c */
+/* File: c/OP_UNUSED_4CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4CFF)
OP_END
-/* File: c/OP_UNUSED_4DFF.c */
+/* File: c/OP_UNUSED_4DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4DFF)
OP_END
-/* File: c/OP_UNUSED_4EFF.c */
+/* File: c/OP_UNUSED_4EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4EFF)
OP_END
-/* File: c/OP_UNUSED_4FFF.c */
+/* File: c/OP_UNUSED_4FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_4FFF)
OP_END
-/* File: c/OP_UNUSED_50FF.c */
+/* File: c/OP_UNUSED_50FF.cpp */
HANDLE_OPCODE(OP_UNUSED_50FF)
OP_END
-/* File: c/OP_UNUSED_51FF.c */
+/* File: c/OP_UNUSED_51FF.cpp */
HANDLE_OPCODE(OP_UNUSED_51FF)
OP_END
-/* File: c/OP_UNUSED_52FF.c */
+/* File: c/OP_UNUSED_52FF.cpp */
HANDLE_OPCODE(OP_UNUSED_52FF)
OP_END
-/* File: c/OP_UNUSED_53FF.c */
+/* File: c/OP_UNUSED_53FF.cpp */
HANDLE_OPCODE(OP_UNUSED_53FF)
OP_END
-/* File: c/OP_UNUSED_54FF.c */
+/* File: c/OP_UNUSED_54FF.cpp */
HANDLE_OPCODE(OP_UNUSED_54FF)
OP_END
-/* File: c/OP_UNUSED_55FF.c */
+/* File: c/OP_UNUSED_55FF.cpp */
HANDLE_OPCODE(OP_UNUSED_55FF)
OP_END
-/* File: c/OP_UNUSED_56FF.c */
+/* File: c/OP_UNUSED_56FF.cpp */
HANDLE_OPCODE(OP_UNUSED_56FF)
OP_END
-/* File: c/OP_UNUSED_57FF.c */
+/* File: c/OP_UNUSED_57FF.cpp */
HANDLE_OPCODE(OP_UNUSED_57FF)
OP_END
-/* File: c/OP_UNUSED_58FF.c */
+/* File: c/OP_UNUSED_58FF.cpp */
HANDLE_OPCODE(OP_UNUSED_58FF)
OP_END
-/* File: c/OP_UNUSED_59FF.c */
+/* File: c/OP_UNUSED_59FF.cpp */
HANDLE_OPCODE(OP_UNUSED_59FF)
OP_END
-/* File: c/OP_UNUSED_5AFF.c */
+/* File: c/OP_UNUSED_5AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5AFF)
OP_END
-/* File: c/OP_UNUSED_5BFF.c */
+/* File: c/OP_UNUSED_5BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5BFF)
OP_END
-/* File: c/OP_UNUSED_5CFF.c */
+/* File: c/OP_UNUSED_5CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5CFF)
OP_END
-/* File: c/OP_UNUSED_5DFF.c */
+/* File: c/OP_UNUSED_5DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5DFF)
OP_END
-/* File: c/OP_UNUSED_5EFF.c */
+/* File: c/OP_UNUSED_5EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5EFF)
OP_END
-/* File: c/OP_UNUSED_5FFF.c */
+/* File: c/OP_UNUSED_5FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_5FFF)
OP_END
-/* File: c/OP_UNUSED_60FF.c */
+/* File: c/OP_UNUSED_60FF.cpp */
HANDLE_OPCODE(OP_UNUSED_60FF)
OP_END
-/* File: c/OP_UNUSED_61FF.c */
+/* File: c/OP_UNUSED_61FF.cpp */
HANDLE_OPCODE(OP_UNUSED_61FF)
OP_END
-/* File: c/OP_UNUSED_62FF.c */
+/* File: c/OP_UNUSED_62FF.cpp */
HANDLE_OPCODE(OP_UNUSED_62FF)
OP_END
-/* File: c/OP_UNUSED_63FF.c */
+/* File: c/OP_UNUSED_63FF.cpp */
HANDLE_OPCODE(OP_UNUSED_63FF)
OP_END
-/* File: c/OP_UNUSED_64FF.c */
+/* File: c/OP_UNUSED_64FF.cpp */
HANDLE_OPCODE(OP_UNUSED_64FF)
OP_END
-/* File: c/OP_UNUSED_65FF.c */
+/* File: c/OP_UNUSED_65FF.cpp */
HANDLE_OPCODE(OP_UNUSED_65FF)
OP_END
-/* File: c/OP_UNUSED_66FF.c */
+/* File: c/OP_UNUSED_66FF.cpp */
HANDLE_OPCODE(OP_UNUSED_66FF)
OP_END
-/* File: c/OP_UNUSED_67FF.c */
+/* File: c/OP_UNUSED_67FF.cpp */
HANDLE_OPCODE(OP_UNUSED_67FF)
OP_END
-/* File: c/OP_UNUSED_68FF.c */
+/* File: c/OP_UNUSED_68FF.cpp */
HANDLE_OPCODE(OP_UNUSED_68FF)
OP_END
-/* File: c/OP_UNUSED_69FF.c */
+/* File: c/OP_UNUSED_69FF.cpp */
HANDLE_OPCODE(OP_UNUSED_69FF)
OP_END
-/* File: c/OP_UNUSED_6AFF.c */
+/* File: c/OP_UNUSED_6AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6AFF)
OP_END
-/* File: c/OP_UNUSED_6BFF.c */
+/* File: c/OP_UNUSED_6BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6BFF)
OP_END
-/* File: c/OP_UNUSED_6CFF.c */
+/* File: c/OP_UNUSED_6CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6CFF)
OP_END
-/* File: c/OP_UNUSED_6DFF.c */
+/* File: c/OP_UNUSED_6DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6DFF)
OP_END
-/* File: c/OP_UNUSED_6EFF.c */
+/* File: c/OP_UNUSED_6EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6EFF)
OP_END
-/* File: c/OP_UNUSED_6FFF.c */
+/* File: c/OP_UNUSED_6FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_6FFF)
OP_END
-/* File: c/OP_UNUSED_70FF.c */
+/* File: c/OP_UNUSED_70FF.cpp */
HANDLE_OPCODE(OP_UNUSED_70FF)
OP_END
-/* File: c/OP_UNUSED_71FF.c */
+/* File: c/OP_UNUSED_71FF.cpp */
HANDLE_OPCODE(OP_UNUSED_71FF)
OP_END
-/* File: c/OP_UNUSED_72FF.c */
+/* File: c/OP_UNUSED_72FF.cpp */
HANDLE_OPCODE(OP_UNUSED_72FF)
OP_END
-/* File: c/OP_UNUSED_73FF.c */
+/* File: c/OP_UNUSED_73FF.cpp */
HANDLE_OPCODE(OP_UNUSED_73FF)
OP_END
-/* File: c/OP_UNUSED_74FF.c */
+/* File: c/OP_UNUSED_74FF.cpp */
HANDLE_OPCODE(OP_UNUSED_74FF)
OP_END
-/* File: c/OP_UNUSED_75FF.c */
+/* File: c/OP_UNUSED_75FF.cpp */
HANDLE_OPCODE(OP_UNUSED_75FF)
OP_END
-/* File: c/OP_UNUSED_76FF.c */
+/* File: c/OP_UNUSED_76FF.cpp */
HANDLE_OPCODE(OP_UNUSED_76FF)
OP_END
-/* File: c/OP_UNUSED_77FF.c */
+/* File: c/OP_UNUSED_77FF.cpp */
HANDLE_OPCODE(OP_UNUSED_77FF)
OP_END
-/* File: c/OP_UNUSED_78FF.c */
+/* File: c/OP_UNUSED_78FF.cpp */
HANDLE_OPCODE(OP_UNUSED_78FF)
OP_END
-/* File: c/OP_UNUSED_79FF.c */
+/* File: c/OP_UNUSED_79FF.cpp */
HANDLE_OPCODE(OP_UNUSED_79FF)
OP_END
-/* File: c/OP_UNUSED_7AFF.c */
+/* File: c/OP_UNUSED_7AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7AFF)
OP_END
-/* File: c/OP_UNUSED_7BFF.c */
+/* File: c/OP_UNUSED_7BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7BFF)
OP_END
-/* File: c/OP_UNUSED_7CFF.c */
+/* File: c/OP_UNUSED_7CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7CFF)
OP_END
-/* File: c/OP_UNUSED_7DFF.c */
+/* File: c/OP_UNUSED_7DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7DFF)
OP_END
-/* File: c/OP_UNUSED_7EFF.c */
+/* File: c/OP_UNUSED_7EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7EFF)
OP_END
-/* File: c/OP_UNUSED_7FFF.c */
+/* File: c/OP_UNUSED_7FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_7FFF)
OP_END
-/* File: c/OP_UNUSED_80FF.c */
+/* File: c/OP_UNUSED_80FF.cpp */
HANDLE_OPCODE(OP_UNUSED_80FF)
OP_END
-/* File: c/OP_UNUSED_81FF.c */
+/* File: c/OP_UNUSED_81FF.cpp */
HANDLE_OPCODE(OP_UNUSED_81FF)
OP_END
-/* File: c/OP_UNUSED_82FF.c */
+/* File: c/OP_UNUSED_82FF.cpp */
HANDLE_OPCODE(OP_UNUSED_82FF)
OP_END
-/* File: c/OP_UNUSED_83FF.c */
+/* File: c/OP_UNUSED_83FF.cpp */
HANDLE_OPCODE(OP_UNUSED_83FF)
OP_END
-/* File: c/OP_UNUSED_84FF.c */
+/* File: c/OP_UNUSED_84FF.cpp */
HANDLE_OPCODE(OP_UNUSED_84FF)
OP_END
-/* File: c/OP_UNUSED_85FF.c */
+/* File: c/OP_UNUSED_85FF.cpp */
HANDLE_OPCODE(OP_UNUSED_85FF)
OP_END
-/* File: c/OP_UNUSED_86FF.c */
+/* File: c/OP_UNUSED_86FF.cpp */
HANDLE_OPCODE(OP_UNUSED_86FF)
OP_END
-/* File: c/OP_UNUSED_87FF.c */
+/* File: c/OP_UNUSED_87FF.cpp */
HANDLE_OPCODE(OP_UNUSED_87FF)
OP_END
-/* File: c/OP_UNUSED_88FF.c */
+/* File: c/OP_UNUSED_88FF.cpp */
HANDLE_OPCODE(OP_UNUSED_88FF)
OP_END
-/* File: c/OP_UNUSED_89FF.c */
+/* File: c/OP_UNUSED_89FF.cpp */
HANDLE_OPCODE(OP_UNUSED_89FF)
OP_END
-/* File: c/OP_UNUSED_8AFF.c */
+/* File: c/OP_UNUSED_8AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8AFF)
OP_END
-/* File: c/OP_UNUSED_8BFF.c */
+/* File: c/OP_UNUSED_8BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8BFF)
OP_END
-/* File: c/OP_UNUSED_8CFF.c */
+/* File: c/OP_UNUSED_8CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8CFF)
OP_END
-/* File: c/OP_UNUSED_8DFF.c */
+/* File: c/OP_UNUSED_8DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8DFF)
OP_END
-/* File: c/OP_UNUSED_8EFF.c */
+/* File: c/OP_UNUSED_8EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8EFF)
OP_END
-/* File: c/OP_UNUSED_8FFF.c */
+/* File: c/OP_UNUSED_8FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_8FFF)
OP_END
-/* File: c/OP_UNUSED_90FF.c */
+/* File: c/OP_UNUSED_90FF.cpp */
HANDLE_OPCODE(OP_UNUSED_90FF)
OP_END
-/* File: c/OP_UNUSED_91FF.c */
+/* File: c/OP_UNUSED_91FF.cpp */
HANDLE_OPCODE(OP_UNUSED_91FF)
OP_END
-/* File: c/OP_UNUSED_92FF.c */
+/* File: c/OP_UNUSED_92FF.cpp */
HANDLE_OPCODE(OP_UNUSED_92FF)
OP_END
-/* File: c/OP_UNUSED_93FF.c */
+/* File: c/OP_UNUSED_93FF.cpp */
HANDLE_OPCODE(OP_UNUSED_93FF)
OP_END
-/* File: c/OP_UNUSED_94FF.c */
+/* File: c/OP_UNUSED_94FF.cpp */
HANDLE_OPCODE(OP_UNUSED_94FF)
OP_END
-/* File: c/OP_UNUSED_95FF.c */
+/* File: c/OP_UNUSED_95FF.cpp */
HANDLE_OPCODE(OP_UNUSED_95FF)
OP_END
-/* File: c/OP_UNUSED_96FF.c */
+/* File: c/OP_UNUSED_96FF.cpp */
HANDLE_OPCODE(OP_UNUSED_96FF)
OP_END
-/* File: c/OP_UNUSED_97FF.c */
+/* File: c/OP_UNUSED_97FF.cpp */
HANDLE_OPCODE(OP_UNUSED_97FF)
OP_END
-/* File: c/OP_UNUSED_98FF.c */
+/* File: c/OP_UNUSED_98FF.cpp */
HANDLE_OPCODE(OP_UNUSED_98FF)
OP_END
-/* File: c/OP_UNUSED_99FF.c */
+/* File: c/OP_UNUSED_99FF.cpp */
HANDLE_OPCODE(OP_UNUSED_99FF)
OP_END
-/* File: c/OP_UNUSED_9AFF.c */
+/* File: c/OP_UNUSED_9AFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9AFF)
OP_END
-/* File: c/OP_UNUSED_9BFF.c */
+/* File: c/OP_UNUSED_9BFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9BFF)
OP_END
-/* File: c/OP_UNUSED_9CFF.c */
+/* File: c/OP_UNUSED_9CFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9CFF)
OP_END
-/* File: c/OP_UNUSED_9DFF.c */
+/* File: c/OP_UNUSED_9DFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9DFF)
OP_END
-/* File: c/OP_UNUSED_9EFF.c */
+/* File: c/OP_UNUSED_9EFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9EFF)
OP_END
-/* File: c/OP_UNUSED_9FFF.c */
+/* File: c/OP_UNUSED_9FFF.cpp */
HANDLE_OPCODE(OP_UNUSED_9FFF)
OP_END
-/* File: c/OP_UNUSED_A0FF.c */
+/* File: c/OP_UNUSED_A0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A0FF)
OP_END
-/* File: c/OP_UNUSED_A1FF.c */
+/* File: c/OP_UNUSED_A1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A1FF)
OP_END
-/* File: c/OP_UNUSED_A2FF.c */
+/* File: c/OP_UNUSED_A2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A2FF)
OP_END
-/* File: c/OP_UNUSED_A3FF.c */
+/* File: c/OP_UNUSED_A3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A3FF)
OP_END
-/* File: c/OP_UNUSED_A4FF.c */
+/* File: c/OP_UNUSED_A4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A4FF)
OP_END
-/* File: c/OP_UNUSED_A5FF.c */
+/* File: c/OP_UNUSED_A5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A5FF)
OP_END
-/* File: c/OP_UNUSED_A6FF.c */
+/* File: c/OP_UNUSED_A6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A6FF)
OP_END
-/* File: c/OP_UNUSED_A7FF.c */
+/* File: c/OP_UNUSED_A7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A7FF)
OP_END
-/* File: c/OP_UNUSED_A8FF.c */
+/* File: c/OP_UNUSED_A8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A8FF)
OP_END
-/* File: c/OP_UNUSED_A9FF.c */
+/* File: c/OP_UNUSED_A9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_A9FF)
OP_END
-/* File: c/OP_UNUSED_AAFF.c */
+/* File: c/OP_UNUSED_AAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AAFF)
OP_END
-/* File: c/OP_UNUSED_ABFF.c */
+/* File: c/OP_UNUSED_ABFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ABFF)
OP_END
-/* File: c/OP_UNUSED_ACFF.c */
+/* File: c/OP_UNUSED_ACFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ACFF)
OP_END
-/* File: c/OP_UNUSED_ADFF.c */
+/* File: c/OP_UNUSED_ADFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ADFF)
OP_END
-/* File: c/OP_UNUSED_AEFF.c */
+/* File: c/OP_UNUSED_AEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AEFF)
OP_END
-/* File: c/OP_UNUSED_AFFF.c */
+/* File: c/OP_UNUSED_AFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_AFFF)
OP_END
-/* File: c/OP_UNUSED_B0FF.c */
+/* File: c/OP_UNUSED_B0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B0FF)
OP_END
-/* File: c/OP_UNUSED_B1FF.c */
+/* File: c/OP_UNUSED_B1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B1FF)
OP_END
-/* File: c/OP_UNUSED_B2FF.c */
+/* File: c/OP_UNUSED_B2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B2FF)
OP_END
-/* File: c/OP_UNUSED_B3FF.c */
+/* File: c/OP_UNUSED_B3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B3FF)
OP_END
-/* File: c/OP_UNUSED_B4FF.c */
+/* File: c/OP_UNUSED_B4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B4FF)
OP_END
-/* File: c/OP_UNUSED_B5FF.c */
+/* File: c/OP_UNUSED_B5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B5FF)
OP_END
-/* File: c/OP_UNUSED_B6FF.c */
+/* File: c/OP_UNUSED_B6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B6FF)
OP_END
-/* File: c/OP_UNUSED_B7FF.c */
+/* File: c/OP_UNUSED_B7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B7FF)
OP_END
-/* File: c/OP_UNUSED_B8FF.c */
+/* File: c/OP_UNUSED_B8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B8FF)
OP_END
-/* File: c/OP_UNUSED_B9FF.c */
+/* File: c/OP_UNUSED_B9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_B9FF)
OP_END
-/* File: c/OP_UNUSED_BAFF.c */
+/* File: c/OP_UNUSED_BAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BAFF)
OP_END
-/* File: c/OP_UNUSED_BBFF.c */
+/* File: c/OP_UNUSED_BBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BBFF)
OP_END
-/* File: c/OP_UNUSED_BCFF.c */
+/* File: c/OP_UNUSED_BCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BCFF)
OP_END
-/* File: c/OP_UNUSED_BDFF.c */
+/* File: c/OP_UNUSED_BDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BDFF)
OP_END
-/* File: c/OP_UNUSED_BEFF.c */
+/* File: c/OP_UNUSED_BEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BEFF)
OP_END
-/* File: c/OP_UNUSED_BFFF.c */
+/* File: c/OP_UNUSED_BFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_BFFF)
OP_END
-/* File: c/OP_UNUSED_C0FF.c */
+/* File: c/OP_UNUSED_C0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C0FF)
OP_END
-/* File: c/OP_UNUSED_C1FF.c */
+/* File: c/OP_UNUSED_C1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C1FF)
OP_END
-/* File: c/OP_UNUSED_C2FF.c */
+/* File: c/OP_UNUSED_C2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C2FF)
OP_END
-/* File: c/OP_UNUSED_C3FF.c */
+/* File: c/OP_UNUSED_C3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C3FF)
OP_END
-/* File: c/OP_UNUSED_C4FF.c */
+/* File: c/OP_UNUSED_C4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C4FF)
OP_END
-/* File: c/OP_UNUSED_C5FF.c */
+/* File: c/OP_UNUSED_C5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C5FF)
OP_END
-/* File: c/OP_UNUSED_C6FF.c */
+/* File: c/OP_UNUSED_C6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C6FF)
OP_END
-/* File: c/OP_UNUSED_C7FF.c */
+/* File: c/OP_UNUSED_C7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C7FF)
OP_END
-/* File: c/OP_UNUSED_C8FF.c */
+/* File: c/OP_UNUSED_C8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C8FF)
OP_END
-/* File: c/OP_UNUSED_C9FF.c */
+/* File: c/OP_UNUSED_C9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_C9FF)
OP_END
-/* File: c/OP_UNUSED_CAFF.c */
+/* File: c/OP_UNUSED_CAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CAFF)
OP_END
-/* File: c/OP_UNUSED_CBFF.c */
+/* File: c/OP_UNUSED_CBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CBFF)
OP_END
-/* File: c/OP_UNUSED_CCFF.c */
+/* File: c/OP_UNUSED_CCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CCFF)
OP_END
-/* File: c/OP_UNUSED_CDFF.c */
+/* File: c/OP_UNUSED_CDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CDFF)
OP_END
-/* File: c/OP_UNUSED_CEFF.c */
+/* File: c/OP_UNUSED_CEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CEFF)
OP_END
-/* File: c/OP_UNUSED_CFFF.c */
+/* File: c/OP_UNUSED_CFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_CFFF)
OP_END
-/* File: c/OP_UNUSED_D0FF.c */
+/* File: c/OP_UNUSED_D0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D0FF)
OP_END
-/* File: c/OP_UNUSED_D1FF.c */
+/* File: c/OP_UNUSED_D1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D1FF)
OP_END
-/* File: c/OP_UNUSED_D2FF.c */
+/* File: c/OP_UNUSED_D2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D2FF)
OP_END
-/* File: c/OP_UNUSED_D3FF.c */
+/* File: c/OP_UNUSED_D3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D3FF)
OP_END
-/* File: c/OP_UNUSED_D4FF.c */
+/* File: c/OP_UNUSED_D4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D4FF)
OP_END
-/* File: c/OP_UNUSED_D5FF.c */
+/* File: c/OP_UNUSED_D5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D5FF)
OP_END
-/* File: c/OP_UNUSED_D6FF.c */
+/* File: c/OP_UNUSED_D6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D6FF)
OP_END
-/* File: c/OP_UNUSED_D7FF.c */
+/* File: c/OP_UNUSED_D7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D7FF)
OP_END
-/* File: c/OP_UNUSED_D8FF.c */
+/* File: c/OP_UNUSED_D8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D8FF)
OP_END
-/* File: c/OP_UNUSED_D9FF.c */
+/* File: c/OP_UNUSED_D9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_D9FF)
OP_END
-/* File: c/OP_UNUSED_DAFF.c */
+/* File: c/OP_UNUSED_DAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DAFF)
OP_END
-/* File: c/OP_UNUSED_DBFF.c */
+/* File: c/OP_UNUSED_DBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DBFF)
OP_END
-/* File: c/OP_UNUSED_DCFF.c */
+/* File: c/OP_UNUSED_DCFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DCFF)
OP_END
-/* File: c/OP_UNUSED_DDFF.c */
+/* File: c/OP_UNUSED_DDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DDFF)
OP_END
-/* File: c/OP_UNUSED_DEFF.c */
+/* File: c/OP_UNUSED_DEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DEFF)
OP_END
-/* File: c/OP_UNUSED_DFFF.c */
+/* File: c/OP_UNUSED_DFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_DFFF)
OP_END
-/* File: c/OP_UNUSED_E0FF.c */
+/* File: c/OP_UNUSED_E0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E0FF)
OP_END
-/* File: c/OP_UNUSED_E1FF.c */
+/* File: c/OP_UNUSED_E1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E1FF)
OP_END
-/* File: c/OP_UNUSED_E2FF.c */
+/* File: c/OP_UNUSED_E2FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E2FF)
OP_END
-/* File: c/OP_UNUSED_E3FF.c */
+/* File: c/OP_UNUSED_E3FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E3FF)
OP_END
-/* File: c/OP_UNUSED_E4FF.c */
+/* File: c/OP_UNUSED_E4FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E4FF)
OP_END
-/* File: c/OP_UNUSED_E5FF.c */
+/* File: c/OP_UNUSED_E5FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E5FF)
OP_END
-/* File: c/OP_UNUSED_E6FF.c */
+/* File: c/OP_UNUSED_E6FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E6FF)
OP_END
-/* File: c/OP_UNUSED_E7FF.c */
+/* File: c/OP_UNUSED_E7FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E7FF)
OP_END
-/* File: c/OP_UNUSED_E8FF.c */
+/* File: c/OP_UNUSED_E8FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E8FF)
OP_END
-/* File: c/OP_UNUSED_E9FF.c */
+/* File: c/OP_UNUSED_E9FF.cpp */
HANDLE_OPCODE(OP_UNUSED_E9FF)
OP_END
-/* File: c/OP_UNUSED_EAFF.c */
+/* File: c/OP_UNUSED_EAFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EAFF)
OP_END
-/* File: c/OP_UNUSED_EBFF.c */
+/* File: c/OP_UNUSED_EBFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EBFF)
OP_END
-/* File: c/OP_UNUSED_ECFF.c */
+/* File: c/OP_UNUSED_ECFF.cpp */
HANDLE_OPCODE(OP_UNUSED_ECFF)
OP_END
-/* File: c/OP_UNUSED_EDFF.c */
+/* File: c/OP_UNUSED_EDFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EDFF)
OP_END
-/* File: c/OP_UNUSED_EEFF.c */
+/* File: c/OP_UNUSED_EEFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EEFF)
OP_END
-/* File: c/OP_UNUSED_EFFF.c */
+/* File: c/OP_UNUSED_EFFF.cpp */
HANDLE_OPCODE(OP_UNUSED_EFFF)
OP_END
-/* File: c/OP_UNUSED_F0FF.c */
+/* File: c/OP_UNUSED_F0FF.cpp */
HANDLE_OPCODE(OP_UNUSED_F0FF)
OP_END
-/* File: c/OP_UNUSED_F1FF.c */
+/* File: c/OP_UNUSED_F1FF.cpp */
HANDLE_OPCODE(OP_UNUSED_F1FF)
/*
* In portable interp, most unused opcodes will fall through to here.
@@ -4292,7 +4273,7 @@
FINISH(1);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
{
Object* obj;
@@ -4323,55 +4304,55 @@
}
OP_END
-/* File: c/OP_IGET_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
+/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
vsrc1 = FETCH(3);
@@ -4380,7 +4361,7 @@
GOTO_exceptionThrown();
OP_END
-/* File: c/gotoTargets.c */
+/* File: c/gotoTargets.cpp */
/*
* C footer. This has some common code shared by the various targets.
*/
@@ -4470,7 +4451,7 @@
/*
* Fill in the elements. It's legal for vsrc1 to be zero.
*/
- contents = (u4*) newArray->contents;
+ contents = (u4*)(void*)newArray->contents;
if (methodCallRange) {
for (i = 0; i < vsrc1; i++)
contents[i] = GET_REGISTER(vdst+i);
@@ -4489,7 +4470,7 @@
dvmWriteBarrierArray(newArray, 0, newArray->length);
}
- retval.l = newArray;
+ retval.l = (Object*)newArray;
}
if (jumboFormat) {
FINISH(5);
@@ -5012,7 +4993,7 @@
}
/* update thread FP, and reset local variables */
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -5149,10 +5130,10 @@
#endif
/*
- * Adjust local variables to match self->curFrame and the
+ * Adjust local variables to match self->interpSave.curFrame and the
* updated PC.
*/
- //fp = (u4*) self->curFrame;
+ //fp = (u4*) self->interpSave.curFrame;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -5331,7 +5312,7 @@
* calls. For native calls, we'll mark EXIT on return.
* For non-native calls, EXIT is marked in the RETURN op.
*/
- PC_FP_TO_SELF();
+ PC_TO_SELF();
dvmReportInvoke(self, methodToCall);
}
@@ -5344,7 +5325,7 @@
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
- self->curFrame = fp = newFp;
+ self->interpSave.curFrame = fp = newFp;
#ifdef EASY_GDB
debugSaveArea = SAVEAREA_FROM_FP(newFp);
#endif
@@ -5357,13 +5338,12 @@
/* set this up for JNI locals, even if not a JNI native */
newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
- self->curFrame = newFp;
+ self->interpSave.curFrame = newFp;
DUMP_REGS(methodToCall, newFp, true); // show input args
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
+ dvmReportPreNativeInvoke(methodToCall, self, fp);
}
ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
@@ -5377,13 +5357,12 @@
(*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
+ dvmReportPostNativeInvoke(methodToCall, self, fp);
}
/* pop frame off */
dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* If the native code threw an exception, or interpreted code
@@ -5416,7 +5395,7 @@
assert(false); // should not get here
GOTO_TARGET_END
-/* File: portable/enddefs.c */
+/* File: portable/enddefs.cpp */
/*--- end of opcodes ---*/
bail:
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
deleted file mode 100644
index 85414bb..0000000
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ /dev/null
@@ -1,2558 +0,0 @@
-/*
- * This file was generated automatically by gen-mterp.py for 'x86-atom'.
- *
- * --> DO NOT EDIT <--
- */
-
-/* File: c/header.c */
-/*
- * Copyright (C) 2008 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.
- */
-
-/* common includes */
-#include "Dalvik.h"
-#include "interp/InterpDefs.h"
-#include "mterp/Mterp.h"
-#include <math.h> // needed for fmod, fmodf
-#include "mterp/common/FindInterface.h"
-
-/*
- * Configuration defines. These affect the C implementations, i.e. the
- * portable interpreter(s) and C stubs.
- *
- * Some defines are controlled by the Makefile, e.g.:
- * WITH_INSTR_CHECKS
- * WITH_TRACKREF_CHECKS
- * EASY_GDB
- * NDEBUG
- */
-
-#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */
-# define CHECK_BRANCH_OFFSETS
-# define CHECK_REGISTER_INDICES
-#endif
-
-/*
- * Some architectures require 64-bit alignment for access to 64-bit data
- * types. We can't just use pointers to copy 64-bit values out of our
- * interpreted register set, because gcc may assume the pointer target is
- * aligned and generate invalid code.
- *
- * There are two common approaches:
- * (1) Use a union that defines a 32-bit pair and a 64-bit value.
- * (2) Call memcpy().
- *
- * Depending upon what compiler you're using and what options are specified,
- * one may be faster than the other. For example, the compiler might
- * convert a memcpy() of 8 bytes into a series of instructions and omit
- * the call. The union version could cause some strange side-effects,
- * e.g. for a while ARM gcc thought it needed separate storage for each
- * inlined instance, and generated instructions to zero out ~700 bytes of
- * stack space at the top of the interpreter.
- *
- * The default is to use memcpy(). The current gcc for ARM seems to do
- * better with the union.
- */
-#if defined(__ARM_EABI__)
-# define NO_UNALIGN_64__UNION
-#endif
-
-
-//#define LOG_INSTR /* verbose debugging */
-/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
-
-/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
- * Export another copy of the PC on every instruction; this is largely
- * redundant with EXPORT_PC and the debugger code. This value can be
- * compared against what we have stored on the stack with EXPORT_PC to
- * help ensure that we aren't missing any export calls.
- */
-#if WITH_EXTRA_GC_CHECKS > 1
-# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
-#else
-# define EXPORT_EXTRA_PC()
-#endif
-
-/*
- * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
- *
- * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
- *
- * We don't advance the program counter until we finish an instruction or
- * branch, because we do want to have to unroll the PC if there's an
- * exception.
- */
-#ifdef CHECK_BRANCH_OFFSETS
-# define ADJUST_PC(_offset) do { \
- int myoff = _offset; /* deref only once */ \
- if (pc + myoff < curMethod->insns || \
- pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
- { \
- char* desc; \
- desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
- LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
- myoff, (int) (pc - curMethod->insns), \
- curMethod->clazz->descriptor, curMethod->name, desc); \
- free(desc); \
- dvmAbort(); \
- } \
- pc += myoff; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#else
-# define ADJUST_PC(_offset) do { \
- pc += _offset; \
- EXPORT_EXTRA_PC(); \
- } while (false)
-#endif
-
-/*
- * If enabled, log instructions as we execute them.
- */
-#ifdef LOG_INSTR
-# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
-# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
-# define ILOG(_level, ...) do { \
- char debugStrBuf[128]; \
- snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
- if (curMethod != NULL) \
- LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
- self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
- else \
- LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
- self->threadId, debugStrBuf); \
- } while(false)
-void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
-# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
-static const char kSpacing[] = " ";
-#else
-# define ILOGD(...) ((void)0)
-# define ILOGV(...) ((void)0)
-# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
-#endif
-
-/* get a long from an array of u4 */
-static inline s8 getLongFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.ll;
-#else
- s8 val;
- memcpy(&val, &ptr[idx], 8);
- return val;
-#endif
-}
-
-/* store a long into an array of u4 */
-static inline void putLongToArray(u4* ptr, int idx, s8 val)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { s8 ll; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.ll = val;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &val, 8);
-#endif
-}
-
-/* get a double from an array of u4 */
-static inline double getDoubleFromArray(const u4* ptr, int idx)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.parts[0] = ptr[0];
- conv.parts[1] = ptr[1];
- return conv.d;
-#else
- double dval;
- memcpy(&dval, &ptr[idx], 8);
- return dval;
-#endif
-}
-
-/* store a double into an array of u4 */
-static inline void putDoubleToArray(u4* ptr, int idx, double dval)
-{
-#if defined(NO_UNALIGN_64__UNION)
- union { double d; u4 parts[2]; } conv;
-
- ptr += idx;
- conv.d = dval;
- ptr[0] = conv.parts[0];
- ptr[1] = conv.parts[1];
-#else
- memcpy(&ptr[idx], &dval, 8);
-#endif
-}
-
-/*
- * If enabled, validate the register number on every access. Otherwise,
- * just do an array access.
- *
- * Assumes the existence of "u4* fp".
- *
- * "_idx" may be referenced more than once.
- */
-#ifdef CHECK_REGISTER_INDICES
-# define GET_REGISTER(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)]) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
-# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
-# define SET_REGISTER_WIDE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
-# define GET_REGISTER_FLOAT(_idx) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
-# define SET_REGISTER_FLOAT(_idx, _val) \
- ( (_idx) < curMethod->registersSize ? \
- (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
-# define GET_REGISTER_DOUBLE(_idx) \
- ( (_idx) < curMethod->registersSize-1 ? \
- getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
-# define SET_REGISTER_DOUBLE(_idx, _val) \
- ( (_idx) < curMethod->registersSize-1 ? \
- putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
-#else
-# define GET_REGISTER(_idx) (fp[(_idx)])
-# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
-# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
-# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
-# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
-# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
-# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
-# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
-# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
-# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
-# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
-# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
-#endif
-
-/*
- * Get 16 bits from the specified offset of the program counter. We always
- * want to load 16 bits at a time from the instruction stream -- it's more
- * efficient than 8 and won't have the alignment problems that 32 might.
- *
- * Assumes existence of "const u2* pc".
- */
-#define FETCH(_offset) (pc[(_offset)])
-
-/*
- * Extract instruction byte from 16-bit fetch (_inst is a u2).
- */
-#define INST_INST(_inst) ((_inst) & 0xff)
-
-/*
- * Replace the opcode (used when handling breakpoints). _opcode is a u1.
- */
-#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
-
-/*
- * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
- */
-#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
-#define INST_B(_inst) ((_inst) >> 12)
-
-/*
- * Get the 8-bit "vAA" 8-bit register index from the instruction word.
- * (_inst is u2)
- */
-#define INST_AA(_inst) ((_inst) >> 8)
-
-/*
- * The current PC must be available to Throwable constructors, e.g.
- * those created by the various exception throw routines, so that the
- * exception stack trace can be generated correctly. If we don't do this,
- * the offset within the current method won't be shown correctly. See the
- * notes in Exception.c.
- *
- * This is also used to determine the address for precise GC.
- *
- * Assumes existence of "u4* fp" and "const u2* pc".
- */
-#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
-
-/*
- * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
- * pc has already been exported to the stack.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler calls into
- * something that could throw an exception (so we have already called
- * EXPORT_PC at the top).
- */
-static inline bool checkForNull(Object* obj)
-{
- if (obj == NULL) {
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/*
- * Check to see if "obj" is NULL. If so, export the PC into the stack
- * frame and throw an exception.
- *
- * Perform additional checks on debug builds.
- *
- * Use this to check for NULL when the instruction handler doesn't do
- * anything else that can throw an exception.
- */
-static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
-{
- if (obj == NULL) {
- EXPORT_PC();
- dvmThrowNullPointerException(NULL);
- return false;
- }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
- if (!dvmIsValidObject(obj)) {
- LOGE("Invalid object %p\n", obj);
- dvmAbort();
- }
-#endif
-#ifndef NDEBUG
- if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
- /* probable heap corruption */
- LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
- dvmAbort();
- }
-#endif
- return true;
-}
-
-/* File: cstubs/stubdefs.c */
-/*
- * In the C mterp stubs, "goto" is a function call followed immediately
- * by a return.
- */
-
-#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
-
-/* (void)xxx to quiet unused variable compiler warnings. */
-#define GOTO_TARGET(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \
- u2 ref, vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- const Method* methodToCall; \
- StackSaveArea* debugSaveArea; \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \
- (void)methodToCall; (void)debugSaveArea;
-
-#define GOTO_TARGET_END }
-
-/*
- * Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
- */
-#define retval self->retval
-#define pc self->interpSave.pc
-#define fp self->interpSave.fp
-#define curMethod self->interpSave.method
-#define methodClassDex self->interpSave.methodClassDex
-#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
-
-/* ugh */
-#define STUB_HACK(x) x
-#if defined(WITH_JIT)
-#define JIT_STUB_HACK(x) x
-#else
-#define JIT_STUB_HACK(x)
-#endif
-
-/*
- * InterpSave's pc and fp must be valid when breaking out to a
- * "Reportxxx" routine. Because the portable interpreter uses local
- * variables for these, we must flush prior. Stubs, however, use
- * the interpSave vars directly, so this is a nop for stubs.
- */
-#define PC_FP_TO_SELF()
-
-/*
- * Opcode handler framing macros. Here, each opcode is a separate function
- * that takes a "self" argument and returns void. We can't declare
- * these "static" because they may be called from an assembly stub.
- * (void)xxx to quiet unused variable compiler warnings.
- */
-#define HANDLE_OPCODE(_op) \
- void dvmMterp_##_op(Thread* self) { \
- u4 ref; \
- u2 vsrc1, vsrc2, vdst; \
- u2 inst = FETCH(0); \
- (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
-
-#define OP_END }
-
-/*
- * Like the "portable" FINISH, but don't reload "inst", and return to caller
- * when done. Further, debugger/profiler checks are handled
- * before handler execution in mterp, so we don't do them here either.
- */
-#if defined(WITH_JIT)
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \
- dvmCheckJit(pc, self); \
- } \
- return; \
- }
-#else
-#define FINISH(_offset) { \
- ADJUST_PC(_offset); \
- return; \
- }
-#endif
-
-
-/*
- * The "goto label" statements turn into function calls followed by
- * return statements. Some of the functions take arguments, which in the
- * portable interpreter are handled by assigning values to globals.
- */
-
-#define GOTO_exceptionThrown() \
- do { \
- dvmMterp_exceptionThrown(self); \
- return; \
- } while(false)
-
-#define GOTO_returnFromMethod() \
- do { \
- dvmMterp_returnFromMethod(self); \
- return; \
- } while(false)
-
-#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
- do { \
- dvmMterp_##_target(self, _methodCallRange, _jumboFormat); \
- return; \
- } while(false)
-
-#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \
- do { \
- dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \
- _vsrc1, _vdst); \
- return; \
- } while(false)
-
-/*
- * As a special case, "goto bail" turns into a longjmp.
- */
-#define GOTO_bail() \
- dvmMterpStdBail(self, false);
-
-/*
- * Periodically check for thread suspension.
- *
- * While we're at it, see if a debugger has attached or the profiler has
- * started.
- */
-#define PERIODIC_CHECKS(_pcadj) { \
- if (dvmCheckSuspendQuick(self)) { \
- EXPORT_PC(); /* need for precise GC */ \
- dvmCheckSuspendPending(self); \
- } \
- }
-
-/* File: c/opcommon.c */
-/* forward declarations of goto targets */
-GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
-GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
- u2 count, u2 regs);
-GOTO_TARGET_DECL(returnFromMethod);
-GOTO_TARGET_DECL(exceptionThrown);
-
-/*
- * ===========================================================================
- *
- * What follows are opcode definitions shared between multiple opcodes with
- * minor substitutions handled by the C pre-processor. These should probably
- * use the mterp substitution mechanism instead, with the code here moved
- * into common fragment files (like the asm "binop.S"), although it's hard
- * to give up the C preprocessor in favor of the much simpler text subst.
- *
- * ===========================================================================
- */
-
-#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_totype(vdst, \
- GET_REGISTER##_fromtype(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
- _tovtype, _tortype) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- { \
- /* spec defines specific handling for +/- inf and NaN values */ \
- _fromvtype val; \
- _tovtype intMin, intMax, result; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- val = GET_REGISTER##_fromrtype(vsrc1); \
- intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
- intMax = ~intMin; \
- result = (_tovtype) val; \
- if (val >= intMax) /* +inf */ \
- result = intMax; \
- else if (val <= intMin) /* -inf */ \
- result = intMin; \
- else if (val != val) /* NaN */ \
- result = 0; \
- else \
- result = (_tovtype) val; \
- SET_REGISTER##_tortype(vdst, result); \
- } \
- FINISH(1);
-
-#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
- FINISH(1);
-
-/* NOTE: the comparison result is always a signed 4-byte integer */
-#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- int result; \
- u2 regs; \
- _varType val1, val2; \
- vdst = INST_AA(inst); \
- regs = FETCH(1); \
- vsrc1 = regs & 0xff; \
- vsrc2 = regs >> 8; \
- ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- val1 = GET_REGISTER##_type(vsrc1); \
- val2 = GET_REGISTER##_type(vsrc2); \
- if (val1 == val2) \
- result = 0; \
- else if (val1 < val2) \
- result = -1; \
- else if (val1 > val2) \
- result = 1; \
- else \
- result = (_nanVal); \
- ILOGV("+ result=%d\n", result); \
- SET_REGISTER(vdst, result); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
- vsrc1 = INST_A(inst); \
- vsrc2 = INST_B(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
- branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
- FINISH(2); \
- }
-
-#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
- HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
- vsrc1 = INST_AA(inst); \
- if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
- int branchOffset = (s2)FETCH(1); /* sign-extended */ \
- ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
- ILOGV("> branch taken"); \
- if (branchOffset < 0) \
- PERIODIC_CHECKS(branchOffset); \
- FINISH(branchOffset); \
- } else { \
- ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
- FINISH(2); \
- }
-
-#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
- FINISH(1);
-
-#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- secondVal = GET_REGISTER(vsrc2); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- vsrc2 = FETCH(1); \
- ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s2) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
- /* won't generate /lit16 instr for this; check anyway */ \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op (s2) vsrc2; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- /* non-div/rem case */ \
- SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s4 firstVal, result; \
- firstVal = GET_REGISTER(vsrc1); \
- if ((s1) vsrc2 == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op ((s1) vsrc2); \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
- { \
- u2 litInfo; \
- vdst = INST_AA(inst); \
- litInfo = FETCH(1); \
- vsrc1 = litInfo & 0xff; \
- vsrc2 = litInfo >> 8; /* constant */ \
- ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
- (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s4 firstVal, secondVal, result; \
- firstVal = GET_REGISTER(vdst); \
- secondVal = GET_REGISTER(vsrc1); \
- if (secondVal == 0) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER(vdst, result); \
- } else { \
- SET_REGISTER(vdst, \
- (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER(vdst, \
- _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vsrc1); \
- secondVal = GET_REGISTER_WIDE(vsrc2); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
- } \
- } \
- FINISH(2);
-
-#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- if (_chkdiv != 0) { \
- s8 firstVal, secondVal, result; \
- firstVal = GET_REGISTER_WIDE(vdst); \
- secondVal = GET_REGISTER_WIDE(vsrc1); \
- if (secondVal == 0LL) { \
- EXPORT_PC(); \
- dvmThrowArithmeticException("divide by zero"); \
- GOTO_exceptionThrown(); \
- } \
- if ((u8)firstVal == 0x8000000000000000ULL && \
- secondVal == -1LL) \
- { \
- if (_chkdiv == 1) \
- result = firstVal; /* division */ \
- else \
- result = 0; /* remainder */ \
- } else { \
- result = firstVal _op secondVal; \
- } \
- SET_REGISTER_WIDE(vdst, result); \
- } else { \
- SET_REGISTER_WIDE(vdst, \
- (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
- } \
- FINISH(1);
-
-#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_WIDE(vdst, \
- _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
- FINISH(1);
-
-#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- u2 srcRegs; \
- vdst = INST_AA(inst); \
- srcRegs = FETCH(1); \
- vsrc1 = srcRegs & 0xff; \
- vsrc2 = srcRegs >> 8; \
- ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_FLOAT(vdst, \
- GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
- HANDLE_OPCODE(_opcode /*vA, vB*/) \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); \
- ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
- SET_REGISTER_DOUBLE(vdst, \
- GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
- FINISH(1);
-
-#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* array ptr */ \
- vsrc2 = arrayInfo >> 8; /* index */ \
- ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
- ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
- { \
- ArrayObject* arrayObj; \
- u2 arrayInfo; \
- EXPORT_PC(); \
- vdst = INST_AA(inst); /* AA: source value */ \
- arrayInfo = FETCH(1); \
- vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
- vsrc2 = arrayInfo >> 8; /* CC: index */ \
- ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
- arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
- if (!checkForNull((Object*) arrayObj)) \
- GOTO_exceptionThrown(); \
- if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
- dvmThrowArrayIndexOutOfBoundsException( \
- arrayObj->length, GET_REGISTER(vsrc2)); \
- GOTO_exceptionThrown(); \
- } \
- ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
- GET_REGISTER##_regsize(vdst); \
- } \
- FINISH(2);
-
-/*
- * It's possible to get a bad value out of a field with sub-32-bit stores
- * because the -quick versions always operate on 32 bits. Consider:
- * short foo = -1 (sets a 32-bit register to 0xffffffff)
- * iput-quick foo (writes all 32 bits to the field)
- * short bar = 1 (sets a 32-bit register to 0x00000001)
- * iput-short (writes the low 16 bits to the field)
- * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
- * This can only happen when optimized and non-optimized code has interleaved
- * access to the same field. This is unlikely but possible.
- *
- * The easiest way to fix this is to always read/write 32 bits at a time. On
- * a device with a 16-bit data bus this is sub-optimal. (The alternative
- * approach is to have sub-int versions of iget-quick, but now we're wasting
- * Dalvik instruction space and making it less likely that handler code will
- * already be in the CPU i-cache.)
- */
-#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- SET_REGISTER##_regsize(vdst, \
- dvmGetField##_ftype(obj, ifield->byteOffset)); \
- ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
- ILOGV("+ IGETQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
- { \
- InstField* ifield; \
- Object* obj; \
- EXPORT_PC(); \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- vsrc1 = FETCH(4); /* object ptr */ \
- ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNull(obj)) \
- GOTO_exceptionThrown(); \
- ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
- if (ifield == NULL) { \
- ifield = dvmResolveInstField(curMethod->clazz, ref); \
- if (ifield == NULL) \
- GOTO_exceptionThrown(); \
- } \
- dvmSetField##_ftype(obj, ifield->byteOffset, \
- GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
- } \
- FINISH(5);
-
-#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
- { \
- Object* obj; \
- vdst = INST_A(inst); \
- vsrc1 = INST_B(inst); /* object ptr */ \
- ref = FETCH(1); /* field offset */ \
- ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
- (_opname), vdst, vsrc1, ref); \
- obj = (Object*) GET_REGISTER(vsrc1); \
- if (!checkForNullExportPC(obj, fp, pc)) \
- GOTO_exceptionThrown(); \
- dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ IPUTQ %d=0x%08llx", ref, \
- (u8) GET_REGISTER##_regsize(vdst)); \
- } \
- FINISH(2);
-
-/*
- * The JIT needs dvmDexGetResolvedField() to return non-null.
- * Because the portable interpreter is not involved with the JIT
- * and trace building, we only need the extra check here when this
- * code is massaged into a stub called from an assembly interpreter.
- * This is controlled by the JIT_STUB_HACK maco.
- */
-
-#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
- ILOGV("+ SGET '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
- } \
- FINISH(4);
-
-#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
- { \
- StaticField* sfield; \
- vdst = INST_AA(inst); \
- ref = FETCH(1); /* field ref */ \
- ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(2);
-
-#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
- HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
- { \
- StaticField* sfield; \
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
- vdst = FETCH(3); \
- ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
- sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
- if (sfield == NULL) { \
- EXPORT_PC(); \
- sfield = dvmResolveStaticField(curMethod->clazz, ref); \
- if (sfield == NULL) \
- GOTO_exceptionThrown(); \
- if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
- JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
- } \
- } \
- dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
- ILOGV("+ SPUT '%s'=0x%08llx", \
- sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
- } \
- FINISH(4);
-
-/* File: c/OP_IGET_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
-OP_END
-
-/* File: c/OP_IPUT_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
-OP_END
-
-/* File: c/OP_SGET_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
-OP_END
-
-/* File: c/OP_SPUT_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
-OP_END
-
-/* File: c/OP_IGET_OBJECT_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_BREAKPOINT.c */
-HANDLE_OPCODE(OP_BREAKPOINT)
- {
- /*
- * Restart this instruction with the original opcode. We do
- * this by simply jumping to the handler.
- *
- * It's probably not necessary to update "inst", but we do it
- * for the sake of anything that needs to do disambiguation in a
- * common handler with INST_INST.
- *
- * The breakpoint itself is handled over in updateDebugger(),
- * because we need to detect other events (method entry, single
- * step) and report them in the same event packet, and we're not
- * yet handling those through breakpoint instructions. By the
- * time we get here, the breakpoint has already been handled and
- * the thread resumed.
- */
- u1 originalOpcode = dvmGetOriginalOpcode(pc);
- LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpcode, inst,
- INST_REPLACE_OP(inst, originalOpcode));
- inst = INST_REPLACE_OP(inst, originalOpcode);
- FINISH_BKPT(originalOpcode);
- }
-OP_END
-
-/* File: c/OP_EXECUTE_INLINE_RANGE.c */
-HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
- {
- u4 arg0, arg1, arg2, arg3;
- arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */
-
- EXPORT_PC();
-
- vsrc1 = INST_AA(inst); /* #of args */
- ref = FETCH(1); /* inline call "ref" */
- vdst = FETCH(2); /* range base */
- ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
-
- assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
- assert(vsrc1 <= 4);
-
- switch (vsrc1) {
- case 4:
- arg3 = GET_REGISTER(vdst+3);
- /* fall through */
- case 3:
- arg2 = GET_REGISTER(vdst+2);
- /* fall through */
- case 2:
- arg1 = GET_REGISTER(vdst+1);
- /* fall through */
- case 1:
- arg0 = GET_REGISTER(vdst+0);
- /* fall through */
- default: // case 0
- ;
- }
-
- if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
- if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
- GOTO_exceptionThrown();
- } else {
- if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
- GOTO_exceptionThrown();
- }
- }
- FINISH(3);
-OP_END
-
-/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
-HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
- {
- Object* obj;
-
- vsrc1 = FETCH(2); /* reg number of "this" pointer */
- obj = GET_REGISTER_AS_OBJECT(vsrc1);
-
- if (!checkForNullExportPC(obj, fp, pc))
- GOTO_exceptionThrown();
-
- /*
- * The object should be marked "finalizable" when Object.<init>
- * completes normally. We're going to assume it does complete
- * (by virtue of being nothing but a return-void) and set it now.
- */
- if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
- EXPORT_PC();
- dvmSetFinalizable(obj);
- if (dvmGetException(self))
- GOTO_exceptionThrown();
- }
-
- if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
- /* behave like OP_INVOKE_DIRECT_RANGE */
- GOTO_invoke(invokeDirect, true, false);
- }
- FINISH(3);
- }
-OP_END
-
-/* File: c/OP_RETURN_VOID_BARRIER.c */
-HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
- ILOGV("|return-void");
-#ifndef NDEBUG
- retval.j = 0xababababULL; /* placate valgrind */
-#endif
- ANDROID_MEMBAR_STORE();
- GOTO_returnFromMethod();
-OP_END
-
-/* File: c/OP_IPUT_OBJECT_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_SGET_OBJECT_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_SPUT_OBJECT_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.c */
-HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
- {
- Object* obj;
-
- vsrc1 = FETCH(4); /* reg number of "this" pointer */
- obj = GET_REGISTER_AS_OBJECT(vsrc1);
-
- if (!checkForNullExportPC(obj, fp, pc))
- GOTO_exceptionThrown();
-
- /*
- * The object should be marked "finalizable" when Object.<init>
- * completes normally. We're going to assume it does complete
- * (by virtue of being nothing but a return-void) and set it now.
- */
- if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
- EXPORT_PC();
- dvmSetFinalizable(obj);
- if (dvmGetException(self))
- GOTO_exceptionThrown();
- }
-
- if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
- /* behave like OP_INVOKE_DIRECT_RANGE */
- GOTO_invoke(invokeDirect, true, true);
- }
- FINISH(5);
- }
-OP_END
-
-/* File: c/OP_IGET_VOLATILE_JUMBO.c */
-HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
-OP_END
-
-/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.c */
-HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.c */
-HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_IPUT_VOLATILE_JUMBO.c */
-HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
-OP_END
-
-/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.c */
-HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c */
-HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_SGET_VOLATILE_JUMBO.c */
-HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
-OP_END
-
-/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.c */
-HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.c */
-HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/OP_SPUT_VOLATILE_JUMBO.c */
-HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
-OP_END
-
-/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.c */
-HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
-OP_END
-
-/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c */
-HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
-OP_END
-
-/* File: c/gotoTargets.c */
-/*
- * C footer. This has some common code shared by the various targets.
- */
-
-/*
- * Everything from here on is a "goto target". In the basic interpreter
- * we jump into these targets and then jump directly to the handler for
- * next instruction. Here, these are subroutines that return to the caller.
- */
-
-GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat)
- {
- ClassObject* arrayClass;
- ArrayObject* newArray;
- u4* contents;
- char typeCh;
- int i;
- u4 arg5;
-
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */
- vsrc1 = FETCH(3); /* #of elements */
- vdst = FETCH(4); /* range base */
- arg5 = -1; /* silence compiler warning */
- ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- } else {
- ref = FETCH(1); /* class ref */
- vdst = FETCH(2); /* first 4 regs -or- range base */
-
- if (methodCallRange) {
- vsrc1 = INST_AA(inst); /* #of elements */
- arg5 = -1; /* silence compiler warning */
- ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- } else {
- arg5 = INST_A(inst);
- vsrc1 = INST_B(inst); /* #of elements */
- ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1, ref, vdst, arg5);
- }
- }
-
- /*
- * Resolve the array class.
- */
- arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
- if (arrayClass == NULL) {
- arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
- if (arrayClass == NULL)
- GOTO_exceptionThrown();
- }
- /*
- if (!dvmIsArrayClass(arrayClass)) {
- dvmThrowRuntimeException(
- "filled-new-array needs array class");
- GOTO_exceptionThrown();
- }
- */
- /* verifier guarantees this is an array class */
- assert(dvmIsArrayClass(arrayClass));
- assert(dvmIsClassInitialized(arrayClass));
-
- /*
- * Create an array of the specified type.
- */
- LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
- typeCh = arrayClass->descriptor[1];
- if (typeCh == 'D' || typeCh == 'J') {
- /* category 2 primitives not allowed */
- dvmThrowRuntimeException("bad filled array req");
- GOTO_exceptionThrown();
- } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
- /* TODO: requires multiple "fill in" loops with different widths */
- LOGE("non-int primitives not implemented\n");
- dvmThrowInternalError(
- "filled-new-array not implemented for anything but 'int'");
- GOTO_exceptionThrown();
- }
-
- newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
- if (newArray == NULL)
- GOTO_exceptionThrown();
-
- /*
- * Fill in the elements. It's legal for vsrc1 to be zero.
- */
- contents = (u4*) newArray->contents;
- if (methodCallRange) {
- for (i = 0; i < vsrc1; i++)
- contents[i] = GET_REGISTER(vdst+i);
- } else {
- assert(vsrc1 <= 5);
- if (vsrc1 == 5) {
- contents[4] = GET_REGISTER(arg5);
- vsrc1--;
- }
- for (i = 0; i < vsrc1; i++) {
- contents[i] = GET_REGISTER(vdst & 0x0f);
- vdst >>= 4;
- }
- }
- if (typeCh == 'L' || typeCh == '[') {
- dvmWriteBarrierArray(newArray, 0, newArray->length);
- }
-
- retval.l = newArray;
- }
- if (jumboFormat) {
- FINISH(5);
- } else {
- FINISH(3);
- }
-GOTO_TARGET_END
-
-
-GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat)
- {
- Method* baseMethod;
- Object* thisPtr;
-
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
- vsrc1 = FETCH(3); /* count */
- vdst = FETCH(4); /* first reg */
- ADJUST_PC(2); /* advance pc partially to make returns easier */
- ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisPtr = (Object*) GET_REGISTER(vdst);
- } else {
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* method ref */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- /*
- * The object against which we are executing a method is always
- * in the first argument.
- */
- if (methodCallRange) {
- assert(vsrc1 > 0);
- ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisPtr = (Object*) GET_REGISTER(vdst);
- } else {
- assert((vsrc1>>4) > 0);
- ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
- }
- }
-
- if (!checkForNull(thisPtr))
- GOTO_exceptionThrown();
-
- /*
- * Resolve the method. This is the correct method for the static
- * type of the object. We also verify access permissions here.
- */
- baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
- if (baseMethod == NULL) {
- baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
- if (baseMethod == NULL) {
- ILOGV("+ unknown method or access denied\n");
- GOTO_exceptionThrown();
- }
- }
-
- /*
- * Combine the object we found with the vtable offset in the
- * method.
- */
- assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
- methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
-
-#if defined(WITH_JIT) && defined(MTERP_STUB)
- self->methodToCall = methodToCall;
- self->callsiteClass = thisPtr->clazz;
-#endif
-
-#if 0
- if (dvmIsAbstractMethod(methodToCall)) {
- /*
- * This can happen if you create two classes, Base and Sub, where
- * Sub is a sub-class of Base. Declare a protected abstract
- * method foo() in Base, and invoke foo() from a method in Base.
- * Base is an "abstract base class" and is never instantiated
- * directly. Now, Override foo() in Sub, and use Sub. This
- * Works fine unless Sub stops providing an implementation of
- * the method.
- */
- dvmThrowAbstractMethodError("abstract method not implemented");
- GOTO_exceptionThrown();
- }
-#else
- assert(!dvmIsAbstractMethod(methodToCall) ||
- methodToCall->nativeFunc != NULL);
-#endif
-
- LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
- baseMethod->clazz->descriptor, baseMethod->name,
- (u4) baseMethod->methodIndex,
- methodToCall->clazz->descriptor, methodToCall->name);
- assert(methodToCall != NULL);
-
-#if 0
- if (vsrc1 != methodToCall->insSize) {
- LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
- baseMethod->clazz->descriptor, baseMethod->name,
- (u4) baseMethod->methodIndex,
- methodToCall->clazz->descriptor, methodToCall->name);
- //dvmDumpClass(baseMethod->clazz);
- //dvmDumpClass(methodToCall->clazz);
- dvmDumpAllClasses(0);
- }
-#endif
-
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat)
- {
- Method* baseMethod;
- u2 thisReg;
-
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
- vsrc1 = FETCH(3); /* count */
- vdst = FETCH(4); /* first reg */
- ADJUST_PC(2); /* advance pc partially to make returns easier */
- ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisReg = vdst;
- } else {
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* method ref */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- if (methodCallRange) {
- ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisReg = vdst;
- } else {
- ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisReg = vdst & 0x0f;
- }
- }
-
- /* impossible in well-formed code, but we must check nevertheless */
- if (!checkForNull((Object*) GET_REGISTER(thisReg)))
- GOTO_exceptionThrown();
-
- /*
- * Resolve the method. This is the correct method for the static
- * type of the object. We also verify access permissions here.
- * The first arg to dvmResolveMethod() is just the referring class
- * (used for class loaders and such), so we don't want to pass
- * the superclass into the resolution call.
- */
- baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
- if (baseMethod == NULL) {
- baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
- if (baseMethod == NULL) {
- ILOGV("+ unknown method or access denied\n");
- GOTO_exceptionThrown();
- }
- }
-
- /*
- * Combine the object we found with the vtable offset in the
- * method's class.
- *
- * We're using the current method's class' superclass, not the
- * superclass of "this". This is because we might be executing
- * in a method inherited from a superclass, and we want to run
- * in that class' superclass.
- */
- if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
- /*
- * Method does not exist in the superclass. Could happen if
- * superclass gets updated.
- */
- dvmThrowNoSuchMethodError(baseMethod->name);
- GOTO_exceptionThrown();
- }
- methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
-
-#if 0
- if (dvmIsAbstractMethod(methodToCall)) {
- dvmThrowAbstractMethodError("abstract method not implemented");
- GOTO_exceptionThrown();
- }
-#else
- assert(!dvmIsAbstractMethod(methodToCall) ||
- methodToCall->nativeFunc != NULL);
-#endif
- LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
- baseMethod->clazz->descriptor, baseMethod->name,
- methodToCall->clazz->descriptor, methodToCall->name);
- assert(methodToCall != NULL);
-
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat)
- {
- Object* thisPtr;
- ClassObject* thisClass;
-
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
- vsrc1 = FETCH(3); /* count */
- vdst = FETCH(4); /* first reg */
- ADJUST_PC(2); /* advance pc partially to make returns easier */
- ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisPtr = (Object*) GET_REGISTER(vdst);
- } else {
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* method ref */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- /*
- * The object against which we are executing a method is always
- * in the first argument.
- */
- if (methodCallRange) {
- assert(vsrc1 > 0);
- ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisPtr = (Object*) GET_REGISTER(vdst);
- } else {
- assert((vsrc1>>4) > 0);
- ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
- }
- }
-
- if (!checkForNull(thisPtr))
- GOTO_exceptionThrown();
-
- thisClass = thisPtr->clazz;
-
-
- /*
- * Given a class and a method index, find the Method* with the
- * actual code we want to execute.
- */
- methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
- methodClassDex);
-#if defined(WITH_JIT) && defined(MTERP_STUB)
- self->callsiteClass = thisClass;
- self->methodToCall = methodToCall;
-#endif
- if (methodToCall == NULL) {
- assert(dvmCheckException(self));
- GOTO_exceptionThrown();
- }
-
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat)
- {
- u2 thisReg;
-
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
- vsrc1 = FETCH(3); /* count */
- vdst = FETCH(4); /* first reg */
- ADJUST_PC(2); /* advance pc partially to make returns easier */
- ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisReg = vdst;
- } else {
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* method ref */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- if (methodCallRange) {
- ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisReg = vdst;
- } else {
- ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisReg = vdst & 0x0f;
- }
- }
-
- if (!checkForNull((Object*) GET_REGISTER(thisReg)))
- GOTO_exceptionThrown();
-
- methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
- if (methodToCall == NULL) {
- methodToCall = dvmResolveMethod(curMethod->clazz, ref,
- METHOD_DIRECT);
- if (methodToCall == NULL) {
- ILOGV("+ unknown direct method\n"); // should be impossible
- GOTO_exceptionThrown();
- }
- }
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat)
- EXPORT_PC();
-
- if (jumboFormat) {
- ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
- vsrc1 = FETCH(3); /* count */
- vdst = FETCH(4); /* first reg */
- ADJUST_PC(2); /* advance pc partially to make returns easier */
- ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- } else {
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* method ref */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- if (methodCallRange)
- ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- else
- ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- }
-
- methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
- if (methodToCall == NULL) {
- methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
- if (methodToCall == NULL) {
- ILOGV("+ unknown method\n");
- GOTO_exceptionThrown();
- }
-
-#if defined(WITH_JIT) && defined(MTERP_STUB)
- /*
- * The JIT needs dvmDexGetResolvedMethod() to return non-null.
- * Include the check if this code is being used as a stub
- * called from the assembly interpreter.
- */
- if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) &&
- (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) {
- /* Class initialization is still ongoing */
- dvmJitEndTraceSelect(self,pc);
- }
-#endif
- }
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat)
- {
- Object* thisPtr;
-
- EXPORT_PC();
-
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* vtable index */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- /*
- * The object against which we are executing a method is always
- * in the first argument.
- */
- if (methodCallRange) {
- assert(vsrc1 > 0);
- ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisPtr = (Object*) GET_REGISTER(vdst);
- } else {
- assert((vsrc1>>4) > 0);
- ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
- }
-
- if (!checkForNull(thisPtr))
- GOTO_exceptionThrown();
-
-
- /*
- * Combine the object we found with the vtable offset in the
- * method.
- */
- assert(ref < (unsigned int) thisPtr->clazz->vtableCount);
- methodToCall = thisPtr->clazz->vtable[ref];
-#if defined(WITH_JIT) && defined(MTERP_STUB)
- self->callsiteClass = thisPtr->clazz;
- self->methodToCall = methodToCall;
-#endif
-
-#if 0
- if (dvmIsAbstractMethod(methodToCall)) {
- dvmThrowAbstractMethodError("abstract method not implemented");
- GOTO_exceptionThrown();
- }
-#else
- assert(!dvmIsAbstractMethod(methodToCall) ||
- methodToCall->nativeFunc != NULL);
-#endif
-
- LOGVV("+++ virtual[%d]=%s.%s\n",
- ref, methodToCall->clazz->descriptor, methodToCall->name);
- assert(methodToCall != NULL);
-
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat)
- {
- u2 thisReg;
-
- EXPORT_PC();
-
- vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
- ref = FETCH(1); /* vtable index */
- vdst = FETCH(2); /* 4 regs -or- first reg */
-
- if (methodCallRange) {
- ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
- vsrc1, ref, vdst, vdst+vsrc1-1);
- thisReg = vdst;
- } else {
- ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
- vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
- thisReg = vdst & 0x0f;
- }
- /* impossible in well-formed code, but we must check nevertheless */
- if (!checkForNull((Object*) GET_REGISTER(thisReg)))
- GOTO_exceptionThrown();
-
-#if 0 /* impossible in optimized + verified code */
- if (ref >= curMethod->clazz->super->vtableCount) {
- dvmThrowNoSuchMethodError(NULL);
- GOTO_exceptionThrown();
- }
-#else
- assert(ref < (unsigned int) curMethod->clazz->super->vtableCount);
-#endif
-
- /*
- * Combine the object we found with the vtable offset in the
- * method's class.
- *
- * We're using the current method's class' superclass, not the
- * superclass of "this". This is because we might be executing
- * in a method inherited from a superclass, and we want to run
- * in the method's class' superclass.
- */
- methodToCall = curMethod->clazz->super->vtable[ref];
-
-#if 0
- if (dvmIsAbstractMethod(methodToCall)) {
- dvmThrowAbstractMethodError("abstract method not implemented");
- GOTO_exceptionThrown();
- }
-#else
- assert(!dvmIsAbstractMethod(methodToCall) ||
- methodToCall->nativeFunc != NULL);
-#endif
- LOGVV("+++ super-virtual[%d]=%s.%s\n",
- ref, methodToCall->clazz->descriptor, methodToCall->name);
- assert(methodToCall != NULL);
- GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
- }
-GOTO_TARGET_END
-
-
- /*
- * General handling for return-void, return, and return-wide. Put the
- * return value in "retval" before jumping here.
- */
-GOTO_TARGET(returnFromMethod)
- {
- StackSaveArea* saveArea;
-
- /*
- * We must do this BEFORE we pop the previous stack frame off, so
- * that the GC can see the return value (if any) in the local vars.
- *
- * Since this is now an interpreter switch point, we must do it before
- * we do anything at all.
- */
- PERIODIC_CHECKS(0);
-
- ILOGV("> retval=0x%llx (leaving %s.%s %s)",
- retval.j, curMethod->clazz->descriptor, curMethod->name,
- curMethod->shorty);
- //DUMP_REGS(curMethod, fp);
-
- saveArea = SAVEAREA_FROM_FP(fp);
-
-#ifdef EASY_GDB
- debugSaveArea = saveArea;
-#endif
-
- /* back up to previous frame and see if we hit a break */
- fp = (u4*)saveArea->prevFrame;
- assert(fp != NULL);
-
- /* Handle any special subMode requirements */
- if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportReturn(self);
- }
-
- if (dvmIsBreakFrame(fp)) {
- /* bail without popping the method frame from stack */
- LOGVV("+++ returned into break frame\n");
- GOTO_bail();
- }
-
- /* update thread FP, and reset local variables */
- self->curFrame = fp;
- curMethod = SAVEAREA_FROM_FP(fp)->method;
- self->interpSave.method = curMethod;
- //methodClass = curMethod->clazz;
- methodClassDex = curMethod->clazz->pDvmDex;
- pc = saveArea->savedPc;
- ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
- curMethod->name, curMethod->shorty);
-
- /* use FINISH on the caller's invoke instruction */
- //u2 invokeInstr = INST_INST(FETCH(0));
- if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
- invokeInstr <= OP_INVOKE_INTERFACE*/)
- {
- FINISH(3);
- } else {
- //LOGE("Unknown invoke instr %02x at %d\n",
- // invokeInstr, (int) (pc - curMethod->insns));
- assert(false);
- }
- }
-GOTO_TARGET_END
-
-
- /*
- * Jump here when the code throws an exception.
- *
- * By the time we get here, the Throwable has been created and the stack
- * trace has been saved off.
- */
-GOTO_TARGET(exceptionThrown)
- {
- Object* exception;
- int catchRelPc;
-
- PERIODIC_CHECKS(0);
-
- /*
- * We save off the exception and clear the exception status. While
- * processing the exception we might need to load some Throwable
- * classes, and we don't want class loader exceptions to get
- * confused with this one.
- */
- assert(dvmCheckException(self));
- exception = dvmGetException(self);
- dvmAddTrackedAlloc(exception, self);
- dvmClearException(self);
-
- LOGV("Handling exception %s at %s:%d\n",
- exception->clazz->descriptor, curMethod->name,
- dvmLineNumFromPC(curMethod, pc - curMethod->insns));
-
- /*
- * Report the exception throw to any "subMode" watchers.
- *
- * TODO: if the exception was thrown by interpreted code, control
- * fell through native, and then back to us, we will report the
- * exception at the point of the throw and again here. We can avoid
- * this by not reporting exceptions when we jump here directly from
- * the native call code above, but then we won't report exceptions
- * that were thrown *from* the JNI code (as opposed to *through* it).
- *
- * The correct solution is probably to ignore from-native exceptions
- * here, and have the JNI exception code do the reporting to the
- * debugger.
- */
- if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportExceptionThrow(self, exception);
- }
-
- /*
- * We need to unroll to the catch block or the nearest "break"
- * frame.
- *
- * A break frame could indicate that we have reached an intermediate
- * native call, or have gone off the top of the stack and the thread
- * needs to exit. Either way, we return from here, leaving the
- * exception raised.
- *
- * If we do find a catch block, we want to transfer execution to
- * that point.
- *
- * Note this can cause an exception while resolving classes in
- * the "catch" blocks.
- */
- catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
- exception, false, (void**)(void*)&fp);
-
- /*
- * Restore the stack bounds after an overflow. This isn't going to
- * be correct in all circumstances, e.g. if JNI code devours the
- * exception this won't happen until some other exception gets
- * thrown. If the code keeps pushing the stack bounds we'll end
- * up aborting the VM.
- *
- * Note we want to do this *after* the call to dvmFindCatchBlock,
- * because that may need extra stack space to resolve exception
- * classes (e.g. through a class loader).
- *
- * It's possible for the stack overflow handling to cause an
- * exception (specifically, class resolution in a "catch" block
- * during the call above), so we could see the thread's overflow
- * flag raised but actually be running in a "nested" interpreter
- * frame. We don't allow doubled-up StackOverflowErrors, so
- * we can check for this by just looking at the exception type
- * in the cleanup function. Also, we won't unroll past the SOE
- * point because the more-recent exception will hit a break frame
- * as it unrolls to here.
- */
- if (self->stackOverflowed)
- dvmCleanupStackOverflow(self, exception);
-
- if (catchRelPc < 0) {
- /* falling through to JNI code or off the bottom of the stack */
-#if DVM_SHOW_EXCEPTION >= 2
- LOGD("Exception %s from %s:%d not caught locally\n",
- exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
- dvmLineNumFromPC(curMethod, pc - curMethod->insns));
-#endif
- dvmSetException(self, exception);
- dvmReleaseTrackedAlloc(exception, self);
- GOTO_bail();
- }
-
-#if DVM_SHOW_EXCEPTION >= 3
- {
- const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
- LOGD("Exception %s thrown from %s:%d to %s:%d\n",
- exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
- dvmLineNumFromPC(curMethod, pc - curMethod->insns),
- dvmGetMethodSourceFile(catchMethod),
- dvmLineNumFromPC(catchMethod, catchRelPc));
- }
-#endif
-
- /*
- * Adjust local variables to match self->curFrame and the
- * updated PC.
- */
- //fp = (u4*) self->curFrame;
- curMethod = SAVEAREA_FROM_FP(fp)->method;
- self->interpSave.method = curMethod;
- //methodClass = curMethod->clazz;
- methodClassDex = curMethod->clazz->pDvmDex;
- pc = curMethod->insns + catchRelPc;
- ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
- curMethod->name, curMethod->shorty);
- DUMP_REGS(curMethod, fp, false); // show all regs
-
- /*
- * Restore the exception if the handler wants it.
- *
- * The Dalvik spec mandates that, if an exception handler wants to
- * do something with the exception, the first instruction executed
- * must be "move-exception". We can pass the exception along
- * through the thread struct, and let the move-exception instruction
- * clear it for us.
- *
- * If the handler doesn't call move-exception, we don't want to
- * finish here with an exception still pending.
- */
- if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
- dvmSetException(self, exception);
-
- dvmReleaseTrackedAlloc(exception, self);
- FINISH(0);
- }
-GOTO_TARGET_END
-
-
-
- /*
- * General handling for invoke-{virtual,super,direct,static,interface},
- * including "quick" variants.
- *
- * Set "methodToCall" to the Method we're calling, and "methodCallRange"
- * depending on whether this is a "/range" instruction.
- *
- * For a range call:
- * "vsrc1" holds the argument count (8 bits)
- * "vdst" holds the first argument in the range
- * For a non-range call:
- * "vsrc1" holds the argument count (4 bits) and the 5th argument index
- * "vdst" holds four 4-bit register indices
- *
- * The caller must EXPORT_PC before jumping here, because any method
- * call can throw a stack overflow exception.
- */
-GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
- u2 count, u2 regs)
- {
- STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
-
- //printf("range=%d call=%p count=%d regs=0x%04x\n",
- // methodCallRange, methodToCall, count, regs);
- //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
- // methodToCall->name, methodToCall->shorty);
-
- u4* outs;
- int i;
-
- /*
- * Copy args. This may corrupt vsrc1/vdst.
- */
- if (methodCallRange) {
- // could use memcpy or a "Duff's device"; most functions have
- // so few args it won't matter much
- assert(vsrc1 <= curMethod->outsSize);
- assert(vsrc1 == methodToCall->insSize);
- outs = OUTS_FROM_FP(fp, vsrc1);
- for (i = 0; i < vsrc1; i++)
- outs[i] = GET_REGISTER(vdst+i);
- } else {
- u4 count = vsrc1 >> 4;
-
- assert(count <= curMethod->outsSize);
- assert(count == methodToCall->insSize);
- assert(count <= 5);
-
- outs = OUTS_FROM_FP(fp, count);
-#if 0
- if (count == 5) {
- outs[4] = GET_REGISTER(vsrc1 & 0x0f);
- count--;
- }
- for (i = 0; i < (int) count; i++) {
- outs[i] = GET_REGISTER(vdst & 0x0f);
- vdst >>= 4;
- }
-#else
- // This version executes fewer instructions but is larger
- // overall. Seems to be a teensy bit faster.
- assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear
- switch (count) {
- case 5:
- outs[4] = GET_REGISTER(vsrc1 & 0x0f);
- case 4:
- outs[3] = GET_REGISTER(vdst >> 12);
- case 3:
- outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
- case 2:
- outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
- case 1:
- outs[0] = GET_REGISTER(vdst & 0x0f);
- default:
- ;
- }
-#endif
- }
- }
-
- /*
- * (This was originally a "goto" target; I've kept it separate from the
- * stuff above in case we want to refactor things again.)
- *
- * At this point, we have the arguments stored in the "outs" area of
- * the current method's stack frame, and the method to call in
- * "methodToCall". Push a new stack frame.
- */
- {
- StackSaveArea* newSaveArea;
- u4* newFp;
-
- ILOGV("> %s%s.%s %s",
- dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
- methodToCall->clazz->descriptor, methodToCall->name,
- methodToCall->shorty);
-
- newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
- newSaveArea = SAVEAREA_FROM_FP(newFp);
-
- /* verify that we have enough space */
- if (true) {
- u1* bottom;
- bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
- if (bottom < self->interpStackEnd) {
- /* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
- self->interpStackStart, self->interpStackEnd, bottom,
- (u1*) fp - bottom, self->interpStackSize,
- methodToCall->name);
- dvmHandleStackOverflow(self, methodToCall);
- assert(dvmCheckException(self));
- GOTO_exceptionThrown();
- }
- //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
- // fp, newFp, newSaveArea, bottom);
- }
-
-#ifdef LOG_INSTR
- if (methodToCall->registersSize > methodToCall->insSize) {
- /*
- * This makes valgrind quiet when we print registers that
- * haven't been initialized. Turn it off when the debug
- * messages are disabled -- we want valgrind to report any
- * used-before-initialized issues.
- */
- memset(newFp, 0xcc,
- (methodToCall->registersSize - methodToCall->insSize) * 4);
- }
-#endif
-
-#ifdef EASY_GDB
- newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
-#endif
- newSaveArea->prevFrame = fp;
- newSaveArea->savedPc = pc;
-#if defined(WITH_JIT) && defined(MTERP_STUB)
- newSaveArea->returnAddr = 0;
-#endif
- newSaveArea->method = methodToCall;
-
- if (self->interpBreak.ctl.subMode != 0) {
- /*
- * We mark ENTER here for both native and non-native
- * calls. For native calls, we'll mark EXIT on return.
- * For non-native calls, EXIT is marked in the RETURN op.
- */
- PC_FP_TO_SELF();
- dvmReportInvoke(self, methodToCall);
- }
-
- if (!dvmIsNativeMethod(methodToCall)) {
- /*
- * "Call" interpreted code. Reposition the PC, update the
- * frame pointer and other local state, and continue.
- */
- curMethod = methodToCall;
- self->interpSave.method = curMethod;
- methodClassDex = curMethod->clazz->pDvmDex;
- pc = methodToCall->insns;
- self->curFrame = fp = newFp;
-#ifdef EASY_GDB
- debugSaveArea = SAVEAREA_FROM_FP(newFp);
-#endif
- self->debugIsMethodEntry = true; // profiling, debugging
- ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
- curMethod->name, curMethod->shorty);
- DUMP_REGS(curMethod, fp, true); // show input args
- FINISH(0); // jump to method start
- } else {
- /* set this up for JNI locals, even if not a JNI native */
- newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
-
- self->curFrame = newFp;
-
- DUMP_REGS(methodToCall, newFp, true); // show input args
-
- if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
- }
-
- ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
- methodToCall->name, methodToCall->shorty);
-
- /*
- * Jump through native call bridge. Because we leave no
- * space for locals on native calls, "newFp" points directly
- * to the method arguments.
- */
- (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
-
- if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
- }
-
- /* pop frame off */
- dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
-
- /*
- * If the native code threw an exception, or interpreted code
- * invoked by the native call threw one and nobody has cleared
- * it, jump to our local exception handling.
- */
- if (dvmCheckException(self)) {
- LOGV("Exception thrown by/below native code\n");
- GOTO_exceptionThrown();
- }
-
- ILOGD("> retval=0x%llx (leaving native)", retval.j);
- ILOGD("> (return from native %s.%s to %s.%s %s)",
- methodToCall->clazz->descriptor, methodToCall->name,
- curMethod->clazz->descriptor, curMethod->name,
- curMethod->shorty);
-
- //u2 invokeInstr = INST_INST(FETCH(0));
- if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
- invokeInstr <= OP_INVOKE_INTERFACE*/)
- {
- FINISH(3);
- } else {
- //LOGE("Unknown invoke instr %02x at %d\n",
- // invokeInstr, (int) (pc - curMethod->insns));
- assert(false);
- }
- }
- }
- assert(false); // should not get here
-GOTO_TARGET_END
-
-/* File: cstubs/enddefs.c */
-
-/* undefine "magic" name remapping */
-#undef retval
-#undef pc
-#undef fp
-#undef curMethod
-#undef methodClassDex
-#undef self
-#undef debugTrackedRefStart
-
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86-atom.cpp
similarity index 96%
copy from vm/mterp/out/InterpC-x86.c
copy to vm/mterp/out/InterpC-x86-atom.cpp
index dd25604..81e84b9 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86-atom.cpp
@@ -1,10 +1,10 @@
/*
- * This file was generated automatically by gen-mterp.py for 'x86'.
+ * This file was generated automatically by gen-mterp.py for 'x86-atom'.
*
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,27 +1249,72 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: c/OP_IGET_WIDE_VOLATILE.c */
+/* File: c/OP_IGET_VOLATILE.cpp */
+HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
+OP_END
+
+/* File: c/OP_IPUT_VOLATILE.cpp */
+HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
+OP_END
+
+/* File: c/OP_SGET_VOLATILE.cpp */
+HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
+OP_END
+
+/* File: c/OP_SPUT_VOLATILE.cpp */
+HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
+OP_END
+
+/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */
+HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
+OP_END
+
+/* File: c/OP_IGET_WIDE_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE.c */
+/* File: c/OP_SGET_WIDE_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_EXECUTE_INLINE_RANGE.c */
+/* File: c/OP_BREAKPOINT.cpp */
+HANDLE_OPCODE(OP_BREAKPOINT)
+ {
+ /*
+ * Restart this instruction with the original opcode. We do
+ * this by simply jumping to the handler.
+ *
+ * It's probably not necessary to update "inst", but we do it
+ * for the sake of anything that needs to do disambiguation in a
+ * common handler with INST_INST.
+ *
+ * The breakpoint itself is handled over in updateDebugger(),
+ * because we need to detect other events (method entry, single
+ * step) and report them in the same event packet, and we're not
+ * yet handling those through breakpoint instructions. By the
+ * time we get here, the breakpoint has already been handled and
+ * the thread resumed.
+ */
+ u1 originalOpcode = dvmGetOriginalOpcode(pc);
+ LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpcode, inst,
+ INST_REPLACE_OP(inst, originalOpcode));
+ inst = INST_REPLACE_OP(inst, originalOpcode);
+ FINISH_BKPT(originalOpcode);
+ }
+OP_END
+
+/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
{
u4 arg0, arg1, arg2, arg3;
@@ -1331,7 +1359,7 @@
FINISH(3);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
{
Object* obj;
@@ -1362,7 +1390,7 @@
}
OP_END
-/* File: c/OP_RETURN_VOID_BARRIER.c */
+/* File: c/OP_RETURN_VOID_BARRIER.cpp */
HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -1372,7 +1400,19 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */
+HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
+OP_END
+
+/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */
+HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
+OP_END
+
+/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */
+HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
+OP_END
+
+/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
{
Object* obj;
@@ -1403,55 +1443,55 @@
}
OP_END
-/* File: c/OP_IGET_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/gotoTargets.c */
+/* File: c/gotoTargets.cpp */
/*
* C footer. This has some common code shared by the various targets.
*/
@@ -1541,7 +1581,7 @@
/*
* Fill in the elements. It's legal for vsrc1 to be zero.
*/
- contents = (u4*) newArray->contents;
+ contents = (u4*)(void*)newArray->contents;
if (methodCallRange) {
for (i = 0; i < vsrc1; i++)
contents[i] = GET_REGISTER(vdst+i);
@@ -1560,7 +1600,7 @@
dvmWriteBarrierArray(newArray, 0, newArray->length);
}
- retval.l = newArray;
+ retval.l = (Object*)newArray;
}
if (jumboFormat) {
FINISH(5);
@@ -2083,7 +2123,7 @@
}
/* update thread FP, and reset local variables */
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -2220,10 +2260,10 @@
#endif
/*
- * Adjust local variables to match self->curFrame and the
+ * Adjust local variables to match self->interpSave.curFrame and the
* updated PC.
*/
- //fp = (u4*) self->curFrame;
+ //fp = (u4*) self->interpSave.curFrame;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -2402,7 +2442,7 @@
* calls. For native calls, we'll mark EXIT on return.
* For non-native calls, EXIT is marked in the RETURN op.
*/
- PC_FP_TO_SELF();
+ PC_TO_SELF();
dvmReportInvoke(self, methodToCall);
}
@@ -2415,7 +2455,7 @@
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
- self->curFrame = fp = newFp;
+ self->interpSave.curFrame = fp = newFp;
#ifdef EASY_GDB
debugSaveArea = SAVEAREA_FROM_FP(newFp);
#endif
@@ -2428,13 +2468,12 @@
/* set this up for JNI locals, even if not a JNI native */
newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
- self->curFrame = newFp;
+ self->interpSave.curFrame = newFp;
DUMP_REGS(methodToCall, newFp, true); // show input args
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
+ dvmReportPreNativeInvoke(methodToCall, self, fp);
}
ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
@@ -2448,13 +2487,12 @@
(*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
+ dvmReportPostNativeInvoke(methodToCall, self, fp);
}
/* pop frame off */
dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* If the native code threw an exception, or interpreted code
@@ -2487,7 +2525,7 @@
assert(false); // should not get here
GOTO_TARGET_END
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.cpp
similarity index 97%
rename from vm/mterp/out/InterpC-x86.c
rename to vm/mterp/out/InterpC-x86.cpp
index dd25604..4cf6603 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.cpp
@@ -4,7 +4,7 @@
* --> DO NOT EDIT <--
*/
-/* File: c/header.c */
+/* File: c/header.cpp */
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -74,18 +74,6 @@
/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
/*
- * Keep a tally of accesses to fields. Currently only works if full DEX
- * optimization is disabled.
- */
-#ifdef PROFILE_FIELD_ACCESS
-# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
-# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
-#else
-# define UPDATE_FIELD_GET(_field) ((void)0)
-# define UPDATE_FIELD_PUT(_field) ((void)0)
-#endif
-
-/*
* Export another copy of the PC on every instruction; this is largely
* redundant with EXPORT_PC and the debugger code. This value can be
* compared against what we have stored on the stack with EXPORT_PC to
@@ -379,14 +367,14 @@
return true;
}
-/* File: cstubs/stubdefs.c */
+/* File: cstubs/stubdefs.cpp */
/*
* In the C mterp stubs, "goto" is a function call followed immediately
* by a return.
*/
#define GOTO_TARGET_DECL(_target, ...) \
- void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
+ extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
/* (void)xxx to quiet unused variable compiler warnings. */
#define GOTO_TARGET(_target, ...) \
@@ -402,11 +390,11 @@
/*
* Redefine what used to be local variable accesses into Thread struct
- * references. (These are undefined down in "footer.c".)
+ * references. (These are undefined down in "footer.cpp".)
*/
#define retval self->retval
#define pc self->interpSave.pc
-#define fp self->interpSave.fp
+#define fp self->interpSave.curFrame
#define curMethod self->interpSave.method
#define methodClassDex self->interpSave.methodClassDex
#define debugTrackedRefStart self->interpSave.debugTrackedRefStart
@@ -426,6 +414,7 @@
* the interpSave vars directly, so this is a nop for stubs.
*/
#define PC_FP_TO_SELF()
+#define PC_TO_SELF()
/*
* Opcode handler framing macros. Here, each opcode is a separate function
@@ -434,6 +423,7 @@
* (void)xxx to quiet unused variable compiler warnings.
*/
#define HANDLE_OPCODE(_op) \
+ extern "C" void dvmMterp_##_op(Thread* self); \
void dvmMterp_##_op(Thread* self) { \
u4 ref; \
u2 vsrc1, vsrc2, vdst; \
@@ -513,7 +503,7 @@
} \
}
-/* File: c/opcommon.c */
+/* File: c/opcommon.cpp */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
@@ -973,7 +963,7 @@
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
} \
FINISH(2);
@@ -998,7 +988,7 @@
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
- ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
+ ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
GET_REGISTER##_regsize(vdst); \
} \
FINISH(2);
@@ -1043,7 +1033,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(2);
@@ -1071,7 +1060,6 @@
dvmGetField##_ftype(obj, ifield->byteOffset)); \
ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&ifield->field); \
} \
FINISH(5);
@@ -1116,7 +1104,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(2);
@@ -1144,7 +1131,6 @@
GET_REGISTER##_regsize(vdst)); \
ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
(u8) GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&ifield->field); \
} \
FINISH(5);
@@ -1194,7 +1180,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(2);
@@ -1218,7 +1203,6 @@
SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
ILOGV("+ SGET '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_GET(&sfield->field); \
} \
FINISH(4);
@@ -1242,7 +1226,6 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(2);
@@ -1266,27 +1249,26 @@
dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
ILOGV("+ SPUT '%s'=0x%08llx", \
sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
- UPDATE_FIELD_PUT(&sfield->field); \
} \
FINISH(4);
-/* File: c/OP_IGET_WIDE_VOLATILE.c */
+/* File: c/OP_IGET_WIDE_VOLATILE.cpp */
HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */
HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE.c */
+/* File: c/OP_SGET_WIDE_VOLATILE.cpp */
HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */
HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_EXECUTE_INLINE_RANGE.c */
+/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */
HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
{
u4 arg0, arg1, arg2, arg3;
@@ -1331,7 +1313,7 @@
FINISH(3);
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
{
Object* obj;
@@ -1362,7 +1344,7 @@
}
OP_END
-/* File: c/OP_RETURN_VOID_BARRIER.c */
+/* File: c/OP_RETURN_VOID_BARRIER.cpp */
HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
ILOGV("|return-void");
#ifndef NDEBUG
@@ -1372,7 +1354,7 @@
GOTO_returnFromMethod();
OP_END
-/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.c */
+/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */
HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
{
Object* obj;
@@ -1403,55 +1385,55 @@
}
OP_END
-/* File: c/OP_IGET_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_IPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SGET_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
OP_END
-/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/OP_SPUT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
OP_END
-/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
OP_END
-/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.c */
+/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */
HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
OP_END
-/* File: c/gotoTargets.c */
+/* File: c/gotoTargets.cpp */
/*
* C footer. This has some common code shared by the various targets.
*/
@@ -1541,7 +1523,7 @@
/*
* Fill in the elements. It's legal for vsrc1 to be zero.
*/
- contents = (u4*) newArray->contents;
+ contents = (u4*)(void*)newArray->contents;
if (methodCallRange) {
for (i = 0; i < vsrc1; i++)
contents[i] = GET_REGISTER(vdst+i);
@@ -1560,7 +1542,7 @@
dvmWriteBarrierArray(newArray, 0, newArray->length);
}
- retval.l = newArray;
+ retval.l = (Object*)newArray;
}
if (jumboFormat) {
FINISH(5);
@@ -2083,7 +2065,7 @@
}
/* update thread FP, and reset local variables */
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -2220,10 +2202,10 @@
#endif
/*
- * Adjust local variables to match self->curFrame and the
+ * Adjust local variables to match self->interpSave.curFrame and the
* updated PC.
*/
- //fp = (u4*) self->curFrame;
+ //fp = (u4*) self->interpSave.curFrame;
curMethod = SAVEAREA_FROM_FP(fp)->method;
self->interpSave.method = curMethod;
//methodClass = curMethod->clazz;
@@ -2402,7 +2384,7 @@
* calls. For native calls, we'll mark EXIT on return.
* For non-native calls, EXIT is marked in the RETURN op.
*/
- PC_FP_TO_SELF();
+ PC_TO_SELF();
dvmReportInvoke(self, methodToCall);
}
@@ -2415,7 +2397,7 @@
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
- self->curFrame = fp = newFp;
+ self->interpSave.curFrame = fp = newFp;
#ifdef EASY_GDB
debugSaveArea = SAVEAREA_FROM_FP(newFp);
#endif
@@ -2428,13 +2410,12 @@
/* set this up for JNI locals, even if not a JNI native */
newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
- self->curFrame = newFp;
+ self->interpSave.curFrame = newFp;
DUMP_REGS(methodToCall, newFp, true); // show input args
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPreNativeInvoke(methodToCall, self);
+ dvmReportPreNativeInvoke(methodToCall, self, fp);
}
ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
@@ -2448,13 +2429,12 @@
(*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
if (self->interpBreak.ctl.subMode != 0) {
- PC_FP_TO_SELF();
- dvmReportPostNativeInvoke(methodToCall, self);
+ dvmReportPostNativeInvoke(methodToCall, self, fp);
}
/* pop frame off */
dvmPopJniLocals(self, newSaveArea);
- self->curFrame = fp;
+ self->interpSave.curFrame = fp;
/*
* If the native code threw an exception, or interpreted code
@@ -2487,7 +2467,7 @@
assert(false); // should not get here
GOTO_TARGET_END
-/* File: cstubs/enddefs.c */
+/* File: cstubs/enddefs.cpp */
/* undefine "magic" name remapping */
#undef retval
diff --git a/vm/mterp/portable/enddefs.c b/vm/mterp/portable/enddefs.cpp
similarity index 100%
rename from vm/mterp/portable/enddefs.c
rename to vm/mterp/portable/enddefs.cpp
diff --git a/vm/mterp/portable/entry.c b/vm/mterp/portable/entry.cpp
similarity index 91%
rename from vm/mterp/portable/entry.c
rename to vm/mterp/portable/entry.cpp
index 485fa82..dddf136 100644
--- a/vm/mterp/portable/entry.c
+++ b/vm/mterp/portable/entry.cpp
@@ -6,7 +6,7 @@
void dvmInterpretPortable(Thread* self)
{
#if defined(EASY_GDB)
- StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame);
+ StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
#endif
#if defined(WITH_TRACKREF_CHECKS)
int debugTrackedRefStart = self->interpSave.debugTrackedRefStart;
@@ -34,7 +34,7 @@
/* copy state in */
curMethod = self->interpSave.method;
pc = self->interpSave.pc;
- fp = self->interpSave.fp;
+ fp = self->interpSave.curFrame;
retval = self->retval; /* only need for kInterpEntryReturn? */
methodClassDex = curMethod->clazz->pDvmDex;
@@ -59,7 +59,7 @@
if (self->debugIsMethodEntry) {
ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
curMethod->name);
- DUMP_REGS(curMethod, self->interpSave.fp, false);
+ DUMP_REGS(curMethod, self->interpSave.curFrame, false);
}
#endif
diff --git a/vm/mterp/portable/stubdefs.c b/vm/mterp/portable/stubdefs.cpp
similarity index 97%
rename from vm/mterp/portable/stubdefs.c
rename to vm/mterp/portable/stubdefs.cpp
index de9a8e7..57ff35c 100644
--- a/vm/mterp/portable/stubdefs.c
+++ b/vm/mterp/portable/stubdefs.cpp
@@ -21,7 +21,8 @@
*/
#define PC_FP_TO_SELF() \
self->interpSave.pc = pc; \
- self->interpSave.fp = fp;
+ self->interpSave.curFrame = fp;
+#define PC_TO_SELF() self->interpSave.pc = pc;
/*
* Instruction framing. For a switch-oriented implementation this is
diff --git a/vm/mterp/x86-atom/TODO.txt b/vm/mterp/x86-atom/TODO.txt
index a16f857..228d3e2 100644
--- a/vm/mterp/x86-atom/TODO.txt
+++ b/vm/mterp/x86-atom/TODO.txt
@@ -13,7 +13,7 @@
elminiates a separate debug interpreter. Needs a dedicated
rIBASE register (or alternate switching model with variable
handler base).
-(hi) Add dvmReportXXXX()" calls in footer.c to support profilers &
+(hi) Add dvmReportXXXX()" calls in footer.cpp to support profilers &
debuggers.
(hi) Set self->debugIsMethodEntry in invoke code.
diff --git a/vm/mterp/x86/entry.S b/vm/mterp/x86/entry.S
index b6f944a..3e2a708 100644
--- a/vm/mterp/x86/entry.S
+++ b/vm/mterp/x86/entry.S
@@ -43,7 +43,7 @@
/* Set up "named" registers */
movl offThread_pc(%ecx),rPC
- movl offThread_fp(%ecx),rFP
+ movl offThread_curFrame(%ecx),rFP
movl offThread_curHandlerTable(%ecx),rIBASE
/* Remember %esp for future "longjmp" */
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index b79d8cf..d4b38a9 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -375,7 +375,7 @@
movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
/* Any special actions to take? */
- cmpb $$0, offThread_subMode(%ecx)
+ cmpw $$0, offThread_subMode(%ecx)
jne 2f # Yes - handle them
1:
testl $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
@@ -393,7 +393,7 @@
movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
movl $$1, offThread_debugIsMethodEntry(%ecx)
movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
- movl rFP, offThread_curFrame(%ecx) # self->curFrame<- newFP
+ movl rFP, offThread_curFrame(%ecx) # curFrame<-newFP
movl offThread_curHandlerTable(%ecx),rIBASE
FETCH_INST
GOTO_NEXT # jump to methodToCall->insns
@@ -408,7 +408,6 @@
SPILL_TMP1(%eax) # preserve methodToCall
SPILL_TMP2(%edx) # preserve newSaveArea
movl rPC, offThread_pc(%ecx) # update interpSave.pc
- movl rFP, offThread_fp(%ecx) # update interpSave.fp
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
call dvmReportInvoke # (self, method)
@@ -427,8 +426,8 @@
movl rINST, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
movl %edx, LOCAL2_OFFSET(%ebp) # save newSaveArea
movl LOCAL1_OFFSET(%ebp), rINST # rINST<- newFP
- movl rINST, offThread_curFrame(%ecx) # self->curFrame<- newFP
- cmpb $$0, offThread_subMode(%ecx) # Anything special going on?
+ movl rINST, offThread_curFrame(%ecx) # curFrame<- newFP
+ cmpw $$0, offThread_subMode(%ecx) # Anything special going on?
jne 11f # yes - handle it
movl %ecx, OUT_ARG3(%esp) # push parameter self
movl %eax, OUT_ARG2(%esp) # push parameter methodToCall
@@ -441,7 +440,7 @@
movl rSELF, %eax # %eax<- self
movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
cmp $$0, offThread_exception(%eax) # check for exception
- movl rFP, offThread_curFrame(%eax) # self->curFrame<- rFP
+ movl rFP, offThread_curFrame(%eax) # curFrame<- rFP
movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
jne common_exceptionThrown # handle exception
movl offThread_curHandlerTable(%eax),rIBASE
@@ -456,10 +455,10 @@
*/
SPILL_TMP1(%eax) # save methodTocall
movl rPC, offThread_pc(%ecx)
- movl rFP, offThread_fp(%ecx)
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
- call dvmReportPreNativeInvoke # (self, methodToCall)
+ movl rFP, OUT_ARG2(%esp)
+ call dvmReportPreNativeInvoke # (self, methodToCall, fp)
UNSPILL_TMP1(%eax) # restore methodToCall
movl rSELF,%ecx # restore self
@@ -475,7 +474,8 @@
movl rSELF, %ecx
movl %ecx, OUT_ARG0(%esp)
movl %eax, OUT_ARG1(%esp)
- call dvmReportPostNativeInvoke # (self, methodToCall)
+ movl rFP, OUT_ARG2(%esp)
+ call dvmReportPostNativeInvoke # (self, methodToCall, fp)
jmp 7b # rejoin
.LstackOverflow: # eax=methodToCall
@@ -492,17 +492,17 @@
common_returnFromMethod:
movl rSELF,%ecx
SAVEAREA_FROM_FP %eax # eax<- saveArea (old)
- movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
- cmpb $$0, offThread_subMode(%ecx) # special action needed?
+ cmpw $$0, offThread_subMode(%ecx) # special action needed?
jne 19f # go if so
14:
+ movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST
cmpl $$0,rINST # break?
je common_gotoBail # break frame, bail out completely
movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC
movl rINST,offThread_method(%ecx) # self->method = newSave->meethod
- movl rFP,offThread_curFrame(%ecx) # self->curFrame = fp
+ movl rFP,offThread_curFrame(%ecx) # curFrame = fp
movl offMethod_clazz(rINST),%eax # eax<- method->clazz
movl offThread_curHandlerTable(%ecx),rIBASE
movl offClassObject_pDvmDex(%eax),rINST # rINST<- method->clazz->pDvmDex
@@ -516,7 +516,7 @@
* Handle special subMode actions
* On entry, rFP: prevFP, %ecx: self, %eax: saveArea
*/
- movl rFP, offThread_fp(%ecx) # update interpSave.fp
+ movl rFP, offThread_curFrame(%ecx) # update interpSave.curFrame
movl rPC, offThread_pc(%ecx) # update interpSave.pc
movl %ecx, OUT_ARG0(%esp) # parameter self
call dvmReportReturn # (self)
@@ -537,7 +537,7 @@
*/
common_gotoBail:
movl rPC,offThread_pc(%ecx) # export state to self
- movl rFP,offThread_fp(%ecx)
+ movl rFP,offThread_curFrame(%ecx)
movl %ecx,OUT_ARG0(%esp) # self in arg0
movl rINST,OUT_ARG1(%esp) # changeInterp in arg1
call dvmMterpStdBail # bail out....
@@ -550,7 +550,7 @@
common_resumeAfterGlueCall:
movl rSELF, %eax
movl offThread_pc(%eax),rPC
- movl offThread_fp(%eax),rFP
+ movl offThread_curFrame(%eax),rFP
movl offThread_curHandlerTable(%eax),rIBASE
FETCH_INST
GOTO_NEXT
@@ -625,7 +625,7 @@
common_exceptionThrown:
movl rSELF,%ecx
movl rPC,offThread_pc(%ecx)
- movl rFP,offThread_fp(%ecx)
+ movl rFP,offThread_curFrame(%ecx)
movl %ecx,OUT_ARG0(%esp)
call dvmMterp_exceptionThrown
jmp common_resumeAfterGlueCall
diff --git a/vm/mterp/x86/header.S b/vm/mterp/x86/header.S
index 0a34a6f..6f3be0c 100644
--- a/vm/mterp/x86/header.S
+++ b/vm/mterp/x86/header.S
@@ -123,13 +123,13 @@
.macro SAVE_PC_FP_TO_SELF _reg
movl rSELF,\_reg
movl rPC,offThread_pc(\_reg)
- movl rFP,offThread_fp(\_reg)
+ movl rFP,offThread_curFrame(\_reg)
.endm
.macro LOAD_PC_FP_FROM_SELF
movl rSELF,rFP
movl offThread_pc(rFP),rPC
- movl offThread_fp(rFP),rFP
+ movl offThread_curFrame(rFP),rFP
.endm
/* The interpreter assumes a properly aligned stack on entry, and
diff --git a/vm/native/InternalNative.c b/vm/native/InternalNative.cpp
similarity index 98%
rename from vm/native/InternalNative.c
rename to vm/native/InternalNative.cpp
index c873472..7ebe8b9 100644
--- a/vm/native/InternalNative.c
+++ b/vm/native/InternalNative.cpp
@@ -67,7 +67,7 @@
/*
* Set up hash values on the class names.
*/
-bool dvmInternalNativeStartup(void)
+bool dvmInternalNativeStartup()
{
DalvikNativeClass* classPtr = gDvmNativeMethodSet;
@@ -87,7 +87,7 @@
/*
* Clean up.
*/
-void dvmInternalNativeShutdown(void)
+void dvmInternalNativeShutdown()
{
dvmHashTableFree(gDvm.userDexFiles);
}
diff --git a/vm/native/InternalNative.h b/vm/native/InternalNative.h
index 7c82dc0..e6b210d 100644
--- a/vm/native/InternalNative.h
+++ b/vm/native/InternalNative.h
@@ -27,6 +27,6 @@
DalvikNativeFunc dvmLookupInternalNativeMethod(const Method* method);
/* exception-throwing stub for abstract methods (DalvikNativeFunc) */
-void dvmAbstractMethodStub(const u4* args, JValue* pResult);
+extern "C" void dvmAbstractMethodStub(const u4* args, JValue* pResult);
#endif /*_DALVIK_NATIVE_INTERNALNATIVE*/
diff --git a/vm/native/InternalNativePriv.h b/vm/native/InternalNativePriv.h
index 440e60d..9489ca2 100644
--- a/vm/native/InternalNativePriv.h
+++ b/vm/native/InternalNativePriv.h
@@ -34,7 +34,7 @@
#define RETURN_LONG(_val) do { pResult->j = (_val); return; } while(0)
#define RETURN_FLOAT(_val) do { pResult->f = (_val); return; } while(0)
#define RETURN_DOUBLE(_val) do { pResult->d = (_val); return; } while(0)
-#define RETURN_PTR(_val) do { pResult->l = (_val); return; } while(0)
+#define RETURN_PTR(_val) do { pResult->l = (Object*)(_val); return; } while(0)
/*
* Normally a method that has an "inline native" will be invoked using
diff --git a/vm/native/dalvik_bytecode_OpcodeInfo.c b/vm/native/dalvik_bytecode_OpcodeInfo.cpp
similarity index 95%
rename from vm/native/dalvik_bytecode_OpcodeInfo.c
rename to vm/native/dalvik_bytecode_OpcodeInfo.cpp
index cabd7b1..3861fef 100644
--- a/vm/native/dalvik_bytecode_OpcodeInfo.c
+++ b/vm/native/dalvik_bytecode_OpcodeInfo.cpp
@@ -31,7 +31,7 @@
static void Dalvik_dalvik_bytecode_OpcodeInfo_isInvoke(const u4* args,
JValue* pResult)
{
- jint opcode = (jint) args[0];
+ Opcode opcode = static_cast<Opcode>(args[0]);
int flags = dexGetFlagsFromOpcode(opcode);
bool result = (flags & kInstrInvoke) != 0;
RETURN_BOOLEAN(result);
diff --git a/vm/native/dalvik_system_DexFile.c b/vm/native/dalvik_system_DexFile.cpp
similarity index 98%
rename from vm/native/dalvik_system_DexFile.c
rename to vm/native/dalvik_system_DexFile.cpp
index 5ebb529..59dddfc 100644
--- a/vm/native/dalvik_system_DexFile.c
+++ b/vm/native/dalvik_system_DexFile.cpp
@@ -34,14 +34,14 @@
/*
* Internal struct for managing DexFile.
*/
-typedef struct DexOrJar {
+struct DexOrJar {
char* fileName;
bool isDex;
bool okayToFree;
RawDexFile* pRawDexFile;
JarFile* pJarFile;
u1* pDexMemory; // malloc()ed memory, if any
-} DexOrJar;
+};
/*
* (This is a dvmHashTableFree callback.)
@@ -408,24 +408,24 @@
{
int cookie = args[0];
DexOrJar* pDexOrJar = (DexOrJar*) cookie;
- DvmDex* pDvmDex;
- DexFile* pDexFile;
- ArrayObject* stringArray;
Thread* self = dvmThreadSelf();
if (!validateCookie(cookie))
RETURN_VOID();
+ DvmDex* pDvmDex;
if (pDexOrJar->isDex)
pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
else
pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
assert(pDvmDex != NULL);
- pDexFile = pDvmDex->pDexFile;
+ DexFile* pDexFile = pDvmDex->pDexFile;
int count = pDexFile->pHeader->classDefsSize;
- stringArray = dvmAllocObjectArray(gDvm.classJavaLangString, count,
- ALLOC_DEFAULT);
+ ClassObject* arrayClass =
+ dvmFindArrayClassForElement(gDvm.classJavaLangString);
+ ArrayObject* stringArray =
+ dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT);
if (stringArray == NULL) {
/* probably OOM */
LOGD("Failed allocating array of %d strings\n", count);
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.cpp
similarity index 96%
rename from vm/native/dalvik_system_VMDebug.c
rename to vm/native/dalvik_system_VMDebug.cpp
index 146f562..cfd8ebc 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.cpp
@@ -21,10 +21,8 @@
#include "native/InternalNativePriv.h"
#include "hprof/Hprof.h"
-#include <cutils/array.h>
#include <string.h>
#include <unistd.h>
-#include <errno.h>
/*
@@ -51,30 +49,20 @@
* static String[] getVmFeatureList()
*
* Return a set of strings describing available VM features (this is chiefly
- * of interest to DDMS). Some features may be controlled by compile-time
- * or command-line flags.
+ * of interest to DDMS).
*/
static void Dalvik_dalvik_system_VMDebug_getVmFeatureList(const u4* args,
JValue* pResult)
{
- Array* features = arrayCreate();
-
- /* VM responds to DDMS method profiling requests */
- arrayAdd(features, "method-trace-profiling");
- arrayAdd(features, "method-trace-profiling-streaming");
- /* VM responds to DDMS heap dump requests */
- arrayAdd(features, "hprof-heap-dump");
- arrayAdd(features, "hprof-heap-dump-streaming");
-
- char** strings = (char**) arrayUnwrap(features);
- int count = arraySize(features);
- ArrayObject* result = dvmCreateStringArray(strings, count);
+ const char* strings[] = { "method-trace-profiling",
+ "method-trace-profiling-streaming",
+ "hprof-heap-dump",
+ "hprof-heap-dump-streaming" };
+ ArrayObject* result = dvmCreateStringArray(strings, NELEM(strings));
dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf());
- arrayFree(features);
RETURN_PTR(result);
}
-
/* These must match the values in dalvik.system.VMDebug.
*/
enum {
@@ -416,7 +404,7 @@
ArrayObject* countArray = (ArrayObject*) args[0];
if (countArray != NULL) {
- int* storage = (int*) countArray->contents;
+ int* storage = (int*)(void*)countArray->contents;
u4 length = countArray->length;
/*
diff --git a/vm/native/dalvik_system_VMRuntime.c b/vm/native/dalvik_system_VMRuntime.cpp
similarity index 94%
rename from vm/native/dalvik_system_VMRuntime.c
rename to vm/native/dalvik_system_VMRuntime.cpp
index 55b0283..7345386 100644
--- a/vm/native/dalvik_system_VMRuntime.c
+++ b/vm/native/dalvik_system_VMRuntime.cpp
@@ -18,6 +18,7 @@
* dalvik.system.VMRuntime
*/
#include "Dalvik.h"
+#include "ScopedPthreadMutexLock.h"
#include "native/InternalNativePriv.h"
#include <cutils/array.h>
@@ -64,12 +65,10 @@
JValue* pResult)
{
#if defined(WITH_JIT)
- if (gDvm.executionMode == kExecutionModeJit &&
- gDvmJit.disableJit == false) {
- dvmLockMutex(&gDvmJit.compilerLock);
+ if (gDvm.executionMode == kExecutionModeJit && gDvmJit.disableJit == false) {
+ ScopedPthreadMutexLock lock(&gDvmJit.compilerLock);
gDvmJit.alreadyEnabledViaFramework = true;
pthread_cond_signal(&gDvmJit.compilerQueueActivity);
- dvmUnlockMutex(&gDvmJit.compilerLock);
}
#endif
RETURN_VOID();
@@ -114,7 +113,7 @@
ClassObject* arrayClass = dvmFindArrayClassForElement(elementClass);
ArrayObject* newArray = dvmAllocArrayByClass(arrayClass,
length,
- ALLOC_DEFAULT);
+ ALLOC_NON_MOVING);
if (newArray == NULL) {
assert(dvmCheckException(dvmThreadSelf()));
RETURN_VOID();
@@ -147,7 +146,7 @@
static void Dalvik_dalvik_system_VMRuntime_properties(const u4* args,
JValue* pResult)
{
- char** strings = (char**) arrayUnwrap(gDvm.properties);
+ const char** strings = (const char**) arrayUnwrap(gDvm.properties);
int count = arraySize(gDvm.properties);
ArrayObject* result = dvmCreateStringArray(strings, count);
dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf());
diff --git a/vm/native/dalvik_system_VMStack.c b/vm/native/dalvik_system_VMStack.cpp
similarity index 78%
rename from vm/native/dalvik_system_VMStack.c
rename to vm/native/dalvik_system_VMStack.cpp
index 045a100..e69fa93 100644
--- a/vm/native/dalvik_system_VMStack.c
+++ b/vm/native/dalvik_system_VMStack.cpp
@@ -18,9 +18,9 @@
* dalvik.system.VMStack
*/
#include "Dalvik.h"
+#include "UniquePtr.h"
#include "native/InternalNativePriv.h"
-
/*
* public static ClassLoader getCallingClassLoader()
*
@@ -29,7 +29,8 @@
static void Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4* args,
JValue* pResult)
{
- ClassObject* clazz = dvmGetCaller2Class(dvmThreadSelf()->curFrame);
+ ClassObject* clazz =
+ dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);
UNUSED_PARAMETER(args);
@@ -46,7 +47,8 @@
static void Dalvik_dalvik_system_VMStack_getCallingClassLoader2(const u4* args,
JValue* pResult)
{
- ClassObject* clazz = dvmGetCaller3Class(dvmThreadSelf()->curFrame);
+ ClassObject* clazz =
+ dvmGetCaller3Class(dvmThreadSelf()->interpSave.curFrame);
UNUSED_PARAMETER(args);
@@ -63,7 +65,8 @@
static void Dalvik_dalvik_system_VMStack_getStackClass2(const u4* args,
JValue* pResult)
{
- ClassObject* clazz = dvmGetCaller3Class(dvmThreadSelf()->curFrame);
+ ClassObject* clazz =
+ dvmGetCaller3Class(dvmThreadSelf()->interpSave.curFrame);
UNUSED_PARAMETER(args);
@@ -81,36 +84,23 @@
JValue* pResult)
{
/* note "maxSize" is unsigned, so -1 turns into a very large value */
- unsigned int maxSize = args[0];
- unsigned int size = 0;
- const unsigned int kSkip = 2;
- const Method** methods = NULL;
- int methodCount;
+ size_t maxSize = args[0];
+ size_t size = 0;
+ const size_t kSkip = 2;
/*
* Get an array with the stack trace in it.
*/
- if (!dvmCreateStackTraceArray(dvmThreadSelf()->curFrame, &methods,
- &methodCount))
- {
- LOGE("Failed to create stack trace array\n");
- dvmThrowInternalError(NULL);
- RETURN_VOID();
- }
-
- //int i;
- //LOGI("dvmCreateStackTraceArray results:\n");
- //for (i = 0; i < methodCount; i++) {
- // LOGI(" %2d: %s.%s\n",
- // i, methods[i]->clazz->descriptor, methods[i]->name);
- //}
+ void *fp = dvmThreadSelf()->interpSave.curFrame;
+ size_t depth = dvmComputeExactFrameDepth(fp);
+ UniquePtr<const Method*[]> methods(new const Method*[depth]);
+ dvmFillStackTraceArray(fp, methods.get(), depth);
/*
* Run through the array and count up how many elements there are.
*/
- unsigned int idx;
- for (idx = kSkip; (int) idx < methodCount && size < maxSize; idx++) {
- const Method* meth = methods[idx];
+ for (size_t i = kSkip; i < depth && size < maxSize; ++i) {
+ const Method* meth = methods[i];
if (dvmIsReflectionMethod(meth))
continue;
@@ -122,37 +112,35 @@
* Create an array object to hold the classes.
* TODO: can use gDvm.classJavaLangClassArray here?
*/
- ClassObject* classArrayClass = NULL;
- ArrayObject* classes = NULL;
- classArrayClass = dvmFindArrayClass("[Ljava/lang/Class;", NULL);
+ ClassObject* classArrayClass = dvmFindArrayClass("[Ljava/lang/Class;",
+ NULL);
if (classArrayClass == NULL) {
- LOGW("Unable to find java.lang.Class array class\n");
- goto bail;
+ LOGW("Unable to find java.lang.Class array class");
+ return;
}
- classes = dvmAllocArray(classArrayClass, size, kObjectArrayRefWidth,
- ALLOC_DEFAULT);
+ ArrayObject* classes = dvmAllocArrayByClass(classArrayClass,
+ size,
+ ALLOC_DEFAULT);
if (classes == NULL) {
- LOGW("Unable to allocate class array (%d elems)\n", size);
- goto bail;
+ LOGW("Unable to allocate class array of %zd elements", size);
+ return;
}
/*
* Fill in the array.
*/
- unsigned int objCount = 0;
- for (idx = kSkip; (int) idx < methodCount; idx++) {
- if (dvmIsReflectionMethod(methods[idx])) {
+ size_t objCount = 0;
+ for (size_t i = kSkip; i < depth; ++i) {
+ if (dvmIsReflectionMethod(methods[i])) {
continue;
}
- dvmSetObjectArrayElement(classes, objCount,
- (Object *)methods[idx]->clazz);
+ Object* klass = (Object *)methods[i]->clazz;
+ dvmSetObjectArrayElement(classes, objCount, klass);
objCount++;
}
assert(objCount == classes->length);
-bail:
- free(methods);
- dvmReleaseTrackedAlloc((Object*) classes, NULL);
+ dvmReleaseTrackedAlloc((Object*)classes, NULL);
RETURN_PTR(classes);
}
diff --git a/vm/native/dalvik_system_Zygote.c b/vm/native/dalvik_system_Zygote.cpp
similarity index 97%
rename from vm/native/dalvik_system_Zygote.c
rename to vm/native/dalvik_system_Zygote.cpp
index 6f7e6fa..79d46ce 100644
--- a/vm/native/dalvik_system_Zygote.c
+++ b/vm/native/dalvik_system_Zygote.cpp
@@ -168,7 +168,7 @@
/* just in case gid_t and u4 are different... */
gids = (gid_t *)alloca(sizeof(gid_t) * gidArray->length);
- contents = (s4 *)gidArray->contents;
+ contents = (s4 *)(void *)gidArray->contents;
for (i = 0 ; i < gidArray->length ; i++) {
gids[i] = (gid_t) contents[i];
@@ -196,11 +196,11 @@
memset (&rlim, 0, sizeof(rlim));
- ArrayObject** tuples = (ArrayObject **)(rlimits->contents);
+ ArrayObject** tuples = (ArrayObject **)(void *)rlimits->contents;
for (i = 0; i < rlimits->length; i++) {
ArrayObject * rlimit_tuple = tuples[i];
- s4* contents = (s4 *)rlimit_tuple->contents;
+ s4* contents = (s4 *)(void *)rlimit_tuple->contents;
int err;
if (rlimit_tuple->length != 3) {
@@ -262,9 +262,7 @@
* easy to handle, because the JDWP thread isn't started until we call
* dvmInitAfterZygote().
* checkjni
- * If set, make sure "check JNI" is eabled. This is a little weird,
- * because we already have the JNIEnv for the main thread set up. However,
- * since we only have one thread at this point, it's easy to patch up.
+ * If set, make sure "check JNI" is enabled.
* assert
* If set, make sure assertions are enabled. This gets fairly weird,
* because it affects the result of a method called by class initializers,
diff --git a/vm/native/java_lang_Class.c b/vm/native/java_lang_Class.cpp
similarity index 98%
rename from vm/native/java_lang_Class.c
rename to vm/native/java_lang_Class.cpp
index a3839a3..790e7b7 100644
--- a/vm/native/java_lang_Class.c
+++ b/vm/native/java_lang_Class.cpp
@@ -192,7 +192,7 @@
}
} else if (publicOnly) {
u4 count, newIdx, publicCount = 0;
- ClassObject** pSource = (ClassObject**) classes->contents;
+ ClassObject** pSource = (ClassObject**)(void*)classes->contents;
u4 length = classes->length;
/* count up public classes */
@@ -536,7 +536,7 @@
* constructor must be public or, if the caller is in the same package,
* have package scope.
*/
- ClassObject* callerClass = dvmGetCaller2Class(self->curFrame);
+ ClassObject* callerClass = dvmGetCaller2Class(self->interpSave.curFrame);
if (!dvmCheckClassAccess(callerClass, clazz)) {
LOGD("newInstance failed: %s not accessible to %s\n",
diff --git a/vm/native/java_lang_Double.c b/vm/native/java_lang_Double.cpp
similarity index 100%
rename from vm/native/java_lang_Double.c
rename to vm/native/java_lang_Double.cpp
diff --git a/vm/native/java_lang_Float.c b/vm/native/java_lang_Float.cpp
similarity index 100%
rename from vm/native/java_lang_Float.c
rename to vm/native/java_lang_Float.cpp
diff --git a/vm/native/java_lang_Math.c b/vm/native/java_lang_Math.cpp
similarity index 100%
rename from vm/native/java_lang_Math.c
rename to vm/native/java_lang_Math.cpp
diff --git a/vm/native/java_lang_Object.c b/vm/native/java_lang_Object.cpp
similarity index 100%
rename from vm/native/java_lang_Object.c
rename to vm/native/java_lang_Object.cpp
diff --git a/vm/native/java_lang_Runtime.c b/vm/native/java_lang_Runtime.cpp
similarity index 100%
rename from vm/native/java_lang_Runtime.c
rename to vm/native/java_lang_Runtime.cpp
diff --git a/vm/native/java_lang_String.c b/vm/native/java_lang_String.cpp
similarity index 100%
rename from vm/native/java_lang_String.c
rename to vm/native/java_lang_String.cpp
diff --git a/vm/native/java_lang_System.c b/vm/native/java_lang_System.cpp
similarity index 97%
rename from vm/native/java_lang_System.c
rename to vm/native/java_lang_System.cpp
index ad0b397..06ab5f8 100644
--- a/vm/native/java_lang_System.c
+++ b/vm/native/java_lang_System.cpp
@@ -51,7 +51,7 @@
#endif
#ifdef HAVE_MEMMOVE_WORDS
-extern void _memmove_words(void* dest, const void* src, size_t n);
+extern "C" void _memmove_words(void* dest, const void* src, size_t n);
#define move16 _memmove_words
#define move32 _memmove_words
#else
@@ -155,8 +155,8 @@
RETURN_VOID();
}
- srcClass = srcArray->obj.clazz;
- dstClass = dstArray->obj.clazz;
+ srcClass = srcArray->clazz;
+ dstClass = dstArray->clazz;
srcType = srcClass->descriptor[1];
dstType = dstClass->descriptor[1];
@@ -252,8 +252,8 @@
int copyCount;
ClassObject* clazz = NULL;
- srcObj = ((Object**) srcArray->contents) + srcPos;
- dstObj = ((Object**) dstArray->contents) + dstPos;
+ srcObj = ((Object**)(void*)srcArray->contents) + srcPos;
+ dstObj = ((Object**)(void*)dstArray->contents) + dstPos;
if (length > 0 && srcObj[0] != NULL)
{
diff --git a/vm/native/java_lang_Throwable.c b/vm/native/java_lang_Throwable.cpp
similarity index 100%
rename from vm/native/java_lang_Throwable.c
rename to vm/native/java_lang_Throwable.cpp
diff --git a/vm/native/java_lang_VMClassLoader.c b/vm/native/java_lang_VMClassLoader.cpp
similarity index 98%
rename from vm/native/java_lang_VMClassLoader.c
rename to vm/native/java_lang_VMClassLoader.cpp
index 387290c..770ce5e 100644
--- a/vm/native/java_lang_VMClassLoader.c
+++ b/vm/native/java_lang_VMClassLoader.cpp
@@ -154,7 +154,7 @@
{
int primType = args[0];
- pResult->l = dvmFindPrimitiveClass(primType);
+ pResult->l = (Object*)dvmFindPrimitiveClass(primType);
}
/*
diff --git a/vm/native/java_lang_VMThread.c b/vm/native/java_lang_VMThread.cpp
similarity index 100%
rename from vm/native/java_lang_VMThread.c
rename to vm/native/java_lang_VMThread.cpp
diff --git a/vm/native/java_lang_reflect_AccessibleObject.c b/vm/native/java_lang_reflect_AccessibleObject.cpp
similarity index 100%
rename from vm/native/java_lang_reflect_AccessibleObject.c
rename to vm/native/java_lang_reflect_AccessibleObject.cpp
diff --git a/vm/native/java_lang_reflect_Array.c b/vm/native/java_lang_reflect_Array.cpp
similarity index 94%
rename from vm/native/java_lang_reflect_Array.c
rename to vm/native/java_lang_reflect_Array.cpp
index fe6647cd..007d738 100644
--- a/vm/native/java_lang_reflect_Array.c
+++ b/vm/native/java_lang_reflect_Array.cpp
@@ -32,7 +32,6 @@
{
ClassObject* elementClass = (ClassObject*) args[0];
int length = args[1];
- ArrayObject* newArray;
assert(elementClass != NULL); // tested by caller
if (length < 0) {
@@ -40,7 +39,10 @@
RETURN_VOID();
}
- newArray = dvmAllocObjectArray(elementClass, length, ALLOC_DEFAULT);
+ ClassObject* arrayClass =
+ dvmFindArrayClassForElement(elementClass);
+ ArrayObject* newArray =
+ dvmAllocArrayByClass(arrayClass, length, ALLOC_DEFAULT);
if (newArray == NULL) {
assert(dvmCheckException(dvmThreadSelf()));
RETURN_VOID();
@@ -87,7 +89,7 @@
numDim = dimArray->length;
assert(numDim > 0 && numDim <= 255);
- dimensions = (int*) dimArray->contents;
+ dimensions = (int*)(void*)dimArray->contents;
for (i = 0; i < numDim; i++) {
if (dimensions[i] < 0) {
dvmThrowNegativeArraySizeException(dimensions[i]);
diff --git a/vm/native/java_lang_reflect_Constructor.c b/vm/native/java_lang_reflect_Constructor.cpp
similarity index 100%
rename from vm/native/java_lang_reflect_Constructor.c
rename to vm/native/java_lang_reflect_Constructor.cpp
diff --git a/vm/native/java_lang_reflect_Field.c b/vm/native/java_lang_reflect_Field.cpp
similarity index 99%
rename from vm/native/java_lang_reflect_Field.c
rename to vm/native/java_lang_reflect_Field.cpp
index 2e8aab5..dc7d556 100644
--- a/vm/native/java_lang_reflect_Field.c
+++ b/vm/native/java_lang_reflect_Field.cpp
@@ -71,7 +71,7 @@
}
ClassObject* callerClass =
- dvmGetCaller2Class(dvmThreadSelf()->curFrame);
+ dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);
/*
* We need to check two things:
diff --git a/vm/native/java_lang_reflect_Method.c b/vm/native/java_lang_reflect_Method.cpp
similarity index 100%
rename from vm/native/java_lang_reflect_Method.c
rename to vm/native/java_lang_reflect_Method.cpp
diff --git a/vm/native/java_lang_reflect_Proxy.c b/vm/native/java_lang_reflect_Proxy.cpp
similarity index 100%
rename from vm/native/java_lang_reflect_Proxy.c
rename to vm/native/java_lang_reflect_Proxy.cpp
diff --git a/vm/native/java_util_concurrent_atomic_AtomicLong.c b/vm/native/java_util_concurrent_atomic_AtomicLong.cpp
similarity index 100%
rename from vm/native/java_util_concurrent_atomic_AtomicLong.c
rename to vm/native/java_util_concurrent_atomic_AtomicLong.cpp
diff --git a/vm/native/org_apache_harmony_dalvik_NativeTestTarget.c b/vm/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
similarity index 100%
rename from vm/native/org_apache_harmony_dalvik_NativeTestTarget.c
rename to vm/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
diff --git a/vm/native/org_apache_harmony_dalvik_ddmc_DdmServer.c b/vm/native/org_apache_harmony_dalvik_ddmc_DdmServer.cpp
similarity index 100%
rename from vm/native/org_apache_harmony_dalvik_ddmc_DdmServer.c
rename to vm/native/org_apache_harmony_dalvik_ddmc_DdmServer.cpp
diff --git a/vm/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.c b/vm/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cpp
similarity index 100%
rename from vm/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.c
rename to vm/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cpp
diff --git a/vm/native/sun_misc_Unsafe.c b/vm/native/sun_misc_Unsafe.cpp
similarity index 99%
rename from vm/native/sun_misc_Unsafe.c
rename to vm/native/sun_misc_Unsafe.cpp
index 16e3ec0..db8493b 100644
--- a/vm/native/sun_misc_Unsafe.c
+++ b/vm/native/sun_misc_Unsafe.cpp
@@ -42,7 +42,7 @@
{
// The base offset is not type-dependent in this vm.
UNUSED_PARAMETER(args);
- RETURN_INT(offsetof(ArrayObject, contents));
+ RETURN_INT(OFFSETOF_MEMBER(ArrayObject, contents));
}
/*
diff --git a/vm/oo/AccessCheck.c b/vm/oo/AccessCheck.cpp
similarity index 100%
rename from vm/oo/AccessCheck.c
rename to vm/oo/AccessCheck.cpp
diff --git a/vm/oo/Array.c b/vm/oo/Array.cpp
similarity index 91%
rename from vm/oo/Array.c
rename to vm/oo/Array.cpp
index 48602d1..f227908 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.cpp
@@ -22,6 +22,9 @@
#include <stddef.h>
#include <limits.h>
+/* width of an object reference, for arrays of objects */
+static size_t kObjectArrayRefWidth = sizeof(Object*);
+
static ClassObject* createArrayClass(const char* descriptor, Object* loader);
/*
@@ -32,7 +35,7 @@
*
* On failure, returns NULL with an exception raised.
*/
-ArrayObject* dvmAllocArray(ClassObject* arrayClass, size_t length,
+static ArrayObject* allocArray(ClassObject* arrayClass, size_t length,
size_t elemWidth, int allocFlags)
{
assert(arrayClass != NULL);
@@ -44,7 +47,7 @@
assert((elemWidth & (elemWidth - 1)) == 0);
size_t elementShift = sizeof(size_t) * CHAR_BIT - 1 - CLZ(elemWidth);
size_t elementSize = length << elementShift;
- size_t headerSize = offsetof(ArrayObject, contents);
+ size_t headerSize = OFFSETOF_MEMBER(ArrayObject, contents);
size_t totalSize = elementSize + headerSize;
if (elementSize >> elementShift != length || totalSize < elementSize) {
char *descriptor = dvmHumanReadableDescriptor(arrayClass->descriptor);
@@ -55,7 +58,7 @@
}
ArrayObject* newArray = (ArrayObject*)dvmMalloc(totalSize, allocFlags);
if (newArray != NULL) {
- DVM_OBJECT_INIT(&newArray->obj, arrayClass);
+ DVM_OBJECT_INIT(newArray, arrayClass);
newArray->length = length;
dvmTrackAllocation(arrayClass, totalSize);
}
@@ -77,7 +80,7 @@
assert(descriptor[2] == '\0');
return dvmAllocPrimitiveArray(descriptor[1], length, allocFlags);
} else {
- return dvmAllocArray(arrayClass, length, kObjectArrayRefWidth,
+ return allocArray(arrayClass, length, kObjectArrayRefWidth,
allocFlags);
}
}
@@ -104,36 +107,6 @@
}
/*
- * Create a new array that holds references to members of the specified class.
- *
- * "elemClassObj" is the element type, and may itself be an array class. It
- * may not be a primitive class.
- *
- * "allocFlags" determines whether the new object will be added to the
- * "tracked alloc" table.
- *
- * This is less efficient than dvmAllocArray(), but occasionally convenient.
- */
-ArrayObject* dvmAllocObjectArray(ClassObject* elemClassObj, size_t length,
- int allocFlags)
-{
- ClassObject* arrayClass;
- ArrayObject* newArray = NULL;
-
- LOGVV("dvmAllocObjectArray: '%s' len=%d\n",
- elemClassObj->descriptor, (int)length);
-
- arrayClass = dvmFindArrayClassForElement(elemClassObj);
- if (arrayClass != NULL) {
- newArray = dvmAllocArray(arrayClass, length, kObjectArrayRefWidth,
- allocFlags);
- }
-
- /* the caller must call dvmReleaseTrackedAlloc */
- return newArray;
-}
-
-/*
* Create a new array that holds primitive types.
*
* "type" is the primitive type letter, e.g. 'I' for int or 'J' for long.
@@ -183,7 +156,7 @@
return NULL; // Keeps the compiler happy.
}
- newArray = dvmAllocArray(arrayClass, length, width, allocFlags);
+ newArray = allocArray(arrayClass, length, width, allocFlags);
/* the caller must dvmReleaseTrackedAlloc if allocFlags==ALLOC_DEFAULT */
return newArray;
@@ -209,7 +182,7 @@
if (*elemName == 'L' || *elemName == '[') {
LOGVV(" end: array class (obj) is '%s'\n",
arrayClass->descriptor);
- newArray = dvmAllocArray(arrayClass, *dimensions,
+ newArray = allocArray(arrayClass, *dimensions,
kObjectArrayRefWidth, ALLOC_DEFAULT);
} else {
LOGVV(" end: array class (prim) is '%s'\n",
@@ -232,7 +205,7 @@
assert(dvmIsArrayClass(subArrayClass));
/* allocate the array that holds the sub-arrays */
- newArray = dvmAllocArray(arrayClass, *dimensions, kObjectArrayRefWidth,
+ newArray = allocArray(arrayClass, *dimensions, kObjectArrayRefWidth,
ALLOC_DEFAULT);
if (newArray == NULL) {
assert(dvmCheckException(dvmThreadSelf()));
@@ -390,7 +363,7 @@
* Array classes are simple enough that we don't need to do a full
* link step.
*/
- newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
+ newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_NON_MOVING);
if (newClass == NULL)
return NULL;
DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
@@ -520,13 +493,13 @@
bool dvmCopyObjectArray(ArrayObject* dstArray, const ArrayObject* srcArray,
ClassObject* dstElemClass)
{
- Object** src = (Object**)srcArray->contents;
+ Object** src = (Object**)(void*)srcArray->contents;
u4 length, count;
assert(srcArray->length == dstArray->length);
- assert(dstArray->obj.clazz->elementClass == dstElemClass ||
- (dstArray->obj.clazz->elementClass == dstElemClass->elementClass &&
- dstArray->obj.clazz->arrayDim == dstElemClass->arrayDim+1));
+ assert(dstArray->clazz->elementClass == dstElemClass ||
+ (dstArray->clazz->elementClass == dstElemClass->elementClass &&
+ dstArray->clazz->arrayDim == dstElemClass->arrayDim+1));
length = dstArray->length;
for (count = 0; count < length; count++) {
@@ -549,7 +522,7 @@
bool dvmUnboxObjectArray(ArrayObject* dstArray, const ArrayObject* srcArray,
ClassObject* dstElemClass)
{
- Object** src = (Object**)srcArray->contents;
+ Object** src = (Object**)(void*)srcArray->contents;
void* dst = (void*)dstArray->contents;
u4 count = dstArray->length;
PrimitiveType typeIndex = dstElemClass->primitiveType;
@@ -650,10 +623,8 @@
size_t dvmArrayObjectSize(const ArrayObject *array)
{
- size_t size;
-
assert(array != NULL);
- size = offsetof(ArrayObject, contents);
- size += array->length * dvmArrayClassElementWidth(array->obj.clazz);
+ size_t size = OFFSETOF_MEMBER(ArrayObject, contents);
+ size += array->length * dvmArrayClassElementWidth(array->clazz);
return size;
}
diff --git a/vm/oo/Array.h b/vm/oo/Array.h
index 9a873e6..ea68f84 100644
--- a/vm/oo/Array.h
+++ b/vm/oo/Array.h
@@ -19,9 +19,6 @@
#ifndef _DALVIK_OO_ARRAY
#define _DALVIK_OO_ARRAY
-/* width of an object reference, for arrays of objects */
-#define kObjectArrayRefWidth sizeof(Object*)
-
/*
* Find a matching array class. If it doesn't exist, create it.
*
@@ -39,42 +36,15 @@
ClassObject* dvmFindArrayClassForElement(ClassObject* elemClassObj);
/*
- * Allocate space for a new array object.
- *
- * "allocFlags" determines whether the new object will be added to the
- * "tracked alloc" table.
- *
- * Returns NULL with an exception raised if allocation fails.
- */
-ArrayObject* dvmAllocArray(ClassObject* arrayClass, size_t length,
- size_t elemWidth, int allocFlags);
-
-/*
* Create a new array, given an array class. The class may represent an
* array of references or primitives.
*
* Returns NULL with an exception raised if allocation fails.
*/
-ArrayObject* dvmAllocArrayByClass(ClassObject* arrayClass,
+extern "C" ArrayObject* dvmAllocArrayByClass(ClassObject* arrayClass,
size_t length, int allocFlags);
/*
- * Create a new array that holds references to members of the specified class.
- *
- * "elemClassObj" is the element type, and may itself be an array class. It
- * may not be a primitive class.
- *
- * "allocFlags" determines whether the new object will be added to the
- * "tracked alloc" table.
- *
- * This is less efficient than dvmAllocArray(), but occasionally convenient.
- *
- * Returns NULL with an exception raised if allocation fails.
- */
-ArrayObject* dvmAllocObjectArray(ClassObject* elemClassObj, size_t length,
- int allocFlags);
-
-/*
* Allocate an array whose members are primitives (bools, ints, etc.).
*
* "type" should be 'I', 'J', 'Z', etc.
@@ -125,7 +95,7 @@
*/
INLINE bool dvmIsObjectArray(const ArrayObject* arrayObj)
{
- return dvmIsObjectArrayClass(arrayObj->obj.clazz);
+ return dvmIsObjectArrayClass(arrayObj->clazz);
}
/*
diff --git a/vm/oo/Class.c b/vm/oo/Class.cpp
similarity index 97%
rename from vm/oo/Class.c
rename to vm/oo/Class.cpp
index 1206383..cfb1050 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.cpp
@@ -341,14 +341,14 @@
const char* descriptor = dexGetPrimitiveTypeDescriptor(primitiveType);
assert(descriptor != NULL);
- ClassObject* newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
+ ClassObject* newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_NON_MOVING);
if (newClass == NULL) {
return false;
}
DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
dvmSetClassSerialNumber(newClass);
- newClass->accessFlags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+ SET_CLASS_FLAG(newClass, ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
newClass->primitiveType = primitiveType;
newClass->descriptorAlloc = NULL;
newClass->descriptor = descriptor;
@@ -369,17 +369,18 @@
* Create the initial class instances. These consist of the class
* Class and all of the classes representing primitive types.
*/
-static bool createInitialClasses(void) {
+static bool createInitialClasses() {
/*
* Initialize the class Class. This has to be done specially, particularly
* because it is an instance of itself.
*/
ClassObject* clazz = (ClassObject*)
- dvmMalloc(classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_DEFAULT);
+ dvmMalloc(classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_NON_MOVING);
if (clazz == NULL) {
return false;
}
DVM_OBJECT_INIT(&clazz->obj, clazz);
+ SET_CLASS_FLAG(clazz, ACC_PUBLIC | ACC_FINAL | CLASS_ISCLASS);
clazz->descriptor = "Ljava/lang/Class;";
gDvm.classJavaLangClass = clazz;
LOGVV("Constructed the class Class.\n");
@@ -408,7 +409,7 @@
*
* Call this after the bootclasspath string has been finalized.
*/
-bool dvmClassStartup(void)
+bool dvmClassStartup()
{
/* make this a requirement -- don't currently support dirs in path */
if (strcmp(gDvm.bootClassPathStr, ".") == 0) {
@@ -467,7 +468,7 @@
/*
* Clean up.
*/
-void dvmClassShutdown(void)
+void dvmClassShutdown()
{
/* discard all system-loaded classes */
dvmHashTableFree(gDvm.loadedClasses);
@@ -532,7 +533,7 @@
/*
* Dump the contents of the bootstrap class path.
*/
-void dvmDumpBootClassPath(void)
+void dvmDumpBootClassPath()
{
dumpClassPath(gDvm.bootClassPath);
}
@@ -859,7 +860,7 @@
*
* (Used for ClassLoader.getResources().)
*/
-int dvmGetBootPathSize(void)
+int dvmGetBootPathSize()
{
const ClassPathEntry* cpe = gDvm.bootClassPath;
@@ -936,10 +937,10 @@
*/
/* search for these criteria in the Class hash table */
-typedef struct ClassMatchCriteria {
+struct ClassMatchCriteria {
const char* descriptor;
Object* loader;
-} ClassMatchCriteria;
+};
#define kInitLoaderInc 4 /* must be power of 2 */
@@ -1204,7 +1205,7 @@
/*
* Check the performance of the "loadedClasses" hash table.
*/
-void dvmCheckClassTablePerf(void)
+void dvmCheckClassTablePerf()
{
dvmHashTableLock(gDvm.loadedClasses);
dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
@@ -1324,7 +1325,6 @@
// descriptor, loader);
Thread* self = dvmThreadSelf();
- ClassObject* clazz;
assert(loader != NULL);
@@ -1338,7 +1338,7 @@
* lookup-by-descriptor twice. It appears this is still a win, so
* I'm keeping it in.
*/
- clazz = dvmLookupClass(descriptor, loader, false);
+ ClassObject* clazz = dvmLookupClass(descriptor, loader, false);
if (clazz != NULL) {
LOGVV("Already loaded: %s %p\n", descriptor, loader);
return clazz;
@@ -1353,7 +1353,7 @@
dotName = dvmDescriptorToDot(descriptor);
if (dotName == NULL) {
dvmThrowOutOfMemoryError(NULL);
- goto bail;
+ return NULL;
}
nameObj = dvmCreateStringFromCstr(dotName);
if (nameObj == NULL) {
@@ -1370,30 +1370,31 @@
* the bootstrap class loader can find it before doing its own load.
*/
LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
- const Method* loadClass =
- loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
- JValue result;
- dvmCallMethod(self, loadClass, loader, &result, nameObj);
- clazz = (ClassObject*) result.l;
+ {
+ const Method* loadClass =
+ loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
+ JValue result;
+ dvmCallMethod(self, loadClass, loader, &result, nameObj);
+ clazz = (ClassObject*) result.l;
- dvmMethodTraceClassPrepEnd();
-
- Object* excep = dvmGetException(self);
- if (excep != NULL) {
+ dvmMethodTraceClassPrepEnd();
+ Object* excep = dvmGetException(self);
+ if (excep != NULL) {
#if DVM_SHOW_EXCEPTION >= 2
- LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
- dotName, loader, excep->clazz->descriptor);
+ LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
+ dotName, loader, excep->clazz->descriptor);
#endif
- dvmAddTrackedAlloc(excep, self);
- dvmClearException(self);
- dvmThrowChainedNoClassDefFoundError(descriptor, excep);
- dvmReleaseTrackedAlloc(excep, self);
- clazz = NULL;
- goto bail;
- } else if (clazz == NULL) {
- LOGW("ClassLoader returned NULL w/o exception pending\n");
- dvmThrowNullPointerException("ClassLoader returned null");
- goto bail;
+ dvmAddTrackedAlloc(excep, self);
+ dvmClearException(self);
+ dvmThrowChainedNoClassDefFoundError(descriptor, excep);
+ dvmReleaseTrackedAlloc(excep, self);
+ clazz = NULL;
+ goto bail;
+ } else if (clazz == NULL) {
+ LOGW("ClassLoader returned NULL w/o exception pending\n");
+ dvmThrowNullPointerException("ClassLoader returned null");
+ goto bail;
+ }
}
/* not adding clazz to tracked-alloc list, because it's a ClassObject */
@@ -1707,6 +1708,7 @@
assert(dvmIsClassLinked(clazz));
assert(gDvm.classJavaLangClass != NULL);
assert(clazz->obj.clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(&clazz->obj));
assert(clazz == gDvm.classJavaLangObject || clazz->super != NULL);
if (!dvmIsInterfaceClass(clazz)) {
//LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
@@ -1764,7 +1766,7 @@
newClass = gDvm.classJavaLangClass;
} else {
size_t size = classObjectSize(pHeader->staticFieldsSize);
- newClass = (ClassObject*) dvmMalloc(size, ALLOC_DEFAULT);
+ newClass = (ClassObject*) dvmMalloc(size, ALLOC_NON_MOVING);
}
if (newClass == NULL)
return NULL;
@@ -1773,7 +1775,7 @@
dvmSetClassSerialNumber(newClass);
newClass->descriptor = descriptor;
assert(newClass->descriptorAlloc == NULL);
- newClass->accessFlags = pClassDef->accessFlags;
+ SET_CLASS_FLAG(newClass, pClassDef->accessFlags);
dvmSetFieldObject((Object *)newClass,
offsetof(ClassObject, classLoader),
(Object *)classLoader);
@@ -2004,6 +2006,7 @@
return;
assert(clazz->obj.clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(&clazz->obj));
/* Guarantee that dvmFreeClassInnards can be called on a given
* class multiple times by clearing things out as we free them.
@@ -2352,10 +2355,6 @@
*/
//sfield->value.j = 0;
assert(sfield->value.j == 0LL); // cleared earlier with calloc
-
-#ifdef PROFILE_FIELD_ACCESS
- sfield->field.gets = sfield->field.puts = 0;
-#endif
}
/*
@@ -2377,10 +2376,6 @@
assert(ifield->byteOffset == 0); // cleared earlier with calloc
ifield->byteOffset = -1; // make it obvious if we fail to set later
#endif
-
-#ifdef PROFILE_FIELD_ACCESS
- ifield->field.gets = ifield->field.puts = 0;
-#endif
}
/*
@@ -2525,6 +2520,7 @@
assert(gDvm.classJavaLangClass != NULL);
assert(clazz->obj.clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(&clazz->obj));
if (clazz->classLoader == NULL &&
(strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
{
@@ -2539,6 +2535,7 @@
dvmAbort();
}
}
+
/* "Resolve" the class.
*
* At this point, clazz's reference fields may contain Dex file
@@ -2857,6 +2854,7 @@
if (interfaceIdxArray != NULL) {
free(interfaceIdxArray);
}
+
return okay;
}
@@ -3017,17 +3015,19 @@
bool zapIftable = false;
bool zapVtable = false;
bool zapIfvipool = false;
- int ifCount, superIfCount, idx;
- int i;
+ int poolOffset = 0, poolSize = 0;
+ Method** mirandaList = NULL;
+ int mirandaCount = 0, mirandaAlloc = 0;
+ int superIfCount;
if (clazz->super != NULL)
superIfCount = clazz->super->iftableCount;
else
superIfCount = 0;
- ifCount = superIfCount;
+ int ifCount = superIfCount;
ifCount += clazz->interfaceCount;
- for (i = 0; i < clazz->interfaceCount; i++)
+ for (int i = 0; i < clazz->interfaceCount; i++)
ifCount += clazz->interfaces[i]->iftableCount;
LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
@@ -3036,8 +3036,7 @@
if (ifCount == 0) {
assert(clazz->iftableCount == 0);
assert(clazz->iftable == NULL);
- result = true;
- goto bail;
+ return true;
}
/*
@@ -3056,13 +3055,10 @@
/*
* Create a flattened interface hierarchy of our immediate interfaces.
*/
- idx = superIfCount;
+ int idx = superIfCount;
- for (i = 0; i < clazz->interfaceCount; i++) {
- ClassObject* interf;
- int j;
-
- interf = clazz->interfaces[i];
+ for (int i = 0; i < clazz->interfaceCount; i++) {
+ ClassObject* interf = clazz->interfaces[i];
assert(interf != NULL);
/* make sure this is still an interface class */
@@ -3078,7 +3074,7 @@
clazz->iftable[idx++].clazz = interf;
/* add entries for the interface's superinterfaces */
- for (j = 0; j < interf->iftableCount; j++) {
+ for (int j = 0; j < interf->iftableCount; j++) {
clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
}
}
@@ -3105,10 +3101,8 @@
* because it wants to return just the interfaces declared to be
* implemented directly by the class. I'm excluding this code for now.
*/
- for (i = superIfCount; i < ifCount; i++) {
- int j;
-
- for (j = 0; j < ifCount; j++) {
+ for (int i = superIfCount; i < ifCount; i++) {
+ for (int j = 0; j < ifCount; j++) {
if (i == j)
continue;
if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
@@ -3158,8 +3152,7 @@
* is flat for fast access in a class and all of its subclasses, but
* "ifviPool" is only created for the topmost implementor.
*/
- int poolSize = 0;
- for (i = superIfCount; i < ifCount; i++) {
+ for (int i = superIfCount; i < ifCount; i++) {
/*
* Note it's valid for an interface to have no methods (e.g.
* java/io/Serializable).
@@ -3185,11 +3178,7 @@
* Fill in the vtable offsets for the interfaces that weren't part of
* our superclass.
*/
- int poolOffset = 0;
- Method** mirandaList = NULL;
- int mirandaCount = 0, mirandaAlloc = 0;
-
- for (i = superIfCount; i < ifCount; i++) {
+ for (int i = superIfCount; i < ifCount; i++) {
ClassObject* interface;
int methIdx;
@@ -3325,7 +3314,7 @@
Method* meth;
int oldMethodCount, oldVtableCount;
- for (i = 0; i < mirandaCount; i++) {
+ for (int i = 0; i < mirandaCount; i++) {
LOGVV("MIRANDA %d: %s.%s\n", i,
mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
}
@@ -3375,7 +3364,7 @@
LOGVV("MIRANDA fixing vtable pointers\n");
dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
Method* meth = newVirtualMethods;
- for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
+ for (int i = 0; i < clazz->virtualMethodCount; i++, meth++)
clazz->vtable[meth->methodIndex] = meth;
dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
}
@@ -3411,7 +3400,7 @@
* dvmAbstractMethodStub().
*/
meth = clazz->virtualMethods + oldMethodCount;
- for (i = 0; i < mirandaCount; i++, meth++) {
+ for (int i = 0; i < mirandaCount; i++, meth++) {
dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
cloneMethod(meth, mirandaList[i]);
meth->clazz = clazz;
@@ -3564,7 +3553,7 @@
if (clazz->super != NULL)
fieldOffset = clazz->super->objectSize;
else
- fieldOffset = offsetof(DataObject, instanceData);
+ fieldOffset = OFFSETOF_MEMBER(DataObject, instanceData);
LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
@@ -3755,7 +3744,7 @@
* We map a C struct directly on top of java/lang/Class objects. Make
* sure we left enough room for the instance fields.
*/
- assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
+ assert(!dvmIsTheClassClass(clazz) || (size_t)fieldOffset <
offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
clazz->objectSize = fieldOffset;
@@ -4168,9 +4157,9 @@
*/
bool dvmIsClassInitializing(const ClassObject* clazz)
{
- ClassStatus status;
-
- status = android_atomic_acquire_load((ClassStatus*) &clazz->status);
+ const int32_t* addr = (const int32_t*)(const void*)&clazz->status;
+ int32_t value = android_atomic_acquire_load(addr);
+ ClassStatus status = static_cast<ClassStatus>(value);
return (status == CLASS_INITIALIZING &&
clazz->initThreadId == dvmThreadSelf()->threadId);
}
@@ -4241,6 +4230,8 @@
*/
bool dvmInitClass(ClassObject* clazz)
{
+ u8 startWhen = 0;
+
#if LOG_CLASS_LOADING
bool initializedByUs = false;
#endif
@@ -4406,7 +4397,6 @@
return false;
}
- u8 startWhen = 0;
if (gDvm.allocProf.enabled) {
startWhen = dvmGetRelativeTimeNsec();
}
@@ -4449,7 +4439,8 @@
/* order matters here, esp. interaction with dvmIsClassInitializing */
clazz->initThreadId = self->threadId;
- android_atomic_release_store(CLASS_INITIALIZING, &clazz->status);
+ android_atomic_release_store(CLASS_INITIALIZING,
+ (int32_t*)(void*)&clazz->status);
dvmUnlockObject(self, (Object*) clazz);
/* init our superclass */
@@ -4653,7 +4644,7 @@
*
* The caller must call dvmReleaseTrackedAlloc on the result.
*/
-Object* dvmGetSystemClassLoader(void)
+Object* dvmGetSystemClassLoader()
{
Thread* self = dvmThreadSelf();
ClassObject* clClass = gDvm.classJavaLangClassLoader;
@@ -4838,50 +4829,6 @@
#endif
}
-#ifdef PROFILE_FIELD_ACCESS
-/*
- * Dump the field access counts for all fields in this method.
- */
-static int dumpAccessCounts(void* vclazz, void* varg)
-{
- const ClassObject* clazz = (const ClassObject*) vclazz;
- int i;
-
- for (i = 0; i < clazz->ifieldCount; i++) {
- Field* field = &clazz->ifields[i].field;
-
- if (field->gets != 0)
- printf("GI %d %s.%s\n", field->gets,
- field->clazz->descriptor, field->name);
- if (field->puts != 0)
- printf("PI %d %s.%s\n", field->puts,
- field->clazz->descriptor, field->name);
- }
- for (i = 0; i < clazz->sfieldCount; i++) {
- Field* field = &clazz->sfields[i].field;
-
- if (field->gets != 0)
- printf("GS %d %s.%s\n", field->gets,
- field->clazz->descriptor, field->name);
- if (field->puts != 0)
- printf("PS %d %s.%s\n", field->puts,
- field->clazz->descriptor, field->name);
- }
-
- return 0;
-}
-
-/*
- * Dump the field access counts for all loaded classes.
- */
-void dvmDumpFieldAccessCounts(void)
-{
- dvmHashTableLock(gDvm.loadedClasses);
- dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
- dvmHashTableUnlock(gDvm.loadedClasses);
-}
-#endif
-
/*
* ===========================================================================
* Method Prototypes and Descriptors
diff --git a/vm/oo/Class.h b/vm/oo/Class.h
index 3ad44bd..025989e 100644
--- a/vm/oo/Class.h
+++ b/vm/oo/Class.h
@@ -35,17 +35,19 @@
* Ordering is significant. (Currently only ".dex" is supported directly
* by the VM.)
*/
-typedef struct ClassPathEntry {
- enum {
- kCpeUnknown = 0,
- kCpeDir,
- kCpeJar,
- kCpeDex,
- kCpeLastEntry /* used as sentinel at end of array */
- } kind;
+enum ClassPathEntryKind {
+ kCpeUnknown = 0,
+ kCpeDir,
+ kCpeJar,
+ kCpeDex,
+ kCpeLastEntry /* used as sentinel at end of array */
+};
+
+struct ClassPathEntry {
+ ClassPathEntryKind kind;
char* fileName;
void* ptr; /* JarFile* or DexFile* */
-} ClassPathEntry;
+};
bool dvmClassStartup(void);
void dvmClassShutdown(void);
@@ -128,7 +130,7 @@
/*
* Initialize a class.
*/
-bool dvmInitClass(ClassObject* clazz);
+extern "C" bool dvmInitClass(ClassObject* clazz);
/*
* Retrieve the system class loader.
@@ -178,10 +180,6 @@
void dvmDumpLoaderStats(const char* msg);
int dvmGetNumLoadedClasses();
-#ifdef PROFILE_FIELD_ACCESS
-void dvmDumpFieldAccessCounts(void);
-#endif
-
/* flags for dvmDumpClass / dvmDumpAllClasses */
#define kDumpClassFullDetail 1
#define kDumpClassClassLoader (1 << 1)
diff --git a/vm/oo/Object.c b/vm/oo/Object.cpp
similarity index 99%
rename from vm/oo/Object.c
rename to vm/oo/Object.cpp
index 00df420..ef4bc8b 100644
--- a/vm/oo/Object.c
+++ b/vm/oo/Object.cpp
@@ -787,7 +787,7 @@
clazz = clazz->super;
}
- if (obj->clazz == gDvm.classJavaLangClass) {
+ if (dvmIsClassObject(obj)) {
LOGD(" Static fields:");
const StaticField* sfields = &((ClassObject *)obj)->sfields[0];
for (i = 0; i < ((ClassObject *)obj)->sfieldCount; ++i) {
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index b32d5b9..c647a90 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -21,9 +21,8 @@
#ifndef _DALVIK_OO_OBJECT
#define _DALVIK_OO_OBJECT
-#include <Atomic.h>
-
#include <stddef.h>
+#include "Atomic.h"
/* fwd decl */
struct DataObject;
@@ -38,18 +37,6 @@
struct InstField;
struct Field;
struct RegisterMap;
-typedef struct DataObject DataObject;
-typedef struct InitiatingLoaderList InitiatingLoaderList;
-typedef struct ClassObject ClassObject;
-typedef struct StringObject StringObject;
-typedef struct ArrayObject ArrayObject;
-typedef struct Method Method;
-typedef struct ExceptionEntry ExceptionEntry;
-typedef struct LineNumEntry LineNumEntry;
-typedef struct StaticField StaticField;
-typedef struct InstField InstField;
-typedef struct Field Field;
-typedef struct RegisterMap RegisterMap;
/*
* Native function pointer type.
@@ -67,32 +54,33 @@
/* vm-internal access flags and related definitions */
-typedef enum AccessFlags {
+enum AccessFlags {
ACC_MIRANDA = 0x8000, // method (internal to VM)
JAVA_FLAGS_MASK = 0xffff, // bits set from Java sources (low 16)
-} AccessFlags;
+};
/* Use the top 16 bits of the access flags field for
* other class flags. Code should use the *CLASS_FLAG*()
* macros to set/get these flags.
*/
-typedef enum ClassFlags {
- CLASS_ISFINALIZABLE = (1<<31), // class/ancestor overrides finalize()
- CLASS_ISARRAY = (1<<30), // class is a "[*"
- CLASS_ISOBJECTARRAY = (1<<29), // class is a "[L*" or "[[*"
+enum ClassFlags {
+ CLASS_ISFINALIZABLE = (1<<31), // class/ancestor overrides finalize()
+ CLASS_ISARRAY = (1<<30), // class is a "[*"
+ CLASS_ISOBJECTARRAY = (1<<29), // class is a "[L*" or "[[*"
+ CLASS_ISCLASS = (1<<28), // class is *the* class Class
- CLASS_ISREFERENCE = (1<<28), // class is a soft/weak/phantom ref
- // only ISREFERENCE is set --> soft
- CLASS_ISWEAKREFERENCE = (1<<27), // class is a weak reference
- CLASS_ISFINALIZERREFERENCE = (1<<26), // class is a phantom reference
- CLASS_ISPHANTOMREFERENCE = (1<<25), // class is a phantom reference
+ CLASS_ISREFERENCE = (1<<27), // class is a soft/weak/phantom ref
+ // only ISREFERENCE is set --> soft
+ CLASS_ISWEAKREFERENCE = (1<<26), // class is a weak reference
+ CLASS_ISFINALIZERREFERENCE = (1<<25), // class is a finalizer reference
+ CLASS_ISPHANTOMREFERENCE = (1<<24), // class is a phantom reference
- CLASS_MULTIPLE_DEFS = (1<<24), // DEX verifier: defs in multiple DEXs
+ CLASS_MULTIPLE_DEFS = (1<<23), // DEX verifier: defs in multiple DEXs
/* unlike the others, these can be present in the optimized DEX file */
- CLASS_ISOPTIMIZED = (1<<17), // class may contain opt instrs
- CLASS_ISPREVERIFIED = (1<<16), // class has been pre-verified
-} ClassFlags;
+ CLASS_ISOPTIMIZED = (1<<17), // class may contain opt instrs
+ CLASS_ISPREVERIFIED = (1<<16), // class has been pre-verified
+};
/* bits we can reasonably expect to see set in a DEX access flags field */
#define EXPECTED_FILE_FLAGS \
@@ -117,9 +105,9 @@
* Use the top 16 bits of the access flags field for other method flags.
* Code should use the *METHOD_FLAG*() macros to set/get these flags.
*/
-typedef enum MethodFlags {
+enum MethodFlags {
METHOD_ISWRITABLE = (1<<31), // the method's code is writable
-} MethodFlags;
+};
/*
* Get/set method flags.
@@ -137,7 +125,7 @@
((u4)((method)->accessFlags & (flags)))
/* current state of the class, increasing as we progress */
-typedef enum ClassStatus {
+enum ClassStatus {
CLASS_ERROR = -1,
CLASS_NOTREADY = 0,
@@ -148,7 +136,7 @@
CLASS_VERIFIED = 5, /* logically part of linking; done pre-init */
CLASS_INITIALIZING = 6, /* class init in progress */
CLASS_INITIALIZED = 7, /* ready to go */
-} ClassStatus;
+};
/*
* Definitions for packing refOffsets in ClassObject.
@@ -192,7 +180,7 @@
/*
* Used for iftable in ClassObject.
*/
-typedef struct InterfaceEntry {
+struct InterfaceEntry {
/* pointer to interface class */
ClassObject* clazz;
@@ -201,7 +189,7 @@
* which holds the vtables for all interfaces declared by this class.
*/
int* methodIndexArray;
-} InterfaceEntry;
+};
@@ -217,7 +205,7 @@
*
* All objects have an Object header followed by type-specific data.
*/
-typedef struct Object {
+struct Object {
/* ptr to class object */
ClassObject* clazz;
@@ -226,25 +214,19 @@
* the comments in Sync.c for a description of its layout.
*/
u4 lock;
-} Object;
+};
/*
* Properly initialize an Object.
* void DVM_OBJECT_INIT(Object *obj, ClassObject *clazz_)
*/
-#define DVM_OBJECT_INIT(obj, clazz_) \
- do { \
- dvmSetFieldObject((Object *)obj, offsetof(Object, clazz), \
- (Object *)clazz_); \
- DVM_LOCK_INIT(&(obj)->lock); \
- } while (0)
+#define DVM_OBJECT_INIT(obj, clazz_) \
+ dvmSetFieldObject((Object *)obj, OFFSETOF_MEMBER(Object, clazz), (Object *)clazz_)
/*
* Data objects have an Object header followed by their instance data.
*/
-struct DataObject {
- Object obj; /* MUST be first item */
-
+struct DataObject : Object {
/* variable #of u4 slots; u8 uses 2 slots */
u4 instanceData[1];
};
@@ -275,9 +257,7 @@
* by the instruction. If necessary, the width can be derived from
* the first char of obj->clazz->descriptor.
*/
-struct ArrayObject {
- Object obj; /* MUST be first item */
-
+struct ArrayObject : Object {
/* number of elements; immutable after init */
u4 length;
@@ -311,10 +291,6 @@
const char* name;
const char* signature; /* e.g. "I", "[C", "Landroid/os/Debug;" */
u4 accessFlags;
-#ifdef PROFILE_FIELD_ACCESS
- u4 gets;
- u4 puts;
-#endif
};
/*
@@ -750,6 +726,24 @@
}
/*
+ * Return whether the given object is an instance of Class.
+ */
+INLINE bool dvmIsClassObject(const Object* obj) {
+ assert(obj != NULL);
+ assert(obj->clazz != NULL);
+ return IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISCLASS);
+}
+
+/*
+ * Return whether the given object is the class Class (that is, the
+ * unique class which is an instance of itself).
+ */
+INLINE bool dvmIsTheClassClass(const ClassObject* clazz) {
+ assert(clazz != NULL);
+ return IS_CLASS_FLAG_SET(clazz, CLASS_ISCLASS);
+}
+
+/*
* Get the associated code struct for a method. This returns NULL
* for non-bytecode methods.
*/
diff --git a/vm/oo/ObjectInlines.h b/vm/oo/ObjectInlines.h
index ef01834..7035d0e 100644
--- a/vm/oo/ObjectInlines.h
+++ b/vm/oo/ObjectInlines.h
@@ -118,7 +118,7 @@
return alias.dval;
}
INLINE Object* dvmGetFieldObjectVolatile(const Object* obj, int offset) {
- void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
+ Object** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
return (Object*)android_atomic_acquire_load((int32_t*)ptr);
}
@@ -193,7 +193,7 @@
dvmSetFieldLongVolatile(obj, offset, alias.lval);
}
INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
- void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
+ Object** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
ANDROID_MEMBAR_STORE();
*ptr = val;
ANDROID_MEMBAR_FULL();
@@ -276,7 +276,7 @@
return alias.dval;
}
INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
- void* const* ptr = &(sfield->value.l);
+ Object* const* ptr = &(sfield->value.l);
return (Object*)android_atomic_acquire_load((int32_t*)ptr);
}
@@ -345,7 +345,7 @@
dvmSetStaticFieldLongVolatile(sfield, alias.lval);
}
INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
- void** ptr = &(sfield->value.l);
+ Object** ptr = &(sfield->value.l);
ANDROID_MEMBAR_STORE();
*ptr = val;
ANDROID_MEMBAR_FULL();
diff --git a/vm/oo/Resolve.c b/vm/oo/Resolve.cpp
similarity index 100%
rename from vm/oo/Resolve.c
rename to vm/oo/Resolve.cpp
diff --git a/vm/oo/Resolve.h b/vm/oo/Resolve.h
index 70b2294..5eb6814 100644
--- a/vm/oo/Resolve.h
+++ b/vm/oo/Resolve.h
@@ -27,13 +27,13 @@
* (<clinit>, <init>, and methods declared "private" or "static" are stored
* in the "direct" list. All others are stored in the "virtual" list.)
*/
-typedef enum MethodType {
+enum MethodType {
METHOD_UNKNOWN = 0,
METHOD_DIRECT, // <init>, private
METHOD_STATIC, // static
METHOD_VIRTUAL, // virtual, super
METHOD_INTERFACE // interface
-} MethodType;
+};
/*
* Resolve a class, given the referring class and a constant pool index
@@ -43,8 +43,9 @@
*
* Throws an exception and returns NULL on failure.
*/
-ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx,
- bool fromUnverifiedConstant);
+extern "C" ClassObject* dvmResolveClass(const ClassObject* referrer,
+ u4 classIdx,
+ bool fromUnverifiedConstant);
/*
* Resolve a direct, static, or virtual method.
@@ -54,8 +55,8 @@
*
* Throws an exception and returns NULL on failure.
*/
-Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
- MethodType methodType);
+extern "C" Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
+ MethodType methodType);
/*
* Resolve an interface method.
@@ -69,7 +70,8 @@
*
* Throws an exception and returns NULL on failure.
*/
-InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx);
+extern "C" InstField* dvmResolveInstField(const ClassObject* referrer,
+ u4 ifieldIdx);
/*
* Resolve a static field.
@@ -78,14 +80,15 @@
*
* Throws an exception and returns NULL on failure.
*/
-StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx);
+extern "C" StaticField* dvmResolveStaticField(const ClassObject* referrer,
+ u4 sfieldIdx);
/*
* Resolve a "const-string" reference.
*
* Throws an exception and returns NULL on failure.
*/
-StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx);
+extern "C" StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx);
/*
* Return debug string constant for enum.
diff --git a/vm/oo/TypeCheck.c b/vm/oo/TypeCheck.cpp
similarity index 98%
rename from vm/oo/TypeCheck.c
rename to vm/oo/TypeCheck.cpp
index fdd38ea..1116d15 100644
--- a/vm/oo/TypeCheck.c
+++ b/vm/oo/TypeCheck.cpp
@@ -36,7 +36,7 @@
/*
* Allocate cache.
*/
-bool dvmInstanceofStartup(void)
+bool dvmInstanceofStartup()
{
gDvm.instanceofCache = dvmAllocAtomicCache(INSTANCEOF_CACHE_SIZE);
if (gDvm.instanceofCache == NULL)
@@ -47,7 +47,7 @@
/*
* Discard the cache.
*/
-void dvmInstanceofShutdown(void)
+void dvmInstanceofShutdown()
{
dvmFreeAtomicCache(gDvm.instanceofCache);
}
diff --git a/vm/oo/TypeCheck.h b/vm/oo/TypeCheck.h
index 1397998..6ffdfe8 100644
--- a/vm/oo/TypeCheck.h
+++ b/vm/oo/TypeCheck.h
@@ -25,8 +25,8 @@
/* used by dvmInstanceof; don't call */
-int dvmInstanceofNonTrivial(const ClassObject* instance,
- const ClassObject* clazz);
+extern "C" int dvmInstanceofNonTrivial(const ClassObject* instance,
+ const ClassObject* clazz);
/*
* Determine whether "instance" is an instance of "clazz".
@@ -72,7 +72,7 @@
*
* Returns 0 (false) if not, 1 (true) if so.
*/
-bool dvmCanPutArrayElement(const ClassObject* elemClass,
+extern "C" bool dvmCanPutArrayElement(const ClassObject* elemClass,
const ClassObject* arrayClass);
#endif /*_DALVIK_OO_TYPECHECK*/
diff --git a/vm/reflect/Annotation.c b/vm/reflect/Annotation.cpp
similarity index 99%
rename from vm/reflect/Annotation.c
rename to vm/reflect/Annotation.cpp
index f0d0dc9..6b33af3 100644
--- a/vm/reflect/Annotation.c
+++ b/vm/reflect/Annotation.cpp
@@ -106,7 +106,7 @@
*
* Caller must call dvmReleaseTrackedAlloc().
*/
-static ArrayObject* emptyAnnoArray(void)
+static ArrayObject* emptyAnnoArray()
{
return dvmAllocArrayByClass(
gDvm.classJavaLangAnnotationAnnotationArray, 0, ALLOC_DEFAULT);
@@ -126,7 +126,7 @@
arr = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArrayArray,
numElements, ALLOC_DEFAULT);
if (arr != NULL) {
- ArrayObject** elems = (ArrayObject**) arr->contents;
+ ArrayObject** elems = (ArrayObject**)(void*)arr->contents;
for (i = 0; i < numElements; i++) {
elems[i] = emptyAnnoArray();
dvmReleaseTrackedAlloc((Object*)elems[i], self);
@@ -283,11 +283,11 @@
* constants for processAnnotationValue indicating what style of
* result is wanted
*/
-typedef enum {
+enum AnnotationResultStyle {
kAllObjects, /* return everything as an object */
kAllRaw, /* return everything as a raw value or index */
kPrimitivesOrObjects /* return primitives as-is but the rest as objects */
-} AnnotationResultStyle;
+};
/*
* Recursively process an annotation value.
@@ -1360,7 +1360,7 @@
if (obj == GAV_FAILED)
return NULL;
- assert(obj->clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(obj));
return (ClassObject*)obj;
}
@@ -1391,7 +1391,7 @@
obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
"EnclosingClass");
if (obj != GAV_FAILED) {
- assert(obj->clazz == gDvm.classJavaLangClass);
+ assert(dvmIsClassObject(obj));
return (ClassObject*)obj;
}
}
diff --git a/vm/reflect/Proxy.c b/vm/reflect/Proxy.cpp
similarity index 86%
rename from vm/reflect/Proxy.c
rename to vm/reflect/Proxy.cpp
index 60483de..6953930 100644
--- a/vm/reflect/Proxy.c
+++ b/vm/reflect/Proxy.cpp
@@ -67,16 +67,12 @@
Object* loader)
{
int result = -1;
- char* nameStr = NULL;
- Method** methods = NULL;
ArrayObject* throws = NULL;
- ClassObject* newClass = NULL;
- int i;
- nameStr = dvmCreateCstrFromString(str);
+ char* nameStr = dvmCreateCstrFromString(str);
if (nameStr == NULL) {
dvmThrowIllegalArgumentException("missing name");
- goto bail;
+ return NULL;
}
LOGV("+++ Generate proxy class '%s' %p from %d interface classes\n",
@@ -104,25 +100,19 @@
*/
/*
- * Generate a temporary list of virtual methods.
- */
- int methodCount = -1;
- if (!gatherMethods(interfaces, &methods, &throws, &methodCount))
- goto bail;
-
- /*
* Allocate storage for the class object and set some basic fields.
*/
- newClass = (ClassObject*) dvmMalloc(sizeof(*newClass) +
- kProxySFieldCount * sizeof(StaticField),
- ALLOC_DEFAULT);
+ size_t newClassSize =
+ sizeof(ClassObject) + kProxySFieldCount * sizeof(StaticField);
+ ClassObject* newClass =
+ (ClassObject*) dvmMalloc(newClassSize, ALLOC_NON_MOVING);
if (newClass == NULL)
goto bail;
DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
dvmSetClassSerialNumber(newClass);
newClass->descriptorAlloc = dvmNameToDescriptor(nameStr);
newClass->descriptor = newClass->descriptorAlloc;
- newClass->accessFlags = ACC_PUBLIC | ACC_FINAL;
+ SET_CLASS_FLAG(newClass, ACC_PUBLIC | ACC_FINAL);
dvmSetFieldObject((Object *)newClass,
offsetof(ClassObject, super),
(Object *)gDvm.classJavaLangReflectProxy);
@@ -143,25 +133,40 @@
/*
* Add virtual method definitions.
*/
- newClass->virtualMethodCount = methodCount;
- newClass->virtualMethods = (Method*) dvmLinearAlloc(newClass->classLoader,
- newClass->virtualMethodCount * sizeof(Method));
- for (i = 0; i < newClass->virtualMethodCount; i++) {
- createHandlerMethod(newClass, &newClass->virtualMethods[i],methods[i]);
+ {
+ /*
+ * Generate a temporary list of virtual methods.
+ */
+ int methodCount;
+ Method **methods;
+ if (!gatherMethods(interfaces, &methods, &throws, &methodCount)) {
+ goto bail;
+ }
+ newClass->virtualMethodCount = methodCount;
+ size_t virtualMethodsSize = methodCount * sizeof(Method);
+ newClass->virtualMethods =
+ (Method*)dvmLinearAlloc(newClass->classLoader, virtualMethodsSize);
+ for (int i = 0; i < newClass->virtualMethodCount; i++) {
+ createHandlerMethod(newClass, &newClass->virtualMethods[i], methods[i]);
+ }
+ free(methods);
+ dvmLinearReadOnly(newClass->classLoader, newClass->virtualMethods);
}
- dvmLinearReadOnly(newClass->classLoader, newClass->virtualMethods);
/*
* Add interface list.
*/
- int interfaceCount = interfaces->length;
- ClassObject** ifArray = (ClassObject**) interfaces->contents;
- newClass->interfaceCount = interfaceCount;
- newClass->interfaces = (ClassObject**)dvmLinearAlloc(newClass->classLoader,
- sizeof(ClassObject*) * interfaceCount);
- for (i = 0; i < interfaceCount; i++)
- newClass->interfaces[i] = ifArray[i];
- dvmLinearReadOnly(newClass->classLoader, newClass->interfaces);
+ {
+ size_t interfaceCount = interfaces->length;
+ ClassObject** ifArray = (ClassObject**)(void*)interfaces->contents;
+ newClass->interfaceCount = interfaceCount;
+ size_t interfacesSize = sizeof(ClassObject*) * interfaceCount;
+ newClass->interfaces =
+ (ClassObject**)dvmLinearAlloc(newClass->classLoader, interfacesSize);
+ for (size_t i = 0; i < interfaceCount; i++)
+ newClass->interfaces[i] = ifArray[i];
+ dvmLinearReadOnly(newClass->classLoader, newClass->interfaces);
+ }
/*
* Static field list. We have one private field, for our list of
@@ -169,12 +174,14 @@
*/
assert(kProxySFieldCount == 1);
newClass->sfieldCount = kProxySFieldCount;
- StaticField* sfield = &newClass->sfields[kThrowsField];
- sfield->field.clazz = newClass;
- sfield->field.name = "throws";
- sfield->field.signature = "[[Ljava/lang/Throwable;";
- sfield->field.accessFlags = ACC_STATIC | ACC_PRIVATE;
- dvmSetStaticFieldObject(sfield, (Object*)throws);
+ {
+ StaticField* sfield = &newClass->sfields[kThrowsField];
+ sfield->field.clazz = newClass;
+ sfield->field.name = "throws";
+ sfield->field.signature = "[[Ljava/lang/Throwable;";
+ sfield->field.accessFlags = ACC_STATIC | ACC_PRIVATE;
+ dvmSetStaticFieldObject(sfield, (Object*)throws);
+ }
/*
* Everything is ready. This class didn't come out of a DEX file
@@ -202,7 +209,6 @@
bail:
free(nameStr);
- free(methods);
if (result != 0) {
/* must free innards explicitly if we didn't finish linking */
dvmFreeClassInnards(newClass);
@@ -247,7 +253,7 @@
*/
maxCount = 3; // 3 methods in java.lang.Object
numInterfaces = interfaces->length;
- classes = (ClassObject**) interfaces->contents;
+ classes = (ClassObject**)(void*)interfaces->contents;
for (i = 0; i < numInterfaces; i++, classes++) {
ClassObject* clazz = *classes;
@@ -274,16 +280,18 @@
/*
* First three entries are the java.lang.Object methods.
*/
- ClassObject* obj = gDvm.classJavaLangObject;
- allMethods[0] = obj->vtable[gDvm.voffJavaLangObject_equals];
- allMethods[1] = obj->vtable[gDvm.voffJavaLangObject_hashCode];
- allMethods[2] = obj->vtable[gDvm.voffJavaLangObject_toString];
- allCount = 3;
+ {
+ ClassObject* obj = gDvm.classJavaLangObject;
+ allMethods[0] = obj->vtable[gDvm.voffJavaLangObject_equals];
+ allMethods[1] = obj->vtable[gDvm.voffJavaLangObject_hashCode];
+ allMethods[2] = obj->vtable[gDvm.voffJavaLangObject_toString];
+ allCount = 3;
+ }
/*
* Add the methods from each interface, in order.
*/
- classes = (ClassObject**) interfaces->contents;
+ classes = (ClassObject**)(void*)interfaces->contents;
for (i = 0; i < numInterfaces; i++, classes++) {
ClassObject* clazz = *classes;
int j;
@@ -488,14 +496,14 @@
return -1;
}
- contents = (Object**) throwArray->contents;
+ contents = (Object**)(void*)throwArray->contents;
for (ent = 0; ent < commonCount; ent++) {
contents[ent] = (Object*)
dvmPointerSetGetEntry(commonThrows, ent);
}
/* add it to the array of arrays */
- contents = (Object**) throwLists->contents;
+ contents = (Object**)(void*)throwLists->contents;
contents[outCount] = (Object*) throwArray;
dvmReleaseTrackedAlloc((Object*) throwArray, NULL);
}
@@ -521,7 +529,7 @@
if (exceptionArray != NULL) {
Object** contents;
- contents = (Object**) throwLists->contents;
+ contents = (Object**)(void*)throwLists->contents;
contents[outCount] = (Object*) exceptionArray;
dvmReleaseTrackedAlloc((Object*) exceptionArray, NULL);
}
@@ -559,18 +567,18 @@
*/
static void reduceExceptionClassList(ArrayObject* exceptionArray)
{
- const ClassObject** classes = (const ClassObject**)exceptionArray->contents;
- int len = exceptionArray->length;
- int i, j;
+ const ClassObject** classes =
+ (const ClassObject**)(void*)exceptionArray->contents;
/*
* Consider all pairs of classes. If one is the subclass of the other,
* null out the subclass.
*/
- for (i = 0; i < len-1; i++) {
+ size_t len = exceptionArray->length;
+ for (size_t i = 0; i < len - 1; i++) {
if (classes[i] == NULL)
continue;
- for (j = i + 1; j < len; j++) {
+ for (size_t j = i + 1; j < len; j++) {
if (classes[j] == NULL)
continue;
@@ -605,10 +613,9 @@
goto bail;
const ClassObject** contents;
- int i;
- contents = (const ClassObject**) exceptionArray->contents;
- for (i = 0; i < (int) exceptionArray->length; i++) {
+ contents = (const ClassObject**)(void*)exceptionArray->contents;
+ for (size_t i = 0; i < exceptionArray->length; i++) {
if (contents[i] != NULL)
dvmPointerSetAddEntry(*pThrows, contents[i]);
}
@@ -648,20 +655,19 @@
/* reduce list, nulling out redundant entries */
reduceExceptionClassList(exceptionArray);
- int mixLen = dvmPointerSetGetCount(throws);
+ size_t mixLen = dvmPointerSetGetCount(throws);
const ClassObject* mixSet[mixLen];
- int declLen = exceptionArray->length;
- const ClassObject** declSet = (const ClassObject**)exceptionArray->contents;
-
- int i, j;
+ size_t declLen = exceptionArray->length;
+ const ClassObject** declSet = (const ClassObject**)(void*)exceptionArray->contents;
/* grab a local copy to work on */
- for (i = 0; i < mixLen; i++) {
+ for (size_t i = 0; i < mixLen; i++) {
mixSet[i] = (ClassObject*)dvmPointerSetGetEntry(throws, i);
}
- for (i = 0; i < mixLen; i++) {
+ for (size_t i = 0; i < mixLen; i++) {
+ size_t j;
for (j = 0; j < declLen; j++) {
if (declSet[j] == NULL)
continue;
@@ -687,7 +693,7 @@
/* copy results back out; this eliminates duplicates as we go */
dvmPointerSetClear(throws);
- for (i = 0; i < mixLen; i++) {
+ for (size_t i = 0; i < mixLen; i++) {
if (mixSet[i] != NULL)
dvmPointerSetAddEntry(throws, mixSet[i]);
}
@@ -785,28 +791,23 @@
static ArrayObject* boxMethodArgs(const Method* method, const u4* args)
{
const char* desc = &method->shorty[1]; // [0] is the return type.
- ArrayObject* argArray = NULL;
- int argCount;
- Object** argObjects;
- bool failed = true;
/* count args */
- argCount = dexProtoGetParameterCount(&method->prototype);
+ size_t argCount = dexProtoGetParameterCount(&method->prototype);
/* allocate storage */
- argArray = dvmAllocArray(gDvm.classJavaLangObjectArray, argCount,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
+ ArrayObject* argArray = dvmAllocArrayByClass(gDvm.classJavaLangObjectArray,
+ argCount, ALLOC_DEFAULT);
if (argArray == NULL)
- goto bail;
- argObjects = (Object**) argArray->contents;
+ return NULL;
+ Object** argObjects = (Object**)(void*)argArray->contents;
/*
* Fill in the array.
*/
- int srcIndex = 0;
-
- argCount = 0;
+ size_t srcIndex = 0;
+ size_t dstIndex = 0;
while (*desc != '\0') {
char descChar = *(desc++);
JValue value;
@@ -819,35 +820,28 @@
case 'S':
case 'I':
value.i = args[srcIndex++];
- argObjects[argCount] = (Object*) dvmBoxPrimitive(value,
+ argObjects[dstIndex] = (Object*) dvmBoxPrimitive(value,
dvmFindPrimitiveClass(descChar));
/* argObjects is tracked, don't need to hold this too */
- dvmReleaseTrackedAlloc(argObjects[argCount], NULL);
- argCount++;
+ dvmReleaseTrackedAlloc(argObjects[dstIndex], NULL);
+ dstIndex++;
break;
case 'D':
case 'J':
value.j = dvmGetArgLong(args, srcIndex);
srcIndex += 2;
- argObjects[argCount] = (Object*) dvmBoxPrimitive(value,
+ argObjects[dstIndex] = (Object*) dvmBoxPrimitive(value,
dvmFindPrimitiveClass(descChar));
- dvmReleaseTrackedAlloc(argObjects[argCount], NULL);
- argCount++;
+ dvmReleaseTrackedAlloc(argObjects[dstIndex], NULL);
+ dstIndex++;
break;
case '[':
case 'L':
- argObjects[argCount++] = (Object*) args[srcIndex++];
+ argObjects[dstIndex++] = (Object*) args[srcIndex++];
break;
}
}
- failed = false;
-
-bail:
- if (failed) {
- dvmReleaseTrackedAlloc((Object*)argArray, NULL);
- argArray = NULL;
- }
return argArray;
}
@@ -1003,38 +997,28 @@
*/
static bool mustWrapException(const Method* method, const Object* throwable)
{
- const ArrayObject* throws;
- const ArrayObject* methodThrows;
- const Object** contents;
- const ClassObject** classes;
-
if (!dvmIsCheckedException(throwable))
return false;
const StaticField* sfield = &method->clazz->sfields[kThrowsField];
- throws = (ArrayObject*) dvmGetStaticFieldObject(sfield);
+ const ArrayObject* throws = (ArrayObject*) dvmGetStaticFieldObject(sfield);
int methodIndex = method - method->clazz->virtualMethods;
assert(methodIndex >= 0 && methodIndex < method->clazz->virtualMethodCount);
- contents = (const Object**) throws->contents;
- methodThrows = (ArrayObject*) contents[methodIndex];
+ const Object** contents = (const Object**)(void*)throws->contents;
+ const ArrayObject* methodThrows = (ArrayObject*) contents[methodIndex];
if (methodThrows == NULL) {
/* no throws declared, must wrap all checked exceptions */
- //printf("+++ methodThrows[%d] is null, wrapping all\n", methodIndex);
return true;
}
- int throwCount = methodThrows->length;
- classes = (const ClassObject**) methodThrows->contents;
- int i;
+ size_t throwCount = methodThrows->length;
+ const ClassObject** classes =
+ (const ClassObject**)(void*)methodThrows->contents;
- //printf("%s.%s list:\n", method->clazz->descriptor, method->name);
- //for (i = 0; i < throwCount; i++)
- // printf(" %d: %s\n", i, classes[i]->descriptor);
-
- for (i = 0; i < throwCount; i++) {
+ for (size_t i = 0; i < throwCount; i++) {
if (dvmInstanceof(throwable->clazz, classes[i])) {
/* this was declared, okay to throw */
return false;
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.cpp
similarity index 91%
rename from vm/reflect/Reflect.c
rename to vm/reflect/Reflect.cpp
index 7a21ef3..3fd46e6 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.cpp
@@ -125,17 +125,14 @@
static ArrayObject* convertSignatureToClassArray(char** pSignature,
ClassObject* defClass)
{
- ArrayObject* classArray;
char* signature = *pSignature;
- char* cp;
- int i, count;
assert(*signature == '(');
signature++;
/* count up the number of parameters */
- count = 0;
- cp = signature;
+ size_t count = 0;
+ char* cp = signature;
while (*cp != ')') {
count++;
@@ -152,17 +149,15 @@
LOGVV("REFLECT found %d parameters in '%s'\n", count, *pSignature);
/* create an array to hold them */
- classArray = dvmAllocArray(gDvm.classJavaLangClassArray, count,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
+ ArrayObject* classArray = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
+ count, ALLOC_DEFAULT);
if (classArray == NULL)
return NULL;
/* fill it in */
cp = signature;
- for (i = 0; i < count; i++) {
- ClassObject* clazz;
-
- clazz = convertSignaturePartToClass(&cp, defClass);
+ for (size_t i = 0; i < count; i++) {
+ ClassObject* clazz = convertSignaturePartToClass(&cp, defClass);
if (clazz == NULL) {
assert(dvmCheckException(dvmThreadSelf()));
return NULL;
@@ -208,10 +203,10 @@
if (slot < 0) {
slot = -(slot+1);
assert(slot < clazz->sfieldCount);
- return (Field*) &clazz->sfields[slot];
+ return (Field*)(void*)&clazz->sfields[slot];
} else {
assert(slot < clazz->ifieldCount);
- return (Field*) &clazz->ifields[slot];
+ return (Field*)(void*)&clazz->ifields[slot];
}
}
@@ -277,36 +272,34 @@
*/
ArrayObject* dvmGetDeclaredFields(ClassObject* clazz, bool publicOnly)
{
- ArrayObject* fieldArray = NULL;
- int i, count;
-
if (!dvmIsClassInitialized(gDvm.classJavaLangReflectField))
dvmInitClass(gDvm.classJavaLangReflectField);
/* count #of fields */
+ size_t count;
if (!publicOnly)
count = clazz->sfieldCount + clazz->ifieldCount;
else {
count = 0;
- for (i = 0; i < clazz->sfieldCount; i++) {
+ for (int i = 0; i < clazz->sfieldCount; i++) {
if ((clazz->sfields[i].field.accessFlags & ACC_PUBLIC) != 0)
count++;
}
- for (i = 0; i < clazz->ifieldCount; i++) {
+ for (int i = 0; i < clazz->ifieldCount; i++) {
if ((clazz->ifields[i].field.accessFlags & ACC_PUBLIC) != 0)
count++;
}
}
/* create the Field[] array */
- fieldArray = dvmAllocArray(gDvm.classJavaLangReflectFieldArray, count,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
+ ArrayObject* fieldArray =
+ dvmAllocArrayByClass(gDvm.classJavaLangReflectFieldArray, count, ALLOC_DEFAULT);
if (fieldArray == NULL)
return NULL;
/* populate */
size_t fieldCount = 0;
- for (i = 0; i < clazz->sfieldCount; i++) {
+ for (int i = 0; i < clazz->sfieldCount; i++) {
if (!publicOnly ||
(clazz->sfields[i].field.accessFlags & ACC_PUBLIC) != 0)
{
@@ -319,7 +312,7 @@
++fieldCount;
}
}
- for (i = 0; i < clazz->ifieldCount; i++) {
+ for (int i = 0; i < clazz->ifieldCount; i++) {
if (!publicOnly ||
(clazz->ifields[i].field.accessFlags & ACC_PUBLIC) != 0)
{
@@ -460,10 +453,6 @@
*/
ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly)
{
- ArrayObject* consArray;
- Method* meth;
- int i, count;
-
if (!dvmIsClassInitialized(gDvm.classJavaLangReflectConstructor))
dvmInitClass(gDvm.classJavaLangReflectConstructor);
@@ -477,9 +466,9 @@
/*
* Count up the #of relevant methods.
*/
- count = 0;
- meth = clazz->directMethods;
- for (i = 0; i < clazz->directMethodCount; i++, meth++) {
+ size_t count = 0;
+ for (int i = 0; i < clazz->directMethodCount; ++i) {
+ Method* meth = &clazz->directMethods[i];
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth))
{
@@ -490,37 +479,35 @@
/*
* Create an array of Constructor objects.
*/
- consArray = dvmAllocArray(gDvm.classJavaLangReflectConstructorArray, count,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
- if (consArray == NULL)
+ ClassObject* arrayClass = gDvm.classJavaLangReflectConstructorArray;
+ ArrayObject* ctorArray = dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT);
+ if (ctorArray == NULL)
return NULL;
/*
* Fill out the array.
*/
- meth = clazz->directMethods;
- size_t consObjCount = 0;
- for (i = 0; i < clazz->directMethodCount; i++, meth++) {
+ size_t ctorObjCount = 0;
+ for (int i = 0; i < clazz->directMethodCount; ++i) {
+ Method* meth = &clazz->directMethods[i];
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth))
{
- Object* consObj = createConstructorObject(meth);
- if (consObj == NULL)
- goto fail;
- dvmSetObjectArrayElement(consArray, consObjCount, consObj);
- ++consObjCount;
- dvmReleaseTrackedAlloc(consObj, NULL);
+ Object* ctorObj = createConstructorObject(meth);
+ if (ctorObj == NULL) {
+ dvmReleaseTrackedAlloc((Object*) ctorArray, NULL);
+ return NULL;
+ }
+ dvmSetObjectArrayElement(ctorArray, ctorObjCount, ctorObj);
+ ++ctorObjCount;
+ dvmReleaseTrackedAlloc(ctorObj, NULL);
}
}
- assert(consObjCount == consArray->length);
+ assert(ctorObjCount == ctorArray->length);
/* caller must call dvmReleaseTrackedAlloc */
- return consArray;
-
-fail:
- dvmReleaseTrackedAlloc((Object*) consArray, NULL);
- return NULL;
+ return ctorArray;
}
/*
@@ -624,10 +611,6 @@
*/
ArrayObject* dvmGetDeclaredMethods(ClassObject* clazz, bool publicOnly)
{
- ArrayObject* methodArray;
- Method* meth;
- int i, count;
-
if (!dvmIsClassInitialized(gDvm.classJavaLangReflectMethod))
dvmInitClass(gDvm.classJavaLangReflectMethod);
@@ -636,9 +619,9 @@
*
* Ignore virtual Miranda methods and direct class/object constructors.
*/
- count = 0;
- meth = clazz->virtualMethods;
- for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
+ size_t count = 0;
+ Method* meth = clazz->virtualMethods;
+ for (int i = 0; i < clazz->virtualMethodCount; i++, meth++) {
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
!dvmIsMirandaMethod(meth))
{
@@ -646,10 +629,8 @@
}
}
meth = clazz->directMethods;
- for (i = 0; i < clazz->directMethodCount; i++, meth++) {
- if ((!publicOnly || dvmIsPublicMethod(meth)) &&
- meth->name[0] != '<')
- {
+ for (int i = 0; i < clazz->directMethodCount; i++, meth++) {
+ if ((!publicOnly || dvmIsPublicMethod(meth)) && meth->name[0] != '<') {
count++;
}
}
@@ -657,18 +638,17 @@
/*
* Create an array of Method objects.
*/
- methodArray = dvmAllocArray(gDvm.classJavaLangReflectMethodArray, count,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
+ ArrayObject* methodArray =
+ dvmAllocArrayByClass(gDvm.classJavaLangReflectMethodArray, count, ALLOC_DEFAULT);
if (methodArray == NULL)
return NULL;
-
/*
* Fill out the array.
*/
meth = clazz->virtualMethods;
size_t methObjCount = 0;
- for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
+ for (int i = 0; i < clazz->virtualMethodCount; i++, meth++) {
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
!dvmIsMirandaMethod(meth))
{
@@ -681,7 +661,7 @@
}
}
meth = clazz->directMethods;
- for (i = 0; i < clazz->directMethodCount; i++, meth++) {
+ for (int i = 0; i < clazz->directMethodCount; i++, meth++) {
if ((!publicOnly || dvmIsPublicMethod(meth)) &&
meth->name[0] != '<')
{
@@ -712,24 +692,17 @@
static void createTargetDescriptor(ArrayObject* args,
DexStringCache* targetDescriptorCache)
{
- size_t i;
- ClassObject** argsArray = NULL;
- size_t length;
- char* at;
- const char* descriptor;
-
- argsArray = (ClassObject**) args->contents;
-
- length = 1; /* +1 for the terminating '\0' */
- for (i = 0; i < args->length; ++i) {
+ ClassObject** argsArray = (ClassObject**)(void*)args->contents;
+ size_t length = 1; /* +1 for the terminating '\0' */
+ for (size_t i = 0; i < args->length; ++i) {
length += strlen(argsArray[i]->descriptor);
}
dexStringCacheAlloc(targetDescriptorCache, length);
- at = (char*) targetDescriptorCache->value;
- for (i = 0; i < args->length; ++i) {
- descriptor = argsArray[i]->descriptor;
+ char* at = (char*) targetDescriptorCache->value;
+ for (size_t i = 0; i < args->length; ++i) {
+ const char* descriptor = argsArray[i]->descriptor;
strcpy(at, descriptor);
at += strlen(descriptor);
}
@@ -839,17 +812,15 @@
*/
ArrayObject* dvmGetInterfaces(ClassObject* clazz)
{
- ArrayObject* interfaceArray;
-
if (!dvmIsClassInitialized(gDvm.classJavaLangReflectMethod))
dvmInitClass(gDvm.classJavaLangReflectMethod);
/*
* Create an array of Class objects.
*/
- int count = clazz->interfaceCount;
- interfaceArray = dvmAllocArray(gDvm.classJavaLangClassArray, count,
- kObjectArrayRefWidth, ALLOC_DEFAULT);
+ size_t count = clazz->interfaceCount;
+ ArrayObject* interfaceArray =
+ dvmAllocArrayByClass(gDvm.classJavaLangClassArray, count, ALLOC_DEFAULT);
if (interfaceArray == NULL)
return NULL;
@@ -873,12 +844,11 @@
static PrimitiveType getBoxedType(DataObject* arg)
{
static const int kJavaLangLen = 11; // strlen("Ljava/lang/")
- const char* name;
if (arg == NULL)
return PRIM_NOT;
- name = arg->obj.clazz->descriptor;
+ const char* name = arg->clazz->descriptor;
if (strncmp(name, "Ljava/lang/", kJavaLangLen) != 0)
return PRIM_NOT;
@@ -1044,7 +1014,7 @@
srcType = getBoxedType(arg);
if (srcType == PRIM_NOT) { // didn't pass a boxed primitive in
LOGVV("conv arg: type '%s' not boxed primitive\n",
- arg->obj.clazz->descriptor);
+ arg->clazz->descriptor);
return -1;
}
@@ -1055,12 +1025,12 @@
valuePtr, destPtr);
} else {
/* verify object is compatible */
- if ((arg == NULL) || dvmInstanceof(arg->obj.clazz, type)) {
+ if ((arg == NULL) || dvmInstanceof(arg->clazz, type)) {
*destPtr = (s4) arg;
retVal = 1;
} else {
LOGVV("Arg %p (%s) not compatible with %s\n",
- arg, arg->obj.clazz->descriptor, type->descriptor);
+ arg, arg->clazz->descriptor, type->descriptor);
retVal = -1;
}
}
diff --git a/vm/reflect/Reflect.h b/vm/reflect/Reflect.h
index 80e96fa..63260b5 100644
--- a/vm/reflect/Reflect.h
+++ b/vm/reflect/Reflect.h
@@ -212,23 +212,23 @@
* Used to pass values out of annotation (and encoded array) processing
* functions.
*/
-typedef struct AnnotationValue {
+struct AnnotationValue {
JValue value;
u1 type;
-} AnnotationValue;
+};
/**
* Iterator structure for iterating over DexEncodedArray instances. The
* structure should be treated as opaque.
*/
-typedef struct {
+struct EncodedArrayIterator {
const u1* cursor; /* current cursor */
u4 elementsLeft; /* number of elements left to read */
const DexEncodedArray* encodedArray; /* instance being iterated over */
u4 size; /* number of elements in instance */
const ClassObject* clazz; /* class to resolve with respect to */
-} EncodedArrayIterator;
+};
/**
* Initializes an encoded array iterator.
diff --git a/vm/test/AtomicTest.c b/vm/test/AtomicTest.cpp
similarity index 91%
rename from vm/test/AtomicTest.c
rename to vm/test/AtomicTest.cpp
index 52f29cc..26ac2bc 100644
--- a/vm/test/AtomicTest.c
+++ b/vm/test/AtomicTest.cpp
@@ -66,7 +66,7 @@
/*
* Get a relative time value.
*/
-static int64_t getRelativeTimeNsec(void)
+static int64_t getRelativeTimeNsec()
{
#define HAVE_POSIX_CLOCKS
#ifdef HAVE_POSIX_CLOCKS
@@ -87,17 +87,17 @@
* If these get inlined the compiler may figure out what we're up to and
* completely elide the operations.
*/
-static void incr(void) __attribute__((noinline));
-static void decr(void) __attribute__((noinline));
+static void incr() __attribute__((noinline));
+static void decr() __attribute__((noinline));
static void add(int addVal) __attribute__((noinline));
static int compareAndSwap(int oldVal, int newVal, int* addr) __attribute__((noinline));
static int compareAndSwapWide(int64_t oldVal, int64_t newVal, int64_t* addr) __attribute__((noinline));
-static void incr(void)
+static void incr()
{
incTest++;
}
-static void decr(void)
+static void decr()
{
decTest--;
}
@@ -207,16 +207,16 @@
for (i = repeatCount / 10; i != 0; i--) {
if (USE_ATOMIC) {
// succeed 10x
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
- (void) android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
+ android_atomic_release_cas(7, 7, valuePtr);
} else {
// succeed 10x
compareAndSwap(7, 7, valuePtr);
@@ -239,7 +239,7 @@
return end - start;
}
-static void testAtomicSpeed(void)
+static void testAtomicSpeed()
{
static const int kIterations = 10;
static const int kRepeatCount = 5 * 1000 * 1000;
@@ -264,7 +264,7 @@
/*
* Start tests, show results.
*/
-bool dvmTestAtomicSpeed(void)
+bool dvmTestAtomicSpeed()
{
pthread_t threads[THREAD_COUNT];
void *(*startRoutine)(void*) = atomicTest;
diff --git a/vm/test/TestHash.c b/vm/test/TestHash.cpp
similarity index 93%
rename from vm/test/TestHash.c
rename to vm/test/TestHash.cpp
index 431e62a..9eabbb6 100644
--- a/vm/test/TestHash.c
+++ b/vm/test/TestHash.cpp
@@ -75,7 +75,7 @@
/*
* Some quick hash table tests.
*/
-bool dvmTestHash(void)
+bool dvmTestHash()
{
HashTable* pTab;
char tmpStr[64];
@@ -141,7 +141,7 @@
hash = 0;
/* two entries, same hash, different values */
- char* str1;
+ const char* str1;
str1 = (char*) dvmHashTableLookup(pTab, hash, strdup("one"),
(HashCompareFunc) strcmp, true);
assert(str1 != NULL);
@@ -149,10 +149,10 @@
(HashCompareFunc) strcmp, true);
/* remove the first one */
- if (!dvmHashTableRemove(pTab, hash, str1))
+ if (!dvmHashTableRemove(pTab, hash, (void*)str1))
LOGE("TestHash failed to delete item\n");
else
- free(str1); // "Remove" doesn't call the free func
+ free((void*)str1); // "Remove" doesn't call the free func
/* make sure iterator doesn't included deleted entries */
int count = 0;
@@ -167,11 +167,11 @@
}
/* see if we can find them */
- str = (const char*) dvmHashTableLookup(pTab, hash, "one",
+ str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"one",
(HashCompareFunc) strcmp,false);
if (str != NULL)
LOGE("TestHash deleted entry has returned!");
- str = (const char*) dvmHashTableLookup(pTab, hash, "two",
+ str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"two",
(HashCompareFunc) strcmp,false);
if (str == NULL)
LOGE("TestHash entry vanished\n");
diff --git a/vm/test/TestIndirectRefTable.c b/vm/test/TestIndirectRefTable.cpp
similarity index 98%
rename from vm/test/TestIndirectRefTable.c
rename to vm/test/TestIndirectRefTable.cpp
index 155ba32..a72e2b0 100644
--- a/vm/test/TestIndirectRefTable.c
+++ b/vm/test/TestIndirectRefTable.cpp
@@ -28,7 +28,7 @@
/*
* Basic add/get/delete tests in an unsegmented table.
*/
-static bool basicTest(void)
+static bool basicTest()
{
static const int kTableMax = 20;
IndirectRefTable irt;
@@ -313,7 +313,7 @@
/*
* Test operations on a segmented table.
*/
-static bool segmentTest(void)
+static bool segmentTest()
{
static const int kTableMax = 20;
IndirectRefTable irt;
@@ -471,7 +471,7 @@
/*
* Some quick tests.
*/
-bool dvmTestIndirectRefTable(void)
+bool dvmTestIndirectRefTable()
{
if (!basicTest()) {
LOGE("IRT basic test failed\n");