Merge "Compute a length based on heap size instead of card table size." into dalvik-dev
diff --git a/dx/src/com/android/dx/command/dexer/Main.java b/dx/src/com/android/dx/command/dexer/Main.java
index b121668..6e8fa7e 100644
--- a/dx/src/com/android/dx/command/dexer/Main.java
+++ b/dx/src/com/android/dx/command/dexer/Main.java
@@ -59,6 +59,7 @@
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
@@ -208,13 +209,18 @@
return 0; // this was a no-op incremental build
}
- byte[] outArray = writeDex();
+ // this array is null if no classes were defined
+ byte[] outArray = null;
- if (outArray == null) {
- return 2;
+ if (!outputDex.isEmpty()) {
+ outArray = writeDex();
+
+ if (outArray == null) {
+ return 2;
+ }
}
- if (args.incremental && incrementalOutFile.exists()) {
+ if (args.incremental) {
outArray = merge(outArray, incrementalOutFile);
}
@@ -225,7 +231,7 @@
if (!createJar(args.outName, outArray)) {
return 3;
}
- } else if (args.outName != null) {
+ } else if (outArray != null && args.outName != null) {
OutputStream out = openOutput(args.outName);
out.write(outArray);
closeOutput(out);
@@ -236,27 +242,50 @@
/**
* Merges the dex files {@code update} and {@code base}, preferring
- * {@code update}'s definition for types defined in both dex files. Returns
- * the bytes of the merged dex file.
+ * {@code update}'s definition for types defined in both dex files.
+ *
+ * @return the bytes of the merged dex file, or null if both the update
+ * and the base dex do not exist.
*/
private static byte[] merge(byte[] update, File base) throws IOException {
- DexBuffer dexA = new DexBuffer();
- dexA.loadFrom(new ByteArrayInputStream(update));
+ DexBuffer dexA = null;
+ DexBuffer dexB = null;
- DexBuffer dexB = new DexBuffer();
- if (args.jarOutput) {
- ZipFile zipFile = new ZipFile(base);
- dexB.loadFrom(zipFile.getInputStream(zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME)));
- zipFile.close();
- } else {
- InputStream in = new FileInputStream(base);
- dexB.loadFrom(in);
- in.close();
+ if (update != null) {
+ dexA = new DexBuffer();
+ dexA.loadFrom(new ByteArrayInputStream(update));
}
- DexBuffer merged = new DexMerger(dexA, dexB).merge();
+ if (base.exists()) {
+ if (args.jarOutput) {
+ ZipFile zipFile = new ZipFile(base);
+ ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME);
+ if (entry != null) {
+ dexB = new DexBuffer();
+ dexB.loadFrom(zipFile.getInputStream(entry));
+ zipFile.close();
+ }
+ } else {
+ InputStream in = new FileInputStream(base);
+ dexB = new DexBuffer();
+ dexB.loadFrom(in);
+ in.close();
+ }
+ }
+
+ DexBuffer result;
+ if (dexA == null && dexB == null) {
+ return null;
+ } else if (dexA == null) {
+ result = dexB;
+ } else if (dexB == null) {
+ result = dexA;
+ } else {
+ result = new DexMerger(dexA, dexB).merge();
+ }
+
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- merged.writeTo(bytesOut);
+ result.writeTo(bytesOut);
return bytesOut.toByteArray();
}
@@ -555,8 +584,8 @@
* Creates a jar file from the resources and given dex file array.
*
* @param fileName {@code non-null;} name of the file
- * @param dexArray {@code non-null;} array containing the dex file
- * to include
+ * @param dexArray array containing the dex file to include, or null if the
+ * output contains no class defs.
* @return whether the creation was successful
*/
private static boolean createJar(String fileName, byte[] dexArray) {
@@ -571,7 +600,9 @@
OutputStream out = openOutput(fileName);
JarOutputStream jarOut = new JarOutputStream(out, manifest);
- outputResources.put(DexFormat.DEX_IN_JAR_NAME, dexArray);
+ if (dexArray != null) {
+ outputResources.put(DexFormat.DEX_IN_JAR_NAME, dexArray);
+ }
try {
for (Map.Entry<String, byte[]> e :
diff --git a/dx/src/com/android/dx/command/grep/Grep.java b/dx/src/com/android/dx/command/grep/Grep.java
new file mode 100644
index 0000000..025aa65
--- /dev/null
+++ b/dx/src/com/android/dx/command/grep/Grep.java
@@ -0,0 +1,125 @@
+/*
+ * 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.command.grep;
+
+import com.android.dx.io.ClassData;
+import com.android.dx.io.ClassDef;
+import com.android.dx.io.CodeReader;
+import com.android.dx.io.DexBuffer;
+import com.android.dx.io.EncodedValueReader;
+import com.android.dx.io.MethodId;
+import com.android.dx.io.instructions.DecodedInstruction;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public final class Grep {
+ private final DexBuffer dex;
+ private final CodeReader codeReader = new CodeReader();
+ private final Set<Integer> stringIds;
+
+ private final PrintStream out;
+ private int count = 0;
+
+ private ClassDef currentClass;
+ private ClassData.Method currentMethod;
+
+ public Grep(final DexBuffer dex, Pattern pattern, final PrintStream out) {
+ this.dex = dex;
+ this.out = out;
+
+ stringIds = getStringIds(dex, pattern);
+
+ codeReader.setStringVisitor(new CodeReader.Visitor() {
+ public void visit(DecodedInstruction[] all, DecodedInstruction one) {
+ encounterString(one.getIndex());
+ }
+ });
+ }
+
+ private EncodedValueReader newEncodedValueReader(DexBuffer.Section section) {
+ return new EncodedValueReader(section) {
+ @Override protected void visitString(int type, int index) {
+ encounterString(index);
+ }
+ };
+ }
+
+ private void encounterString(int index) {
+ if (stringIds.contains(index)) {
+ out.println(location() + " " + dex.strings().get(index));
+ count++;
+ }
+ }
+
+ private String location() {
+ String className = dex.typeNames().get(currentClass.getTypeIndex());
+ if (currentMethod != null) {
+ MethodId methodId = dex.methodIds().get(currentMethod.getMethodIndex());
+ return className + "." + dex.strings().get(methodId.getNameIndex());
+ } else {
+ return className;
+ }
+ }
+
+ /**
+ * Prints usages to out. Returns the number of matches found.
+ */
+ public int grep() {
+ for (ClassDef classDef : dex.classDefs()) {
+ currentClass = classDef;
+ currentMethod = null;
+
+ if (classDef.getClassDataOffset() == 0) {
+ continue;
+ }
+
+ ClassData classData = dex.readClassData(classDef);
+
+ // find the strings in encoded constants
+ int staticValuesOffset = classDef.getStaticValuesOffset();
+ if (staticValuesOffset != 0) {
+ newEncodedValueReader(dex.open(staticValuesOffset)).readArray();
+ }
+
+ // find the strings in method bodies
+ for (ClassData.Method method : classData.allMethods()) {
+ currentMethod = method;
+ if (method.getCodeOffset() != 0) {
+ codeReader.visitAll(dex.readCode(method).getInstructions());
+ }
+ }
+ }
+
+ currentClass = null;
+ currentMethod = null;
+ return count;
+ }
+
+ private Set<Integer> getStringIds(DexBuffer dex, Pattern pattern) {
+ Set<Integer> stringIds = new HashSet<Integer>();
+ int stringIndex = 0;
+ for (String s : dex.strings()) {
+ if (pattern.matcher(s).find()) {
+ stringIds.add(stringIndex);
+ }
+ stringIndex++;
+ }
+ return stringIds;
+ }
+}
diff --git a/dx/src/com/android/dx/command/grep/Main.java b/dx/src/com/android/dx/command/grep/Main.java
new file mode 100644
index 0000000..e765a31
--- /dev/null
+++ b/dx/src/com/android/dx/command/grep/Main.java
@@ -0,0 +1,46 @@
+/*
+ * 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.command.grep;
+
+import com.android.dx.dex.DexFormat;
+import com.android.dx.io.DexBuffer;
+import com.android.dx.util.FileUtils;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
+import java.util.zip.ZipFile;
+
+public final class Main {
+ public static void main(String[] args) throws IOException {
+ String dexFile = args[0];
+ String pattern = args[1];
+
+ DexBuffer dex = new DexBuffer();
+ if (FileUtils.hasArchiveSuffix(dexFile)) {
+ ZipFile zip = new ZipFile(dexFile);
+ InputStream in = zip.getInputStream(zip.getEntry(DexFormat.DEX_IN_JAR_NAME));
+ dex.loadFrom(in);
+ zip.close();
+ } else {
+ dex.loadFrom(new File(dexFile));
+ }
+
+ int count = new Grep(dex, Pattern.compile(pattern), System.out).grep();
+ System.exit((count > 0) ? 0 : 1);
+ }
+}
diff --git a/dx/src/com/android/dx/dex/file/DexFile.java b/dx/src/com/android/dx/dex/file/DexFile.java
index 1cc9358..73f0864 100644
--- a/dx/src/com/android/dx/dex/file/DexFile.java
+++ b/dx/src/com/android/dx/dex/file/DexFile.java
@@ -134,6 +134,13 @@
}
/**
+ * Returns true if this dex doesn't contain any class defs.
+ */
+ public boolean isEmpty() {
+ return classDefs.items().isEmpty();
+ }
+
+ /**
* Adds a class to this instance. It is illegal to attempt to add more
* than one class with the same name.
*
diff --git a/dx/src/com/android/dx/io/EncodedValueReader.java b/dx/src/com/android/dx/io/EncodedValueReader.java
new file mode 100644
index 0000000..6c913a1
--- /dev/null
+++ b/dx/src/com/android/dx/io/EncodedValueReader.java
@@ -0,0 +1,139 @@
+/*
+ * 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.io;
+
+/**
+ * SAX-style reader for encoded values.
+ * TODO: convert this to a pull-style reader
+ */
+public class EncodedValueReader {
+ public static final int ENCODED_BYTE = 0x00;
+ public static final int ENCODED_SHORT = 0x02;
+ public static final int ENCODED_CHAR = 0x03;
+ public static final int ENCODED_INT = 0x04;
+ public static final int ENCODED_LONG = 0x06;
+ public static final int ENCODED_FLOAT = 0x10;
+ public static final int ENCODED_DOUBLE = 0x11;
+ public static final int ENCODED_STRING = 0x17;
+ public static final int ENCODED_TYPE = 0x18;
+ public static final int ENCODED_FIELD = 0x19;
+ public static final int ENCODED_ENUM = 0x1b;
+ public static final int ENCODED_METHOD = 0x1a;
+ public static final int ENCODED_ARRAY = 0x1c;
+ public static final int ENCODED_ANNOTATION = 0x1d;
+ public static final int ENCODED_NULL = 0x1e;
+ public static final int ENCODED_BOOLEAN = 0x1f;
+
+ protected final DexBuffer.Section in;
+
+ public EncodedValueReader(DexBuffer.Section in) {
+ this.in = in;
+ }
+
+ public final void readArray() {
+ int size = in.readUleb128();
+ visitArray(size);
+
+ for (int i = 0; i < size; i++) {
+ readValue();
+ }
+ }
+
+ public final void readAnnotation() {
+ int typeIndex = in.readUleb128();
+ int size = in.readUleb128();
+ visitAnnotation(typeIndex, size);
+
+ for (int i = 0; i < size; i++) {
+ visitAnnotationName(in.readUleb128());
+ readValue();
+ }
+ }
+
+ public final void readValue() {
+ int argAndType = in.readByte() & 0xff;
+ int type = argAndType & 0x1f;
+ int arg = (argAndType & 0xe0) >> 5;
+ int size = arg + 1;
+
+ switch (type) {
+ case ENCODED_BYTE:
+ case ENCODED_SHORT:
+ case ENCODED_CHAR:
+ case ENCODED_INT:
+ case ENCODED_LONG:
+ case ENCODED_FLOAT:
+ case ENCODED_DOUBLE:
+ visitPrimitive(argAndType, type, arg, size);
+ break;
+ case ENCODED_STRING:
+ visitString(type, readIndex(in, size));
+ break;
+ case ENCODED_TYPE:
+ visitType(type, readIndex(in, size));
+ break;
+ case ENCODED_FIELD:
+ case ENCODED_ENUM:
+ visitField(type, readIndex(in, size));
+ break;
+ case ENCODED_METHOD:
+ visitMethod(type, readIndex(in, size));
+ break;
+ case ENCODED_ARRAY:
+ visitArrayValue(argAndType);
+ readArray();
+ break;
+ case ENCODED_ANNOTATION:
+ visitAnnotationValue(argAndType);
+ readAnnotation();
+ break;
+ case ENCODED_NULL:
+ visitEncodedNull(argAndType);
+ break;
+ case ENCODED_BOOLEAN:
+ visitEncodedBoolean(argAndType);
+ break;
+ }
+ }
+
+ protected void visitArray(int size) {}
+ protected void visitAnnotation(int typeIndex, int size) {}
+ protected void visitAnnotationName(int nameIndex) {}
+ protected void visitPrimitive(int argAndType, int type, int arg, int size) {
+ for (int i = 0; i < size; i++) {
+ in.readByte();
+ }
+ }
+ protected void visitString(int type, int index) {}
+ protected void visitType(int type, int index) {}
+ protected void visitField(int type, int index) {}
+ protected void visitMethod(int type, int index) {}
+ protected void visitArrayValue(int argAndType) {}
+ protected void visitAnnotationValue(int argAndType) {}
+ protected void visitEncodedBoolean(int argAndType) {}
+ protected void visitEncodedNull(int argAndType) {}
+
+ private int readIndex(DexBuffer.Section in, int byteCount) {
+ int result = 0;
+ int shift = 0;
+ for (int i = 0; i < byteCount; i++) {
+ result += (in.readByte() & 0xff) << shift;
+ shift += 8;
+ }
+ return result;
+ }
+}
diff --git a/dx/src/com/android/dx/merge/DexMerger.java b/dx/src/com/android/dx/merge/DexMerger.java
index 0c24a85..1fe0ff5 100644
--- a/dx/src/com/android/dx/merge/DexMerger.java
+++ b/dx/src/com/android/dx/merge/DexMerger.java
@@ -636,7 +636,7 @@
// elements
for (int i = 0; i < size; i++) {
annotationOut.writeUleb128(indexMap.adjustString(in.readUleb128())); // name
- new EncodedValueTransformer(indexMap, in, annotationOut).transformValue(); // value
+ new EncodedValueTransformer(in, indexMap, annotationOut).readValue(); // value
}
}
@@ -751,7 +751,7 @@
private void transformStaticValues(DexBuffer.Section in, IndexMap indexMap) {
contentsOut.encodedArrays.size++;
- new EncodedValueTransformer(indexMap, in, encodedArrayOut).transformArray();
+ new EncodedValueTransformer(in, indexMap, encodedArrayOut).readArray();
}
/**
diff --git a/dx/src/com/android/dx/merge/EncodedValueTransformer.java b/dx/src/com/android/dx/merge/EncodedValueTransformer.java
index bcf0d72..0959f15 100644
--- a/dx/src/com/android/dx/merge/EncodedValueTransformer.java
+++ b/dx/src/com/android/dx/merge/EncodedValueTransformer.java
@@ -17,121 +17,67 @@
package com.android.dx.merge;
import com.android.dx.io.DexBuffer;
+import com.android.dx.io.EncodedValueReader;
import com.android.dx.util.Unsigned;
-final class EncodedValueTransformer {
- private static final int ENCODED_BYTE = 0x00;
- private static final int ENCODED_SHORT = 0x02;
- private static final int ENCODED_CHAR = 0x03;
- private static final int ENCODED_INT = 0x04;
- private static final int ENCODED_LONG = 0x06;
- private static final int ENCODED_FLOAT = 0x10;
- private static final int ENCODED_DOUBLE = 0x11;
- private static final int ENCODED_STRING = 0x17;
- private static final int ENCODED_TYPE = 0x18;
- private static final int ENCODED_FIELD = 0x19;
- private static final int ENCODED_ENUM = 0x1b;
- private static final int ENCODED_METHOD = 0x1a;
- private static final int ENCODED_ARRAY = 0x1c;
- private static final int ENCODED_ANNOTATION = 0x1d;
- private static final int ENCODED_NULL = 0x1e;
- private static final int ENCODED_BOOLEAN = 0x1f;
-
+public final class EncodedValueTransformer extends EncodedValueReader {
private final IndexMap indexMap;
- private final DexBuffer.Section in;
private final DexBuffer.Section out;
- public EncodedValueTransformer(IndexMap indexMap, DexBuffer.Section in, DexBuffer.Section out) {
+ public EncodedValueTransformer(DexBuffer.Section in, IndexMap indexMap, DexBuffer.Section out) {
+ super(in);
this.indexMap = indexMap;
- this.in = in;
this.out = out;
}
- public void transformArray() {
- int size = in.readUleb128(); // size
+ protected void visitArray(int size) {
out.writeUleb128(size);
- for (int i = 0; i < size; i++) {
- transformValue();
- }
}
- public void transformAnnotation() {
- out.writeUleb128(indexMap.adjustType(in.readUleb128())); // type idx
-
- int size = in.readUleb128(); // size
+ protected void visitAnnotation(int typeIndex, int size) {
+ out.writeUleb128(indexMap.adjustType(typeIndex));
out.writeUleb128(size);
-
- for (int i = 0; i < size; i++) {
- out.writeUleb128(indexMap.adjustString(in.readUleb128())); // name idx
- transformValue();
- }
}
- public void transformValue() {
- int argAndType = in.readByte() & 0xff;
- int type = argAndType & 0x1f;
- int arg = (argAndType & 0xe0) >> 5;
- int size = arg + 1;
-
- switch (type) {
- case ENCODED_BYTE:
- case ENCODED_SHORT:
- case ENCODED_CHAR:
- case ENCODED_INT:
- case ENCODED_LONG:
- case ENCODED_FLOAT:
- case ENCODED_DOUBLE:
- out.writeByte(argAndType);
- copyBytes(in, out, size);
- break;
-
- case ENCODED_STRING:
- int indexIn = readIndex(in, size);
- int indexOut = indexMap.adjustString(indexIn);
- writeTypeAndSizeAndIndex(type, indexOut, out);
- break;
- case ENCODED_TYPE:
- indexIn = readIndex(in, size);
- indexOut = indexMap.adjustType(indexIn);
- writeTypeAndSizeAndIndex(type, indexOut, out);
- break;
- case ENCODED_FIELD:
- case ENCODED_ENUM:
- indexIn = readIndex(in, size);
- indexOut = indexMap.adjustField(indexIn);
- writeTypeAndSizeAndIndex(type, indexOut, out);
- break;
- case ENCODED_METHOD:
- indexIn = readIndex(in, size);
- indexOut = indexMap.adjustMethod(indexIn);
- writeTypeAndSizeAndIndex(type, indexOut, out);
- break;
-
- case ENCODED_ARRAY:
- out.writeByte(argAndType);
- transformArray();
- break;
-
- case ENCODED_ANNOTATION:
- out.writeByte(argAndType);
- transformAnnotation();
- break;
-
- case ENCODED_NULL:
- case ENCODED_BOOLEAN:
- out.writeByte(argAndType);
- break;
- }
+ protected void visitAnnotationName(int index) {
+ out.writeUleb128(indexMap.adjustString(index));
}
- private int readIndex(DexBuffer.Section in, int byteCount) {
- int result = 0;
- int shift = 0;
- for (int i = 0; i < byteCount; i++) {
- result += (in.readByte() & 0xff) << shift;
- shift += 8;
- }
- return result;
+ protected void visitPrimitive(int argAndType, int type, int arg, int size) {
+ out.writeByte(argAndType);
+ copyBytes(in, out, size);
+ }
+
+ protected void visitString(int type, int index) {
+ writeTypeAndSizeAndIndex(type, indexMap.adjustString(index), out);
+ }
+
+ protected void visitType(int type, int index) {
+ writeTypeAndSizeAndIndex(type, indexMap.adjustType(index), out);
+ }
+
+ protected void visitField(int type, int index) {
+ writeTypeAndSizeAndIndex(type, indexMap.adjustField(index), out);
+ }
+
+ protected void visitMethod(int type, int index) {
+ writeTypeAndSizeAndIndex(type, indexMap.adjustMethod(index), out);
+ }
+
+ protected void visitArrayValue(int argAndType) {
+ out.writeByte(argAndType);
+ }
+
+ protected void visitAnnotationValue(int argAndType) {
+ out.writeByte(argAndType);
+ }
+
+ protected void visitEncodedBoolean(int argAndType) {
+ out.writeByte(argAndType);
+ }
+
+ protected void visitEncodedNull(int argAndType) {
+ out.writeByte(argAndType);
}
private void writeTypeAndSizeAndIndex(int type, int index, DexBuffer.Section out) {
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 06dc864..fd865e2 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -464,10 +464,7 @@
/* pad for 64-bit alignment if necessary */
} DexOptHeader;
-#define DEX_FLAG_VERIFIED (1) /* tried to verify all classes */
#define DEX_OPT_FLAG_BIG (1<<1) /* swapped to big-endian */
-#define DEX_OPT_FLAG_FIELDS (1<<2) /* field access optimized */
-#define DEX_OPT_FLAG_INVOCATIONS (1<<3) /* method calls optimized */
#define DEX_INTERFACE_CACHE_SIZE 128 /* must be power of 2 */
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 8c10234..cf1332c 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -98,6 +98,7 @@
Hash.c \
IndirectRefTable.c.arm \
Init.c \
+ InitRefs.c \
InlineNative.c.arm \
Inlines.c \
Intern.c \
diff --git a/vm/DvmDex.c b/vm/DvmDex.c
index 500bf42..c5790e5 100644
--- a/vm/DvmDex.c
+++ b/vm/DvmDex.c
@@ -137,6 +137,7 @@
/* tuck this into the DexFile so it gets released later */
sysCopyMap(&pDvmDex->memMap, &memMap);
+ pDvmDex->isMappedReadOnly = true;
*ppDvmDex = pDvmDex;
result = 0;
@@ -175,6 +176,7 @@
goto bail;
}
+ pDvmDex->isMappedReadOnly = false;
*ppDvmDex = pDvmDex;
result = 0;
diff --git a/vm/DvmDex.h b/vm/DvmDex.h
index f36940b..ad82e54 100644
--- a/vm/DvmDex.h
+++ b/vm/DvmDex.h
@@ -58,6 +58,7 @@
struct AtomicCache* pInterfaceCache;
/* shared memory region with file contents */
+ bool isMappedReadOnly;
MemMapping memMap;
/* lock ensuring mutual exclusion during updates */
diff --git a/vm/Exception.c b/vm/Exception.c
index 02e0e2a..aaf97a4 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -99,93 +99,16 @@
static bool initException(Object* exception, const char* msg, Object* cause,
Thread* self);
-/*
- * Format the message into a small buffer and pass it along.
- */
-void dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt,
- va_list args)
-{
- char msgBuf[512];
-
- vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
- dvmThrowChainedException(exceptionDescriptor, msgBuf, NULL);
-}
-
-void dvmThrowExceptionFmtByClassV(ClassObject* exceptionClass,
+void dvmThrowExceptionFmtV(ClassObject* exceptionClass,
const char* fmt, va_list args)
{
char msgBuf[512];
vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
- dvmThrowChainedExceptionByClass(exceptionClass, msgBuf, NULL);
+ dvmThrowChainedException(exceptionClass, msgBuf, NULL);
}
-/*
- * Create a Throwable and throw an exception in the current thread (where
- * "throwing" just means "set the thread's exception pointer").
- *
- * "msg" and/or "cause" may be NULL.
- *
- * If we have a bad exception hierarchy -- something in Throwable.<init>
- * is missing -- then every attempt to throw an exception will result
- * in another exception. Exceptions are generally allowed to "chain"
- * to other exceptions, so it's hard to auto-detect this problem. It can
- * only happen if the system classes are broken, so it's probably not
- * worth spending cycles to detect it.
- *
- * We do have one case to worry about: if the classpath is completely
- * wrong, we'll go into a death spin during startup because we can't find
- * the initial class and then we can't find NoClassDefFoundError. We have
- * to handle this case.
- *
- * [Do we want to cache pointers to common exception classes?]
- */
-void dvmThrowChainedException(const char* exceptionDescriptor, const char* msg,
- Object* cause)
-{
- ClassObject* excepClass;
-
- LOGV("THROW '%s' msg='%s' cause=%s\n",
- exceptionDescriptor, msg,
- (cause != NULL) ? cause->clazz->descriptor : "(none)");
-
- if (gDvm.initializing) {
- if (++gDvm.initExceptionCount >= 2) {
- LOGE("Too many exceptions during init (failed on '%s' '%s')\n",
- exceptionDescriptor, msg);
- dvmAbort();
- }
- }
-
- excepClass = dvmFindSystemClass(exceptionDescriptor);
- if (excepClass == NULL) {
- /*
- * We couldn't find the exception class. The attempt to find a
- * nonexistent class should have raised an exception. If no
- * exception is currently raised, then we're pretty clearly unable
- * to throw ANY sort of exception, and we need to pack it in.
- *
- * If we were able to throw the "class load failed" exception,
- * stick with that. Ideally we'd stuff the original exception
- * into the "cause" field, but since we can't find it we can't
- * do that. The exception class name should be in the "message"
- * field.
- */
- if (!dvmCheckException(dvmThreadSelf())) {
- LOGE("FATAL: unable to throw exception (failed on '%s' '%s')\n",
- exceptionDescriptor, msg);
- dvmAbort();
- }
- return;
- }
-
- dvmThrowChainedExceptionByClass(excepClass, msg, cause);
-}
-
-/*
- * Start/continue throwing process now that we have a class reference.
- */
-void dvmThrowChainedExceptionByClass(ClassObject* excepClass, const char* msg,
+void dvmThrowChainedException(ClassObject* excepClass, const char* msg,
Object* cause)
{
Thread* self = dvmThreadSelf();
@@ -207,7 +130,7 @@
excepClass->descriptor);
if (strcmp(excepClass->descriptor, "Ljava/lang/InternalError;") == 0)
dvmAbort();
- dvmThrowChainedExceptionByClass(gDvm.exInternalError,
+ dvmThrowChainedException(gDvm.exInternalError,
"failed to init original exception class", cause);
return;
}
@@ -261,29 +184,13 @@
dvmReleaseTrackedAlloc(exception, self);
}
-/*
- * Throw the named exception using the human-readable form of the class
- * descriptor as the exception message, and with the specified cause.
- */
-void dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
- const char* messageDescriptor, Object* cause)
-{
- char* message = dvmHumanReadableDescriptor(messageDescriptor);
-
- dvmThrowChainedException(exceptionDescriptor, message, cause);
- free(message);
-}
-
-/*
- * Like dvmThrowException, but take a class object instead of a name
- * and turn the given message into the human-readable form for a descriptor.
- */
-void dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
- const char* messageDescriptor)
+void dvmThrowChainedExceptionWithClassMessage(
+ ClassObject* exceptionClass, const char* messageDescriptor,
+ Object* cause)
{
char* message = dvmDescriptorToName(messageDescriptor);
- dvmThrowExceptionByClass(exceptionClass, message);
+ dvmThrowChainedException(exceptionClass, message, cause);
free(message);
}
@@ -464,7 +371,7 @@
excepClass->descriptor, msg, initKind);
assert(strcmp(excepClass->descriptor,
"Ljava/lang/RuntimeException;") != 0);
- dvmThrowChainedExceptionByClass(gDvm.exRuntimeException,
+ dvmThrowChainedException(gDvm.exRuntimeException,
"re-throw on exception class missing constructor", NULL);
goto bail;
}
@@ -544,19 +451,15 @@
/*
- * Clear the pending exception and the "initExceptionCount" counter. This
- * is used by the optimization and verification code, which has to run with
- * "initializing" set to avoid going into a death-spin if the "class not
- * found" exception can't be found.
+ * Clear the pending exception. This is used by the optimization and
+ * verification code, which mostly happens during runs of dexopt.
*
* This can also be called when the VM is in a "normal" state, e.g. when
- * verifying classes that couldn't be verified at optimization time. The
- * reset of initExceptionCount should be harmless in that case.
+ * verifying classes that couldn't be verified at optimization time.
*/
void dvmClearOptException(Thread* self)
{
self->exception = NULL;
- gDvm.initExceptionCount = 0;
}
/*
@@ -1300,16 +1203,16 @@
}
void dvmThrowAbstractMethodError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exAbstractMethodError, msg);
+ dvmThrowException(gDvm.exAbstractMethodError, msg);
}
void dvmThrowArithmeticException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exArithmeticException, msg);
+ dvmThrowException(gDvm.exArithmeticException, msg);
}
-void dvmThrowArrayIndexOutOfBoundsException(int index, int length)
+void dvmThrowArrayIndexOutOfBoundsException(int length, int index)
{
- dvmThrowExceptionFmtByClass(gDvm.exArrayIndexOutOfBoundsException,
+ dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
"length=%d; index=%d", length, index);
}
@@ -1323,7 +1226,7 @@
{
char* actualClassName = dvmHumanReadableDescriptor(actual->descriptor);
char* desiredClassName = dvmHumanReadableDescriptor(desired->descriptor);
- dvmThrowExceptionFmtByClass(exceptionClass, fmt,
+ dvmThrowExceptionFmt(exceptionClass, fmt,
actualClassName, desiredClassName);
free(desiredClassName);
free(actualClassName);
@@ -1343,22 +1246,22 @@
}
void dvmThrowClassCircularityError(const char* descriptor) {
- dvmThrowExceptionByClassWithClassMessage(gDvm.exClassCircularityError,
+ dvmThrowExceptionWithClassMessage(gDvm.exClassCircularityError,
descriptor);
}
void dvmThrowClassFormatError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exClassFormatError, msg);
+ dvmThrowException(gDvm.exClassFormatError, msg);
}
void dvmThrowClassNotFoundException(const char* name) {
// TODO: Should the name be converted into human-readable form?
- dvmThrowExceptionByClass(gDvm.exClassNotFoundException, name);
+ dvmThrowException(gDvm.exClassNotFoundException, name);
}
void dvmThrowChainedClassNotFoundException(const char* name, Object* cause) {
// TODO: Should the name be converted into human-readable form?
- dvmThrowChainedExceptionByClass(gDvm.exClassNotFoundException, name,
+ dvmThrowChainedException(gDvm.exClassNotFoundException, name,
cause);
}
@@ -1391,58 +1294,58 @@
dvmAddTrackedAlloc(exception, self);
dvmClearException(self);
- dvmThrowChainedExceptionByClass(gDvm.exExceptionInInitializerError,
+ dvmThrowChainedException(gDvm.exExceptionInInitializerError,
NULL, exception);
dvmReleaseTrackedAlloc(exception, self);
}
void dvmThrowFileNotFoundException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exFileNotFoundException, msg);
+ dvmThrowException(gDvm.exFileNotFoundException, msg);
}
void dvmThrowIOException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIOException, msg);
+ dvmThrowException(gDvm.exIOException, msg);
}
void dvmThrowIllegalAccessException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalAccessException, msg);
+ dvmThrowException(gDvm.exIllegalAccessException, msg);
}
void dvmThrowIllegalAccessError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalAccessError, msg);
+ dvmThrowException(gDvm.exIllegalAccessError, msg);
}
void dvmThrowIllegalArgumentException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalArgumentException, msg);
+ dvmThrowException(gDvm.exIllegalArgumentException, msg);
}
void dvmThrowIllegalMonitorStateException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalMonitorStateException, msg);
+ dvmThrowException(gDvm.exIllegalMonitorStateException, msg);
}
void dvmThrowIllegalStateException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalStateException, msg);
+ dvmThrowException(gDvm.exIllegalStateException, msg);
}
void dvmThrowIllegalThreadStateException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIllegalThreadStateException, msg);
+ dvmThrowException(gDvm.exIllegalThreadStateException, msg);
}
void dvmThrowIncompatibleClassChangeError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exIncompatibleClassChangeError, msg);
+ dvmThrowException(gDvm.exIncompatibleClassChangeError, msg);
}
void dvmThrowIncompatibleClassChangeErrorWithClassMessage(
const char* descriptor)
{
- dvmThrowExceptionByClassWithClassMessage(
+ dvmThrowExceptionWithClassMessage(
gDvm.exIncompatibleClassChangeError, descriptor);
}
void dvmThrowInstantiationException(ClassObject* clazz,
const char* extraDetail) {
char* className = dvmHumanReadableDescriptor(clazz->descriptor);
- dvmThrowExceptionFmtByClass(gDvm.exInstantiationException,
+ dvmThrowExceptionFmt(gDvm.exInstantiationException,
"can't instantiate class %s%s%s", className,
(extraDetail == NULL) ? "" : "; ",
(extraDetail == NULL) ? "" : extraDetail);
@@ -1450,84 +1353,90 @@
}
void dvmThrowInternalError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exInternalError, msg);
+ dvmThrowException(gDvm.exInternalError, msg);
}
void dvmThrowInterruptedException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exInterruptedException, msg);
+ dvmThrowException(gDvm.exInterruptedException, msg);
}
void dvmThrowLinkageError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exLinkageError, msg);
+ dvmThrowException(gDvm.exLinkageError, msg);
}
void dvmThrowNegativeArraySizeException(s4 size) {
- dvmThrowExceptionFmtByClass(gDvm.exNegativeArraySizeException, "%d", size);
+ dvmThrowExceptionFmt(gDvm.exNegativeArraySizeException, "%d", size);
}
void dvmThrowNoClassDefFoundError(const char* descriptor) {
- dvmThrowExceptionByClassWithClassMessage(gDvm.exNoClassDefFoundError,
+ dvmThrowExceptionWithClassMessage(gDvm.exNoClassDefFoundError,
descriptor);
}
+void dvmThrowChainedNoClassDefFoundError(const char* descriptor,
+ Object* cause) {
+ dvmThrowChainedExceptionWithClassMessage(
+ gDvm.exNoClassDefFoundError, descriptor, cause);
+}
+
void dvmThrowNoSuchFieldError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exNoSuchFieldError, msg);
+ dvmThrowException(gDvm.exNoSuchFieldError, msg);
}
void dvmThrowNoSuchFieldException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exNoSuchFieldException, msg);
+ dvmThrowException(gDvm.exNoSuchFieldException, msg);
}
void dvmThrowNoSuchMethodError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exNoSuchMethodError, msg);
+ dvmThrowException(gDvm.exNoSuchMethodError, msg);
}
void dvmThrowNullPointerException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exNullPointerException, msg);
+ dvmThrowException(gDvm.exNullPointerException, msg);
}
void dvmThrowOutOfMemoryError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exOutOfMemoryError, msg);
+ dvmThrowException(gDvm.exOutOfMemoryError, msg);
}
void dvmThrowRuntimeException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exRuntimeException, msg);
+ dvmThrowException(gDvm.exRuntimeException, msg);
}
void dvmThrowStaleDexCacheError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exStaleDexCacheError, msg);
+ dvmThrowException(gDvm.exStaleDexCacheError, msg);
}
void dvmThrowStringIndexOutOfBoundsExceptionWithIndex(jsize stringLength,
jsize requestIndex) {
- dvmThrowExceptionFmtByClass(gDvm.exStringIndexOutOfBoundsException,
+ dvmThrowExceptionFmt(gDvm.exStringIndexOutOfBoundsException,
"length=%d; index=%d", stringLength, requestIndex);
}
void dvmThrowStringIndexOutOfBoundsExceptionWithRegion(jsize stringLength,
jsize requestStart, jsize requestLength) {
- dvmThrowExceptionFmtByClass(gDvm.exStringIndexOutOfBoundsException,
- "length=%d; regionStart=%d regionLength=%d",
+ dvmThrowExceptionFmt(gDvm.exStringIndexOutOfBoundsException,
+ "length=%d; regionStart=%d; regionLength=%d",
stringLength, requestStart, requestLength);
}
void dvmThrowTypeNotPresentException(const char* descriptor) {
- dvmThrowExceptionByClassWithClassMessage(gDvm.exTypeNotPresentException,
+ dvmThrowExceptionWithClassMessage(gDvm.exTypeNotPresentException,
descriptor);
}
void dvmThrowUnsatisfiedLinkError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exUnsatisfiedLinkError, msg);
+ dvmThrowException(gDvm.exUnsatisfiedLinkError, msg);
}
void dvmThrowUnsupportedOperationException(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exUnsupportedOperationException, msg);
+ dvmThrowException(gDvm.exUnsupportedOperationException, msg);
}
void dvmThrowVerifyError(const char* descriptor) {
- dvmThrowExceptionByClassWithClassMessage(gDvm.exVerifyError, descriptor);
+ dvmThrowExceptionWithClassMessage(gDvm.exVerifyError, descriptor);
}
void dvmThrowVirtualMachineError(const char* msg) {
- dvmThrowExceptionByClass(gDvm.exVirtualMachineError, msg);
+ dvmThrowException(gDvm.exVirtualMachineError, msg);
}
diff --git a/vm/Exception.h b/vm/Exception.h
index 6d27437..3022e04 100644
--- a/vm/Exception.h
+++ b/vm/Exception.h
@@ -21,86 +21,70 @@
#define _DALVIK_EXCEPTION
/*
- * Throw an exception in the current thread, by class descriptor.
+ * Create a Throwable and throw an exception in the current thread (where
+ * "throwing" just means "set the thread's exception pointer").
+ *
+ * "msg" and/or "cause" may be NULL.
+ *
+ * If we have a bad exception hierarchy -- something in Throwable.<init>
+ * is missing -- then every attempt to throw an exception will result
+ * in another exception. Exceptions are generally allowed to "chain"
+ * to other exceptions, so it's hard to auto-detect this problem. It can
+ * only happen if the system classes are broken, so it's probably not
+ * worth spending cycles to detect it.
+ *
+ * We do have one case to worry about: if the classpath is completely
+ * wrong, we'll go into a death spin during startup because we can't find
+ * the initial class and then we can't find NoClassDefFoundError. We have
+ * to handle this case.
*/
-void dvmThrowChainedException(const char* exceptionDescriptor, const char* msg,
- Object* cause);
-INLINE void dvmThrowException(const char* exceptionDescriptor,
+void dvmThrowChainedException(ClassObject* exceptionClass,
+ const char* msg, Object* cause);
+INLINE void dvmThrowException(ClassObject* exceptionClass,
const char* msg)
{
- dvmThrowChainedException(exceptionDescriptor, msg, NULL);
+ dvmThrowChainedException(exceptionClass, msg, NULL);
}
/*
* Like dvmThrowException, but takes printf-style args for the message.
*/
-void dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt,
- va_list args);
-void dvmThrowExceptionFmt(const char* exceptionDescriptor, const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__ ((format(printf, 2, 3)))
-#endif
- ;
-INLINE void dvmThrowExceptionFmt(const char* exceptionDescriptor,
- const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- dvmThrowExceptionFmtV(exceptionDescriptor, fmt, args);
- va_end(args);
-}
-
-/*
- * Throw an exception in the current thread, by class object.
- */
-void dvmThrowChainedExceptionByClass(ClassObject* exceptionClass,
- const char* msg, Object* cause);
-INLINE void dvmThrowExceptionByClass(ClassObject* exceptionClass,
- const char* msg)
-{
- dvmThrowChainedExceptionByClass(exceptionClass, msg, NULL);
-}
-
-/*
- * Like dvmThrowExceptionFmt, but takes an exception class object instead
- * of a descriptor string.
- */
-void dvmThrowExceptionFmtByClassV(ClassObject* exceptionClass,
+void dvmThrowExceptionFmtV(ClassObject* exceptionClass,
const char* fmt, va_list args);
-void dvmThrowExceptionFmtByClass(ClassObject* exceptionClass,
+void dvmThrowExceptionFmt(ClassObject* exceptionClass,
const char* fmt, ...)
#if defined(__GNUC__)
__attribute__ ((format(printf, 2, 3)))
#endif
;
-INLINE void dvmThrowExceptionFmtByClass(ClassObject* exceptionClass,
+INLINE void dvmThrowExceptionFmt(ClassObject* exceptionClass,
const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- dvmThrowExceptionFmtByClassV(exceptionClass, fmt, args);
+ dvmThrowExceptionFmtV(exceptionClass, fmt, args);
va_end(args);
}
/*
- * Throw the named exception using the human-readable form of the class
- * descriptor as the exception message, and with the specified cause.
+ * Like dvmThrowChainedException, but take a class object
+ * instead of a name and turn the given message into the
+ * human-readable form for a descriptor.
*/
-void dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
- const char* messageDescriptor, Object* cause);
-INLINE void dvmThrowExceptionWithClassMessage(const char* exceptionDescriptor,
- const char* messageDescriptor)
-{
- dvmThrowChainedExceptionWithClassMessage(exceptionDescriptor,
- messageDescriptor, NULL);
-}
+void dvmThrowChainedExceptionWithClassMessage(
+ ClassObject* exceptionClass, const char* messageDescriptor,
+ Object* cause);
/*
* Like dvmThrowException, but take a class object instead of a name
* and turn the given message into the human-readable form for a descriptor.
*/
-void dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
- const char* messageDescriptor);
+INLINE void dvmThrowExceptionWithClassMessage(
+ ClassObject* exceptionClass, const char* messageDescriptor)
+{
+ dvmThrowChainedExceptionWithClassMessage(exceptionClass,
+ messageDescriptor, NULL);
+}
/*
* Return the exception being thrown in the current thread, or NULL if
@@ -231,9 +215,9 @@
/*
* Throw an ArrayIndexOutOfBoundsException in the current thread,
- * using the given index and array length in the detail message.
+ * using the given array length and index in the detail message.
*/
-void dvmThrowArrayIndexOutOfBoundsException(int index, int length);
+void dvmThrowArrayIndexOutOfBoundsException(int length, int index);
/*
* Throw an ArrayStoreException in the current thread, using the given classes'
@@ -378,6 +362,14 @@
void dvmThrowNoClassDefFoundError(const char* descriptor);
/**
+ * Throw a NoClassDefFoundError in the current thread, with the given
+ * cause, and the human-readable form of the given descriptor as the
+ * detail message.
+ */
+void dvmThrowChainedNoClassDefFoundError(const char* descriptor,
+ Object* cause);
+
+/**
* Throw a NoSuchFieldError in the current thread, with the given
* detail message.
*/
diff --git a/vm/Globals.h b/vm/Globals.h
index a4b47a6..e595df3 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -178,7 +178,6 @@
* VM init management.
*/
bool initializing;
- int initExceptionCount;
bool optimizing;
/*
@@ -286,6 +285,7 @@
ClassObject* exIllegalStateException;
ClassObject* exIllegalThreadStateException;
ClassObject* exIncompatibleClassChangeError;
+ ClassObject* exInstantiationError;
ClassObject* exInstantiationException;
ClassObject* exInternalError;
ClassObject* exInterruptedException;
@@ -506,10 +506,14 @@
*/
#ifdef USE_INDIRECT_REF
IndirectRefTable jniGlobalRefTable;
+ IndirectRefTable jniWeakGlobalRefTable;
#else
ReferenceTable jniGlobalRefTable;
#endif
pthread_mutex_t jniGlobalRefLock;
+#ifdef USE_INDIRECT_REF
+ pthread_mutex_t jniWeakGlobalRefLock;
+#endif
int jniGlobalRefHiMark;
int jniGlobalRefLoMark;
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c
index f940653..0a69f3c 100644
--- a/vm/IndirectRefTable.c
+++ b/vm/IndirectRefTable.c
@@ -27,7 +27,7 @@
{
assert(initialCount > 0);
assert(initialCount <= maxCount);
- assert(kind == kIndirectKindLocal || kind == kIndirectKindGlobal);
+ assert(kind != kIndirectKindInvalid);
pRef->table = (Object**) malloc(initialCount * sizeof(Object*));
if (pRef->table == NULL)
diff --git a/vm/Init.c b/vm/Init.c
index e4d05ee..33d808b 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -1145,185 +1145,6 @@
}
/*
- * Helper for dvmInitRequiredClassesAndMembers(), which looks up
- * classes and stores them to the indicated pointer, returning a
- * failure code (false == failure).
- */
-static bool initRef(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;
- }
-
- if (name[0] == '[') {
- result = dvmFindArrayClass(name, NULL);
- } else {
- result = dvmFindSystemClassNoInit(name);
- }
-
- if (result == NULL) {
- LOGE("Could not find essential class %s\n", name);
- return false;
- }
-
- *pClass = result;
- return true;
-}
-
-/* (documented in header) */
-int dvmFindRequiredClassesAndMembers(void) {
- /*
- * Note: Under normal VM use, this is called by dvmStartup()
- * below. For dex optimization, this is called as well, but in
- * that case, the call is made from DexPrepare.c.
- */
-
- bool ok = true;
-
- /* The corest of the core classes */
-
- ok &= initRef(&gDvm.classJavaLangClass, "Ljava/lang/Class;");
- ok &= initRef(&gDvm.classJavaLangObject, "Ljava/lang/Object;");
-
- ok &= initRef(&gDvm.classJavaLangString, "Ljava/lang/String;");
- ok &= initRef(&gDvm.classJavaLangThread, "Ljava/lang/Thread;");
- ok &= initRef(&gDvm.classJavaLangThreadGroup, "Ljava/lang/ThreadGroup;");
- ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
- ok &= initRef(&gDvm.classJavaLangVMThread, "Ljava/lang/VMThread;");
-
- /* Exception classes and related support classes */
-
- ok &= initRef(&gDvm.exAbstractMethodError,
- "Ljava/lang/AbstractMethodError;");
- ok &= initRef(&gDvm.exArithmeticException,
- "Ljava/lang/ArithmeticException;");
- ok &= initRef(&gDvm.exArrayIndexOutOfBoundsException,
- "Ljava/lang/ArrayIndexOutOfBoundsException;");
- ok &= initRef(&gDvm.exArrayStoreException,
- "Ljava/lang/ArrayStoreException;");
- ok &= initRef(&gDvm.exClassCastException,
- "Ljava/lang/ClassCastException;");
- ok &= initRef(&gDvm.exClassCircularityError,
- "Ljava/lang/ClassCircularityError;");
- ok &= initRef(&gDvm.exClassNotFoundException,
- "Ljava/lang/ClassNotFoundException;");
- ok &= initRef(&gDvm.exClassFormatError, "Ljava/lang/ClassFormatError;");
- ok &= initRef(&gDvm.exError, "Ljava/lang/Error;");
- ok &= initRef(&gDvm.exExceptionInInitializerError,
- "Ljava/lang/ExceptionInInitializerError;");
- ok &= initRef(&gDvm.exFileNotFoundException,
- "Ljava/io/FileNotFoundException;");
- ok &= initRef(&gDvm.exIOException, "Ljava/io/IOException;");
- ok &= initRef(&gDvm.exIllegalAccessError,
- "Ljava/lang/IllegalAccessError;");
- ok &= initRef(&gDvm.exIllegalAccessException,
- "Ljava/lang/IllegalAccessException;");
- ok &= initRef(&gDvm.exIllegalArgumentException,
- "Ljava/lang/IllegalArgumentException;");
- ok &= initRef(&gDvm.exIllegalMonitorStateException,
- "Ljava/lang/IllegalMonitorStateException;");
- ok &= initRef(&gDvm.exIllegalStateException,
- "Ljava/lang/IllegalStateException;");
- ok &= initRef(&gDvm.exIllegalThreadStateException,
- "Ljava/lang/IllegalThreadStateException;");
- ok &= initRef(&gDvm.exIncompatibleClassChangeError,
- "Ljava/lang/IncompatibleClassChangeError;");
- ok &= initRef(&gDvm.exInstantiationException,
- "Ljava/lang/InstantiationException;");
- ok &= initRef(&gDvm.exInternalError,
- "Ljava/lang/InternalError;");
- ok &= initRef(&gDvm.exInterruptedException,
- "Ljava/lang/InterruptedException;");
- ok &= initRef(&gDvm.exLinkageError,
- "Ljava/lang/LinkageError;");
- ok &= initRef(&gDvm.exNegativeArraySizeException,
- "Ljava/lang/NegativeArraySizeException;");
- ok &= initRef(&gDvm.exNoClassDefFoundError,
- "Ljava/lang/NoClassDefFoundError;");
- ok &= initRef(&gDvm.exNoSuchFieldError,
- "Ljava/lang/NoSuchFieldError;");
- ok &= initRef(&gDvm.exNoSuchFieldException,
- "Ljava/lang/NoSuchFieldException;");
- ok &= initRef(&gDvm.exNoSuchMethodError,
- "Ljava/lang/NoSuchMethodError;");
- ok &= initRef(&gDvm.exNullPointerException,
- "Ljava/lang/NullPointerException;");
- ok &= initRef(&gDvm.exOutOfMemoryError,
- "Ljava/lang/OutOfMemoryError;");
- ok &= initRef(&gDvm.exRuntimeException, "Ljava/lang/RuntimeException;");
- ok &= initRef(&gDvm.exStackOverflowError,
- "Ljava/lang/StackOverflowError;");
- ok &= initRef(&gDvm.exStaleDexCacheError,
- "Ldalvik/system/StaleDexCacheError;");
- ok &= initRef(&gDvm.exStringIndexOutOfBoundsException,
- "Ljava/lang/StringIndexOutOfBoundsException;");
- ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
- ok &= initRef(&gDvm.exTypeNotPresentException,
- "Ljava/lang/TypeNotPresentException;");
- ok &= initRef(&gDvm.exUnsatisfiedLinkError,
- "Ljava/lang/UnsatisfiedLinkError;");
- ok &= initRef(&gDvm.exUnsupportedOperationException,
- "Ljava/lang/UnsupportedOperationException;");
- ok &= initRef(&gDvm.exVerifyError,
- "Ljava/lang/VerifyError;");
- ok &= initRef(&gDvm.exVirtualMachineError,
- "Ljava/lang/VirtualMachineError;");
-
- ok &= initRef(&gDvm.classJavaLangStackTraceElement,
- "Ljava/lang/StackTraceElement;");
- ok &= initRef(&gDvm.classJavaLangStackTraceElementArray,
- "[Ljava/lang/StackTraceElement;");
-
- if (!ok) {
- return false;
- }
-
- /*
- * Find the StackTraceElement constructor. Note that, unlike other
- * saved method lookups, we're using a Method* instead of a vtable
- * offset. This is because constructors don't have vtable offsets.
- * (Also, since we're creating the object in question, it's
- * impossible for anyone to sub-class it.)
- */
- Method* meth;
- meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
- "<init>",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
- if (meth == NULL) {
- LOGE("Unable to find constructor for StackTraceElement\n");
- return false;
- }
- gDvm.methJavaLangStackTraceElement_init = meth;
-
- /* grab an offset for the field Throwable.stackState */
- gDvm.offJavaLangThrowable_stackState =
- dvmFindFieldOffset(gDvm.exThrowable,
- "stackState", "Ljava/lang/Object;");
- if (gDvm.offJavaLangThrowable_stackState < 0) {
- LOGE("Unable to find Throwable.stackState\n");
- return false;
- }
-
- /* and one for the field Throwable.cause, just 'cause */
- gDvm.offJavaLangThrowable_cause =
- dvmFindFieldOffset(gDvm.exThrowable,
- "cause", "Ljava/lang/Throwable;");
- if (gDvm.offJavaLangThrowable_cause < 0) {
- LOGE("Unable to find Throwable.cause\n");
- return false;
- }
-
- return true;
-}
-
-/*
* VM initialization. Pass in any options provided on the command line.
* Do not pass in the class name or the options for the class.
*
@@ -1416,10 +1237,6 @@
if (!dvmFindRequiredClassesAndMembers())
goto fail;
- if (!dvmBaseClassStartup())
- goto fail;
- if (!dvmThreadObjStartup())
- goto fail;
if (!dvmStringInternStartup())
goto fail;
if (!dvmNativeStartup())
@@ -1428,8 +1245,6 @@
goto fail;
if (!dvmJniStartup())
goto fail;
- if (!dvmReflectStartup())
- goto fail;
if (!dvmProfilingStartup())
goto fail;
@@ -1520,7 +1335,6 @@
#endif
assert(!dvmCheckException(dvmThreadSelf()));
- gDvm.initExceptionCount = 0;
return 0;
@@ -1837,7 +1651,6 @@
LOGD("VM cleaning up\n");
dvmDebuggerShutdown();
- dvmReflectShutdown();
dvmProfilingShutdown();
dvmJniShutdown();
dvmStringInternShutdown();
diff --git a/vm/Init.h b/vm/Init.h
index 06b93af..60f6bf3 100644
--- a/vm/Init.h
+++ b/vm/Init.h
@@ -45,8 +45,10 @@
* storing references to them into the globals instance. See
* Globals.h. This function is exposed so that dex optimization may
* call it (while avoiding doing other unnecessary VM initialization).
+ *
+ * The function returns a success flag (true == success).
*/
-int dvmFindRequiredClassesAndMembers(void);
+bool dvmFindRequiredClassesAndMembers(void);
/*
* Replacement for fprintf() when we want to send a message to the console.
diff --git a/vm/InitRefs.c b/vm/InitRefs.c
new file mode 100644
index 0000000..242db43
--- /dev/null
+++ b/vm/InitRefs.c
@@ -0,0 +1,597 @@
+/*
+ * 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.
+ */
+
+/*
+ * Code to initialize references to classes and members for use by
+ * lower-level VM facilities
+ */
+
+#include "Dalvik.h"
+
+/*
+ * Helper for dvmInitRequiredClassesAndMembers(), which looks up
+ * classes and stores them to the indicated pointer, returning a
+ * failure code (false == failure).
+ */
+static bool initRef(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;
+ }
+
+ if (name[0] == '[') {
+ result = dvmFindArrayClass(name, NULL);
+ } else {
+ result = dvmFindSystemClassNoInit(name);
+ }
+
+ if (result == NULL) {
+ LOGE("Could not find essential class %s\n", name);
+ return false;
+ }
+
+ *pClass = result;
+ return true;
+}
+
+static bool find1(void) {
+ /*
+ * Note: Under normal VM use, this is called by dvmStartup()
+ * in Init.c. For dex optimization, this is called as well, but in
+ * that case, the call is made from DexPrepare.c.
+ */
+
+ bool ok = true;
+
+ /* The corest of the core classes */
+
+ ok &= initRef(&gDvm.classJavaLangClass, "Ljava/lang/Class;");
+ ok &= initRef(&gDvm.classJavaLangObject, "Ljava/lang/Object;");
+ ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
+
+ ok &= initRef(&gDvm.classJavaLangString, "Ljava/lang/String;");
+ ok &= initRef(&gDvm.classJavaLangThread, "Ljava/lang/Thread;");
+ ok &= initRef(&gDvm.classJavaLangThreadGroup, "Ljava/lang/ThreadGroup;");
+ ok &= initRef(&gDvm.classJavaLangVMThread, "Ljava/lang/VMThread;");
+
+ /* Exception classes and related support classes */
+
+ ok &= initRef(&gDvm.exAbstractMethodError,
+ "Ljava/lang/AbstractMethodError;");
+ ok &= initRef(&gDvm.exArithmeticException,
+ "Ljava/lang/ArithmeticException;");
+ ok &= initRef(&gDvm.exArrayIndexOutOfBoundsException,
+ "Ljava/lang/ArrayIndexOutOfBoundsException;");
+ ok &= initRef(&gDvm.exArrayStoreException,
+ "Ljava/lang/ArrayStoreException;");
+ ok &= initRef(&gDvm.exClassCastException,
+ "Ljava/lang/ClassCastException;");
+ ok &= initRef(&gDvm.exClassCircularityError,
+ "Ljava/lang/ClassCircularityError;");
+ ok &= initRef(&gDvm.exClassNotFoundException,
+ "Ljava/lang/ClassNotFoundException;");
+ ok &= initRef(&gDvm.exClassFormatError, "Ljava/lang/ClassFormatError;");
+ ok &= initRef(&gDvm.exError, "Ljava/lang/Error;");
+ ok &= initRef(&gDvm.exExceptionInInitializerError,
+ "Ljava/lang/ExceptionInInitializerError;");
+ ok &= initRef(&gDvm.exFileNotFoundException,
+ "Ljava/io/FileNotFoundException;");
+ ok &= initRef(&gDvm.exIOException, "Ljava/io/IOException;");
+ ok &= initRef(&gDvm.exIllegalAccessError,
+ "Ljava/lang/IllegalAccessError;");
+ ok &= initRef(&gDvm.exIllegalAccessException,
+ "Ljava/lang/IllegalAccessException;");
+ ok &= initRef(&gDvm.exIllegalArgumentException,
+ "Ljava/lang/IllegalArgumentException;");
+ ok &= initRef(&gDvm.exIllegalMonitorStateException,
+ "Ljava/lang/IllegalMonitorStateException;");
+ ok &= initRef(&gDvm.exIllegalStateException,
+ "Ljava/lang/IllegalStateException;");
+ ok &= initRef(&gDvm.exIllegalThreadStateException,
+ "Ljava/lang/IllegalThreadStateException;");
+ ok &= initRef(&gDvm.exIncompatibleClassChangeError,
+ "Ljava/lang/IncompatibleClassChangeError;");
+ ok &= initRef(&gDvm.exInstantiationError,
+ "Ljava/lang/InstantiationError;");
+ ok &= initRef(&gDvm.exInstantiationException,
+ "Ljava/lang/InstantiationException;");
+ ok &= initRef(&gDvm.exInternalError,
+ "Ljava/lang/InternalError;");
+ ok &= initRef(&gDvm.exInterruptedException,
+ "Ljava/lang/InterruptedException;");
+ ok &= initRef(&gDvm.exLinkageError,
+ "Ljava/lang/LinkageError;");
+ ok &= initRef(&gDvm.exNegativeArraySizeException,
+ "Ljava/lang/NegativeArraySizeException;");
+ ok &= initRef(&gDvm.exNoClassDefFoundError,
+ "Ljava/lang/NoClassDefFoundError;");
+ ok &= initRef(&gDvm.exNoSuchFieldError,
+ "Ljava/lang/NoSuchFieldError;");
+ ok &= initRef(&gDvm.exNoSuchFieldException,
+ "Ljava/lang/NoSuchFieldException;");
+ ok &= initRef(&gDvm.exNoSuchMethodError,
+ "Ljava/lang/NoSuchMethodError;");
+ ok &= initRef(&gDvm.exNullPointerException,
+ "Ljava/lang/NullPointerException;");
+ ok &= initRef(&gDvm.exOutOfMemoryError,
+ "Ljava/lang/OutOfMemoryError;");
+ ok &= initRef(&gDvm.exRuntimeException, "Ljava/lang/RuntimeException;");
+ ok &= initRef(&gDvm.exStackOverflowError,
+ "Ljava/lang/StackOverflowError;");
+ ok &= initRef(&gDvm.exStaleDexCacheError,
+ "Ldalvik/system/StaleDexCacheError;");
+ ok &= initRef(&gDvm.exStringIndexOutOfBoundsException,
+ "Ljava/lang/StringIndexOutOfBoundsException;");
+ ok &= initRef(&gDvm.exTypeNotPresentException,
+ "Ljava/lang/TypeNotPresentException;");
+ ok &= initRef(&gDvm.exUnsatisfiedLinkError,
+ "Ljava/lang/UnsatisfiedLinkError;");
+ ok &= initRef(&gDvm.exUnsupportedOperationException,
+ "Ljava/lang/UnsupportedOperationException;");
+ ok &= initRef(&gDvm.exVerifyError,
+ "Ljava/lang/VerifyError;");
+ ok &= initRef(&gDvm.exVirtualMachineError,
+ "Ljava/lang/VirtualMachineError;");
+
+ ok &= initRef(&gDvm.classJavaLangStackTraceElement,
+ "Ljava/lang/StackTraceElement;");
+ ok &= initRef(&gDvm.classJavaLangStackTraceElementArray,
+ "[Ljava/lang/StackTraceElement;");
+
+ if (!ok) {
+ return false;
+ }
+
+ /*
+ * Find the StackTraceElement constructor. Note that, unlike other
+ * saved method lookups, we're using a Method* instead of a vtable
+ * offset. This is because constructors don't have vtable offsets.
+ * (Also, since we're creating the object in question, it's
+ * impossible for anyone to sub-class it.)
+ */
+ Method* meth;
+ meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
+ "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
+ if (meth == NULL) {
+ LOGE("Unable to find constructor for StackTraceElement\n");
+ return false;
+ }
+ gDvm.methJavaLangStackTraceElement_init = meth;
+
+ /* grab an offset for the field Throwable.stackState */
+ gDvm.offJavaLangThrowable_stackState =
+ dvmFindFieldOffset(gDvm.exThrowable,
+ "stackState", "Ljava/lang/Object;");
+ if (gDvm.offJavaLangThrowable_stackState < 0) {
+ LOGE("Unable to find Throwable.stackState\n");
+ return false;
+ }
+
+ /* and one for the field Throwable.cause, just 'cause */
+ gDvm.offJavaLangThrowable_cause =
+ dvmFindFieldOffset(gDvm.exThrowable,
+ "cause", "Ljava/lang/Throwable;");
+ if (gDvm.offJavaLangThrowable_cause < 0) {
+ LOGE("Unable to find Throwable.cause\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool find2(void) {
+ ClassObject* clClass = dvmFindSystemClassNoInit("Ljava/lang/ClassLoader;");
+ Method* meth = dvmFindVirtualMethodByDescriptor(clClass, "loadClass",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ if (meth == NULL) {
+ LOGE("Unable to find loadClass() in java.lang.ClassLoader\n");
+ return false;
+ }
+ gDvm.voffJavaLangClassLoader_loadClass = meth->methodIndex;
+
+ return true;
+}
+
+static bool find3(void) {
+ assert(gDvm.classJavaLangThread != NULL);
+ assert(gDvm.classJavaLangThreadGroup != NULL);
+ assert(gDvm.classJavaLangVMThread != NULL);
+
+ /*
+ * Cache field offsets. This makes things a little faster, at the
+ * expense of hard-coding non-public field names into the VM.
+ */
+ gDvm.offJavaLangThread_vmThread =
+ dvmFindFieldOffset(gDvm.classJavaLangThread,
+ "vmThread", "Ljava/lang/VMThread;");
+ gDvm.offJavaLangThread_group =
+ dvmFindFieldOffset(gDvm.classJavaLangThread,
+ "group", "Ljava/lang/ThreadGroup;");
+ gDvm.offJavaLangThread_daemon =
+ dvmFindFieldOffset(gDvm.classJavaLangThread, "daemon", "Z");
+ gDvm.offJavaLangThread_name =
+ dvmFindFieldOffset(gDvm.classJavaLangThread,
+ "name", "Ljava/lang/String;");
+ gDvm.offJavaLangThread_priority =
+ dvmFindFieldOffset(gDvm.classJavaLangThread, "priority", "I");
+
+ if (gDvm.offJavaLangThread_vmThread < 0 ||
+ gDvm.offJavaLangThread_group < 0 ||
+ gDvm.offJavaLangThread_daemon < 0 ||
+ gDvm.offJavaLangThread_name < 0 ||
+ gDvm.offJavaLangThread_priority < 0)
+ {
+ LOGE("Unable to find all fields in java.lang.Thread\n");
+ return false;
+ }
+
+ gDvm.offJavaLangVMThread_thread =
+ dvmFindFieldOffset(gDvm.classJavaLangVMThread,
+ "thread", "Ljava/lang/Thread;");
+ gDvm.offJavaLangVMThread_vmData =
+ dvmFindFieldOffset(gDvm.classJavaLangVMThread, "vmData", "I");
+ if (gDvm.offJavaLangVMThread_thread < 0 ||
+ gDvm.offJavaLangVMThread_vmData < 0)
+ {
+ LOGE("Unable to find all fields in java.lang.VMThread\n");
+ return false;
+ }
+
+ /*
+ * Cache the vtable offset for "run()".
+ *
+ * We don't want to keep the Method* because then we won't find see
+ * methods defined in subclasses.
+ */
+ Method* meth;
+ meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThread, "run", "()V");
+ if (meth == NULL) {
+ LOGE("Unable to find run() in java.lang.Thread\n");
+ return false;
+ }
+ gDvm.voffJavaLangThread_run = meth->methodIndex;
+
+ /*
+ * Cache vtable offsets for ThreadGroup methods.
+ */
+ meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThreadGroup,
+ "removeThread", "(Ljava/lang/Thread;)V");
+ if (meth == NULL) {
+ LOGE("Unable to find removeThread(Thread) in java.lang.ThreadGroup\n");
+ return false;
+ }
+ gDvm.voffJavaLangThreadGroup_removeThread = meth->methodIndex;
+
+ return true;
+}
+
+static bool find4(void) {
+ Method* meth;
+
+ /*
+ * Grab the PhantomReference constructor.
+ */
+ gDvm.classJavaLangRefPhantomReference =
+ dvmFindSystemClassNoInit("Ljava/lang/ref/PhantomReference;");
+ if (gDvm.classJavaLangRefPhantomReference == NULL) {
+ LOGE("Unable to find PhantomReference class\n");
+ return false;
+ }
+ meth= dvmFindDirectMethodByDescriptor(gDvm.classJavaLangRefPhantomReference,
+ "<init>", "(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V");
+ if (meth == NULL) {
+ LOGE("Unable to find constructor for PhantomReference\n");
+ return false;
+ }
+ gDvm.methJavaLangRefPhantomReference_init = meth;
+
+
+ /*
+ * Look up and cache pointers to some direct buffer classes, fields,
+ * and methods.
+ */
+ ClassObject* readWriteBufferClass =
+ dvmFindSystemClassNoInit("Ljava/nio/ReadWriteDirectByteBuffer;");
+ ClassObject* bufferClass =
+ dvmFindSystemClassNoInit("Ljava/nio/Buffer;");
+
+ if (readWriteBufferClass == NULL || bufferClass == NULL) {
+ LOGE("Unable to find internal direct buffer classes\n");
+ return false;
+ }
+ gDvm.classJavaNioReadWriteDirectByteBuffer = readWriteBufferClass;
+
+ meth = dvmFindDirectMethodByDescriptor(readWriteBufferClass,
+ "<init>",
+ "(II)V");
+ if (meth == NULL) {
+ LOGE("Unable to find ReadWriteDirectByteBuffer.<init>\n");
+ return false;
+ }
+ gDvm.methJavaNioReadWriteDirectByteBuffer_init = meth;
+
+ gDvm.offJavaNioBuffer_capacity =
+ dvmFindFieldOffset(bufferClass, "capacity", "I");
+ if (gDvm.offJavaNioBuffer_capacity < 0) {
+ LOGE("Unable to find Buffer.capacity\n");
+ return false;
+ }
+
+ gDvm.offJavaNioBuffer_effectiveDirectAddress =
+ dvmFindFieldOffset(bufferClass, "effectiveDirectAddress", "I");
+ if (gDvm.offJavaNioBuffer_effectiveDirectAddress < 0) {
+ LOGE("Unable to find Buffer.effectiveDirectAddress\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool find5(void)
+{
+ gDvm.classJavaLangReflectAccessibleObject =
+ dvmFindSystemClassNoInit("Ljava/lang/reflect/AccessibleObject;");
+ gDvm.classJavaLangReflectConstructor =
+ dvmFindSystemClassNoInit("Ljava/lang/reflect/Constructor;");
+ gDvm.classJavaLangReflectConstructorArray =
+ dvmFindArrayClass("[Ljava/lang/reflect/Constructor;", NULL);
+ gDvm.classJavaLangReflectField =
+ dvmFindSystemClassNoInit("Ljava/lang/reflect/Field;");
+ gDvm.classJavaLangReflectFieldArray =
+ dvmFindArrayClass("[Ljava/lang/reflect/Field;", NULL);
+ gDvm.classJavaLangReflectMethod =
+ dvmFindSystemClassNoInit("Ljava/lang/reflect/Method;");
+ gDvm.classJavaLangReflectMethodArray =
+ dvmFindArrayClass("[Ljava/lang/reflect/Method;", NULL);
+ gDvm.classJavaLangReflectProxy =
+ dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
+ if (gDvm.classJavaLangReflectAccessibleObject == NULL ||
+ gDvm.classJavaLangReflectConstructor == NULL ||
+ gDvm.classJavaLangReflectConstructorArray == NULL ||
+ gDvm.classJavaLangReflectField == NULL ||
+ gDvm.classJavaLangReflectFieldArray == NULL ||
+ gDvm.classJavaLangReflectMethod == NULL ||
+ gDvm.classJavaLangReflectMethodArray == NULL ||
+ gDvm.classJavaLangReflectProxy == NULL)
+ {
+ LOGE("Could not find one or more reflection classes\n");
+ return false;
+ }
+
+ gDvm.methJavaLangReflectConstructor_init =
+ dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectConstructor, "<init>",
+ "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V");
+ gDvm.methJavaLangReflectField_init =
+ dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectField, "<init>",
+ "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
+ gDvm.methJavaLangReflectMethod_init =
+ dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectMethod, "<init>",
+ "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
+ if (gDvm.methJavaLangReflectConstructor_init == NULL ||
+ gDvm.methJavaLangReflectField_init == NULL ||
+ gDvm.methJavaLangReflectMethod_init == NULL)
+ {
+ LOGE("Could not find reflection constructors\n");
+ return false;
+ }
+
+ gDvm.classJavaLangClassArray =
+ dvmFindArrayClass("[Ljava/lang/Class;", NULL);
+ gDvm.classJavaLangObjectArray =
+ dvmFindArrayClass("[Ljava/lang/Object;", NULL);
+ if (gDvm.classJavaLangClassArray == NULL ||
+ gDvm.classJavaLangObjectArray == NULL)
+ {
+ LOGE("Could not find class-array or object-array class\n");
+ return false;
+ }
+
+ gDvm.offJavaLangReflectAccessibleObject_flag =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectAccessibleObject, "flag",
+ "Z");
+
+ gDvm.offJavaLangReflectConstructor_slot =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor, "slot", "I");
+ gDvm.offJavaLangReflectConstructor_declClass =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor,
+ "declaringClass", "Ljava/lang/Class;");
+
+ gDvm.offJavaLangReflectField_slot =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectField, "slot", "I");
+ gDvm.offJavaLangReflectField_declClass =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectField,
+ "declaringClass", "Ljava/lang/Class;");
+
+ gDvm.offJavaLangReflectMethod_slot =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectMethod, "slot", "I");
+ gDvm.offJavaLangReflectMethod_declClass =
+ dvmFindFieldOffset(gDvm.classJavaLangReflectMethod,
+ "declaringClass", "Ljava/lang/Class;");
+
+ if (gDvm.offJavaLangReflectAccessibleObject_flag < 0 ||
+ gDvm.offJavaLangReflectConstructor_slot < 0 ||
+ gDvm.offJavaLangReflectConstructor_declClass < 0 ||
+ gDvm.offJavaLangReflectField_slot < 0 ||
+ gDvm.offJavaLangReflectField_declClass < 0 ||
+ gDvm.offJavaLangReflectMethod_slot < 0 ||
+ gDvm.offJavaLangReflectMethod_declClass < 0)
+ {
+ LOGE("Could not find reflection fields\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool find6()
+{
+ /*
+ * Standard methods we must provide in our proxy.
+ */
+ Method* methE;
+ Method* methH;
+ Method* methT;
+ Method* methF;
+ methE = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
+ "equals", "(Ljava/lang/Object;)Z");
+ methH = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
+ "hashCode", "()I");
+ methT = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
+ "toString", "()Ljava/lang/String;");
+ methF = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
+ "finalize", "()V");
+ if (methE == NULL || methH == NULL || methT == NULL || methF == NULL) {
+ LOGE("Could not find equals/hashCode/toString/finalize in Object\n");
+ return false;
+ }
+ gDvm.voffJavaLangObject_equals = methE->methodIndex;
+ gDvm.voffJavaLangObject_hashCode = methH->methodIndex;
+ gDvm.voffJavaLangObject_toString = methT->methodIndex;
+ gDvm.voffJavaLangObject_finalize = methF->methodIndex;
+
+ /*
+ * The prototype signature needs to be cloned from a method in a
+ * "real" DEX file. We declared this otherwise unused method just
+ * for this purpose.
+ */
+ ClassObject* proxyClass;
+ Method* meth;
+ proxyClass = dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
+ if (proxyClass == NULL) {
+ LOGE("No java.lang.reflect.Proxy\n");
+ return false;
+ }
+ meth = dvmFindDirectMethodByDescriptor(proxyClass, "constructorPrototype",
+ "(Ljava/lang/reflect/InvocationHandler;)V");
+ if (meth == NULL) {
+ LOGE("Could not find java.lang.Proxy.constructorPrototype()\n");
+ return false;
+ }
+ gDvm.methJavaLangReflectProxy_constructorPrototype = meth;
+
+ /*
+ * Get the offset of the "h" field in Proxy.
+ */
+ gDvm.offJavaLangReflectProxy_h = dvmFindFieldOffset(proxyClass, "h",
+ "Ljava/lang/reflect/InvocationHandler;");
+ if (gDvm.offJavaLangReflectProxy_h < 0) {
+ LOGE("Unable to find 'h' field in java.lang.Proxy\n");
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Perform Annotation setup.
+ */
+static bool find7(void)
+{
+ Method* meth;
+
+ /*
+ * Find some standard Annotation classes.
+ */
+ gDvm.classJavaLangAnnotationAnnotationArray =
+ dvmFindArrayClass("[Ljava/lang/annotation/Annotation;", NULL);
+ gDvm.classJavaLangAnnotationAnnotationArrayArray =
+ dvmFindArrayClass("[[Ljava/lang/annotation/Annotation;", NULL);
+ if (gDvm.classJavaLangAnnotationAnnotationArray == NULL ||
+ gDvm.classJavaLangAnnotationAnnotationArrayArray == NULL)
+ {
+ LOGE("Could not find Annotation-array classes\n");
+ return false;
+ }
+
+ /*
+ * VM-specific annotation classes.
+ */
+ gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory =
+ dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationFactory;");
+ gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember =
+ dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationMember;");
+ gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray =
+ dvmFindArrayClass("[Lorg/apache/harmony/lang/annotation/AnnotationMember;", NULL);
+ if (gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory == NULL ||
+ gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember == NULL ||
+ gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray == NULL)
+ {
+ LOGE("Could not find android.lang annotation classes\n");
+ return false;
+ }
+
+ meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,
+ "createAnnotation",
+ "(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)Ljava/lang/annotation/Annotation;");
+ if (meth == NULL) {
+ LOGE("Unable to find createAnnotation() in android AnnotationFactory\n");
+ return false;
+ }
+ gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation = meth;
+
+ meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
+ "<init>",
+ "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V");
+ if (meth == NULL) {
+ LOGE("Unable to find 4-arg constructor in android AnnotationMember\n");
+ return false;
+ }
+
+ gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init = meth;
+
+ return true;
+}
+
+static bool find8(void) {
+ ClassObject* clazz =
+ dvmFindClassNoInit("Ldalvik/system/VMDebug;", NULL);
+ assert(clazz != NULL);
+ gDvm.methodTrace.gcMethod =
+ dvmFindDirectMethodByDescriptor(clazz, "startGC", "()V");
+ gDvm.methodTrace.classPrepMethod =
+ dvmFindDirectMethodByDescriptor(clazz, "startClassPrep", "()V");
+ if (gDvm.methodTrace.gcMethod == NULL ||
+ gDvm.methodTrace.classPrepMethod == NULL)
+ {
+ LOGE("Unable to find startGC or startClassPrep\n");
+ return false;
+ }
+
+ return true;
+}
+
+/* (documented in header) */
+bool dvmFindRequiredClassesAndMembers(void) {
+ bool ok = true;
+
+ ok &= find1();
+ ok &= find2();
+ ok &= find3();
+ ok &= find4();
+ ok &= find5();
+ ok &= find6();
+ ok &= find7();
+ ok &= find8();
+
+ return ok;
+}
diff --git a/vm/Jni.c b/vm/Jni.c
index 0c8f4ca..b86ace8 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -236,7 +236,6 @@
/* fwd */
static const struct JNINativeInterface gNativeInterface;
-static jobject addGlobalReference(Object* obj);
#ifdef WITH_JNI_STACK_CHECK
# define COMPUTE_STACK_SUM(_self) computeStackSum(_self);
@@ -287,6 +286,8 @@
#define kGrefWaterInterval 100
#define kTrackGrefUsage true
+#define kWeakGlobalRefsTableInitialSize 16
+
#define kPinTableInitialSize 16
#define kPinTableMaxSize 1024
#define kPinComplainThreshold 10
@@ -299,8 +300,14 @@
{
#ifdef USE_INDIRECT_REF
if (!dvmInitIndirectRefTable(&gDvm.jniGlobalRefTable,
- kGlobalRefsTableInitialSize, kGlobalRefsTableMaxSize,
- kIndirectKindGlobal))
+ kGlobalRefsTableInitialSize,
+ kGlobalRefsTableMaxSize,
+ kIndirectKindGlobal))
+ return false;
+ if (!dvmInitIndirectRefTable(&gDvm.jniWeakGlobalRefTable,
+ kWeakGlobalRefsTableInitialSize,
+ kGlobalRefsTableMaxSize,
+ kIndirectKindWeakGlobal))
return false;
#else
if (!dvmInitReferenceTable(&gDvm.jniGlobalRefTable,
@@ -309,6 +316,9 @@
#endif
dvmInitMutex(&gDvm.jniGlobalRefLock);
+#ifdef USE_INDIRECT_REF
+ dvmInitMutex(&gDvm.jniWeakGlobalRefLock);
+#endif
gDvm.jniGlobalRefLoMark = 0;
gDvm.jniGlobalRefHiMark = kGrefWaterInterval * 2;
@@ -318,64 +328,6 @@
dvmInitMutex(&gDvm.jniPinRefLock);
- Method* meth;
-
- /*
- * Grab the PhantomReference constructor.
- */
- gDvm.classJavaLangRefPhantomReference =
- dvmFindSystemClassNoInit("Ljava/lang/ref/PhantomReference;");
- if (gDvm.classJavaLangRefPhantomReference == NULL) {
- LOGE("Unable to find PhantomReference class\n");
- return false;
- }
- meth= dvmFindDirectMethodByDescriptor(gDvm.classJavaLangRefPhantomReference,
- "<init>", "(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V");
- if (meth == NULL) {
- LOGE("Unable to find constructor for PhantomReference\n");
- return false;
- }
- gDvm.methJavaLangRefPhantomReference_init = meth;
-
-
- /*
- * Look up and cache pointers to some direct buffer classes, fields,
- * and methods.
- */
- ClassObject* readWriteBufferClass =
- dvmFindSystemClassNoInit("Ljava/nio/ReadWriteDirectByteBuffer;");
- ClassObject* bufferClass =
- dvmFindSystemClassNoInit("Ljava/nio/Buffer;");
-
- if (readWriteBufferClass == NULL || bufferClass == NULL) {
- LOGE("Unable to find internal direct buffer classes\n");
- return false;
- }
- gDvm.classJavaNioReadWriteDirectByteBuffer = readWriteBufferClass;
-
- meth = dvmFindDirectMethodByDescriptor(readWriteBufferClass,
- "<init>",
- "(II)V");
- if (meth == NULL) {
- LOGE("Unable to find ReadWriteDirectByteBuffer.<init>\n");
- return false;
- }
- gDvm.methJavaNioReadWriteDirectByteBuffer_init = meth;
-
- gDvm.offJavaNioBuffer_capacity =
- dvmFindFieldOffset(bufferClass, "capacity", "I");
- if (gDvm.offJavaNioBuffer_capacity < 0) {
- LOGE("Unable to find Buffer.capacity\n");
- return false;
- }
-
- gDvm.offJavaNioBuffer_effectiveDirectAddress =
- dvmFindFieldOffset(bufferClass, "effectiveDirectAddress", "I");
- if (gDvm.offJavaNioBuffer_effectiveDirectAddress < 0) {
- LOGE("Unable to find Buffer.effectiveDirectAddress\n");
- return false;
- }
-
return true;
}
@@ -540,10 +492,11 @@
break;
case kIndirectKindWeakGlobal:
{
- // TODO: implement
- LOGE("weak-global not yet supported\n");
- result = NULL;
- dvmAbort();
+ // TODO: find a way to avoid the mutex activity here
+ IndirectRefTable* pRefTable = &gDvm.jniWeakGlobalRefTable;
+ dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
+ result = dvmGetFromIndirectRefTable(pRefTable, jobj);
+ dvmUnlockMutex(&gDvm.jniWeakGlobalRefLock);
}
break;
case kIndirectKindInvalid:
@@ -811,6 +764,36 @@
return jobj;
}
+#ifdef USE_INDIRECT_REF
+static jobject addWeakGlobalReference(Object* obj)
+{
+ if (obj == NULL)
+ return NULL;
+ dvmLockMutex(&gDvm.jniWeakGlobalRefLock);
+ IndirectRefTable *table = &gDvm.jniWeakGlobalRefTable;
+ jobject jobj = 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)
+ return;
+ dvmLockMutex(&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);
+}
+#endif
+
/*
* Remove a global reference. In most cases it's the entry most recently
* added, which makes this pretty quick.
@@ -865,6 +848,7 @@
dvmUnlockMutex(&gDvm.jniGlobalRefLock);
}
+#ifndef USE_INDIRECT_REF
/*
* We create a PhantomReference that references the object, add a
* global reference to it, and then flip some bits before returning it.
@@ -917,7 +901,9 @@
* Add it to the global reference table, and mangle the pointer.
*/
phantomRef = addGlobalReference(phantomObj);
- return dvmObfuscateWeakGlobalRef(phantomRef);
+ jweak wref = dvmObfuscateWeakGlobalRef(phantomRef);
+ assert(wref == NULL || dvmIsWeakGlobalRef(wref));
+ return wref;
}
/*
@@ -928,7 +914,7 @@
{
if (wref == NULL)
return;
-
+ assert(dvmIsWeakGlobalRef(wref));
jobject phantomRef = dvmNormalizeWeakGlobalRef(wref);
deleteGlobalReference(phantomRef);
}
@@ -952,7 +938,7 @@
return dvmGetFieldObject(obj, gDvm.offJavaLangRefReference_referent);
}
-
+#endif
/*
* Objects don't currently move, so we just need to create a reference
@@ -969,7 +955,7 @@
if (!dvmAddToReferenceTable(&gDvm.jniPinRefTable, (Object*)arrayObj)) {
dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
LOGE("Failed adding to JNI pinned array ref table (%d entries)\n",
- (int) dvmReferenceTableEntries(&gDvm.jniPinRefTable));
+ (int) dvmReferenceTableEntries(&gDvm.jniPinRefTable));
dvmDumpThread(dvmThreadSelf(), false);
dvmAbort();
}
@@ -1031,12 +1017,12 @@
{
Thread* self = dvmThreadSelf();
JNIEnv* env = self->jniEnv;
- ReferenceTable* pLocalRefs = getLocalRefTable(env);
-
#ifdef USE_INDIRECT_REF
+ IndirectRefTable* pLocalRefs = getLocalRefTable(env);
dvmDumpIndirectRefTable(pLocalRefs, "JNI local");
dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
#else
+ ReferenceTable* pLocalRefs = getLocalRefTable(env);
dvmDumpReferenceTable(pLocalRefs, "JNI local");
dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
#endif
@@ -1973,7 +1959,7 @@
JNI_ENTER();
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- dvmThrowExceptionByClass(clazz, message);
+ dvmThrowException(clazz, message);
// TODO: should return failure if this didn't work (e.g. OOM)
JNI_EXIT();
@@ -2099,10 +2085,14 @@
Object* obj;
JNI_ENTER();
+#ifdef USE_INDIRECT_REF
+ obj = dvmDecodeIndirectRef(env, jobj);
+#else
if (dvmIsWeakGlobalRef(jobj))
obj = getPhantomReferent(env, (jweak) jobj);
else
obj = dvmDecodeIndirectRef(env, jobj);
+#endif
jobject retval = addGlobalReference(obj);
JNI_EXIT();
return retval;
@@ -2127,10 +2117,14 @@
Object* obj;
JNI_ENTER();
+#ifdef USE_INDIRECT_REF
+ obj = dvmDecodeIndirectRef(env, jobj);
+#else
if (dvmIsWeakGlobalRef(jobj))
obj = getPhantomReferent(env, (jweak) jobj);
else
obj = dvmDecodeIndirectRef(env, jobj);
+#endif
jobject retval = addLocalReference(env, obj);
JNI_EXIT();
return retval;
@@ -2351,7 +2345,7 @@
} else if (dvmIsInterfaceClass(clazz)) {
Method* meth = dvmFindInterfaceMethodHierByDescriptor(clazz, name, sig);
if (meth == NULL) {
- dvmThrowExceptionFmt("Ljava/lang/NoSuchMethodError;",
+ dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
"no method with name='%s' signature='%s' in interface %s",
name, sig, clazz->descriptor);
}
@@ -2372,7 +2366,7 @@
meth = NULL;
}
if (meth == NULL) {
- dvmThrowExceptionFmt("Ljava/lang/NoSuchMethodError;",
+ dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
"no method with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
} else {
@@ -2407,7 +2401,7 @@
} else {
id = (jfieldID) dvmFindInstanceFieldHier(clazz, name, sig);
if (id == NULL) {
- dvmThrowExceptionFmt("Ljava/lang/NoSuchFieldError;",
+ dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
"no field with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
}
@@ -2449,7 +2443,7 @@
id = (jmethodID) meth;
if (id == NULL) {
- dvmThrowExceptionFmt("Ljava/lang/NoSuchMethodError;",
+ dvmThrowExceptionFmt(gDvm.exNoSuchMethodError,
"no static method with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
}
@@ -2476,7 +2470,7 @@
} else {
id = (jfieldID) dvmFindStaticField(clazz, name, sig);
if (id == NULL) {
- dvmThrowExceptionFmt("Ljava/lang/NoSuchFieldError;",
+ dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
"no static field with name='%s' signature='%s' in class %s",
name, sig, clazz->descriptor);
}
@@ -3082,7 +3076,7 @@
static bool checkArrayElementBounds(ArrayObject* arrayObj, jsize index) {
assert(arrayObj != NULL);
if (index < 0 || index >= (int) arrayObj->length) {
- dvmThrowArrayIndexOutOfBoundsException(index, arrayObj->length);
+ dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, index);
return false;
}
return true;
@@ -3210,7 +3204,7 @@
static void throwArrayRegionOutOfBounds(ArrayObject* arrayObj, jsize start,
jsize len, const char* arrayIdentifier)
{
- dvmThrowExceptionFmtByClass(gDvm.exArrayIndexOutOfBoundsException,
+ dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
"%s offset=%d length=%d %s.length=%d",
arrayObj->obj.clazz->descriptor, start, len, arrayIdentifier,
arrayObj->length);
@@ -3505,10 +3499,16 @@
/*
* Create a new weak global reference.
*/
-static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj)
+static jweak NewWeakGlobalRef(JNIEnv* env, jobject jobj)
{
JNI_ENTER();
- jweak wref = createWeakGlobalRef(env, obj);
+#ifdef USE_INDIRECT_REF
+ Object *obj = dvmDecodeIndirectRef(env, jobj);
+ jweak wref = addWeakGlobalReference(obj);
+#else
+ jweak wref = createWeakGlobalRef(env, jobj);
+#endif
+ assert(wref == NULL || dvmIsWeakGlobalRef(wref));
JNI_EXIT();
return wref;
}
@@ -3519,7 +3519,11 @@
static void DeleteWeakGlobalRef(JNIEnv* env, jweak wref)
{
JNI_ENTER();
+#ifdef USE_INDIRECT_REF
+ deleteWeakGlobalReference(wref);
+#else
deleteWeakGlobalRef(env, wref);
+#endif
JNI_EXIT();
}
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index 302dcb0..a9e962b 100644
--- a/vm/JniInternal.h
+++ b/vm/JniInternal.h
@@ -225,14 +225,22 @@
* "Obfuscate" a weak global reference pointer.
*/
INLINE jweak dvmObfuscateWeakGlobalRef(jobject jobj) {
+#ifndef USE_INDIRECT_REF
return (jweak) ((u4) jobj ^ WEAK_GLOBAL_XOR);
+#else
+ return jobj;
+#endif
}
/*
* Undo the obfuscation.
*/
INLINE jobject dvmNormalizeWeakGlobalRef(jweak ref) {
+#ifndef USE_INDIRECT_REF
return (jobject) ((u4) ref ^ WEAK_GLOBAL_XOR);
+#else
+ return ref;
+#endif
}
/*
@@ -242,7 +250,11 @@
* guaranteed by 64-bit alignment of objects).
*/
INLINE bool dvmIsWeakGlobalRef(jobject jobj) {
+#ifndef USE_INDIRECT_REF
return (((u4) jobj & 0x07) == 0x07);
+#else
+ return (((u4) jobj & 0x03) == 0x03);
+#endif
}
#endif /*_DALVIK_JNIINTERNAL*/
diff --git a/vm/Profile.c b/vm/Profile.c
index 1d45715..f1acc97 100644
--- a/vm/Profile.c
+++ b/vm/Profile.c
@@ -146,20 +146,6 @@
dvmInitMutex(&gDvm.methodTrace.startStopLock);
pthread_cond_init(&gDvm.methodTrace.threadExitCond, NULL);
- ClassObject* clazz =
- dvmFindClassNoInit("Ldalvik/system/VMDebug;", NULL);
- assert(clazz != NULL);
- gDvm.methodTrace.gcMethod =
- dvmFindDirectMethodByDescriptor(clazz, "startGC", "()V");
- gDvm.methodTrace.classPrepMethod =
- dvmFindDirectMethodByDescriptor(clazz, "startClassPrep", "()V");
- if (gDvm.methodTrace.gcMethod == NULL ||
- gDvm.methodTrace.classPrepMethod == NULL)
- {
- LOGE("Unable to find startGC or startClassPrep\n");
- return false;
- }
-
assert(!dvmCheckException(dvmThreadSelf()));
/*
@@ -359,7 +345,7 @@
int err = errno;
LOGE("Unable to open trace file '%s': %s\n",
traceFileName, strerror(err));
- dvmThrowExceptionFmt("Ljava/lang/RuntimeException;",
+ dvmThrowExceptionFmt(gDvm.exRuntimeException,
"Unable to open trace file '%s': %s",
traceFileName, strerror(err));
goto fail;
@@ -636,7 +622,7 @@
int err = errno;
LOGE("trace fwrite(%d) failed: %s\n",
finalCurOffset, strerror(err));
- dvmThrowExceptionFmt("Ljava/lang/RuntimeException;",
+ dvmThrowExceptionFmt(gDvm.exRuntimeException,
"Trace data write failed: %s", strerror(err));
}
}
diff --git a/vm/RawDexFile.c b/vm/RawDexFile.c
index 5da4907..2c73481 100644
--- a/vm/RawDexFile.c
+++ b/vm/RawDexFile.c
@@ -250,11 +250,20 @@
}
/* See documentation comment in header. */
-int dvmRawDexFileOpenArray(const u1* pBytes, u4 length,
- RawDexFile** ppDexFile)
+int dvmRawDexFileOpenArray(u1* pBytes, u4 length, RawDexFile** ppRawDexFile)
{
- // TODO - should be very similar to what JarFile does.
- return -1;
+ DvmDex* pDvmDex = NULL;
+
+ if (!dvmPrepareDexInMemory(pBytes, length, &pDvmDex)) {
+ LOGD("Unable to open raw DEX from array\n");
+ return -1;
+ }
+ assert(pDvmDex != NULL);
+
+ *ppRawDexFile = (RawDexFile*) calloc(1, sizeof(RawDexFile));
+ (*ppRawDexFile)->pDvmDex = pDvmDex;
+
+ return 0;
}
/*
diff --git a/vm/RawDexFile.h b/vm/RawDexFile.h
index f15aac2..cbcb3b6 100644
--- a/vm/RawDexFile.h
+++ b/vm/RawDexFile.h
@@ -49,8 +49,7 @@
* On success, returns 0 and sets "*ppDexFile" to a newly-allocated DexFile.
* On failure, returns a meaningful error code [currently just -1].
*/
-int dvmRawDexFileOpenArray(const u1* pBytes, u4 length,
- RawDexFile** ppDexFile);
+int dvmRawDexFileOpenArray(u1* pBytes, u4 length, RawDexFile** ppDexFile);
/*
* Free a RawDexFile structure, along with any associated structures.
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.c
index 20ead16..b8d9741 100644
--- a/vm/SignalCatcher.c
+++ b/vm/SignalCatcher.c
@@ -169,11 +169,6 @@
dvmCompilerDumpStats();
#endif
- if (false) {
- dvmLockMutex(&gDvm.jniGlobalRefLock);
- dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
- dvmUnlockMutex(&gDvm.jniGlobalRefLock);
- }
if (false) dvmDumpTrackedAllocations(true);
dvmResumeAllThreads(SUSPEND_FOR_STACK_DUMP);
diff --git a/vm/Thread.c b/vm/Thread.c
index 8861dff..69d1670 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -318,92 +318,6 @@
}
/*
- * We're a little farther up now, and can load some basic classes.
- *
- * We're far enough along that we can poke at java.lang.Thread and friends,
- * but should not assume that static initializers have run (or cause them
- * to do so). That means no object allocations yet.
- */
-bool dvmThreadObjStartup(void)
-{
- /*
- * TODO: Pull this function's guts into dvmInitRequiredClassesAndMembers()
- * in Init.c
- */
-
- assert(gDvm.classJavaLangThread != NULL);
- assert(gDvm.classJavaLangThreadGroup != NULL);
- assert(gDvm.classJavaLangVMThread != NULL);
-
- /*
- * Cache field offsets. This makes things a little faster, at the
- * expense of hard-coding non-public field names into the VM.
- */
- gDvm.offJavaLangThread_vmThread =
- dvmFindFieldOffset(gDvm.classJavaLangThread,
- "vmThread", "Ljava/lang/VMThread;");
- gDvm.offJavaLangThread_group =
- dvmFindFieldOffset(gDvm.classJavaLangThread,
- "group", "Ljava/lang/ThreadGroup;");
- gDvm.offJavaLangThread_daemon =
- dvmFindFieldOffset(gDvm.classJavaLangThread, "daemon", "Z");
- gDvm.offJavaLangThread_name =
- dvmFindFieldOffset(gDvm.classJavaLangThread,
- "name", "Ljava/lang/String;");
- gDvm.offJavaLangThread_priority =
- dvmFindFieldOffset(gDvm.classJavaLangThread, "priority", "I");
-
- if (gDvm.offJavaLangThread_vmThread < 0 ||
- gDvm.offJavaLangThread_group < 0 ||
- gDvm.offJavaLangThread_daemon < 0 ||
- gDvm.offJavaLangThread_name < 0 ||
- gDvm.offJavaLangThread_priority < 0)
- {
- LOGE("Unable to find all fields in java.lang.Thread\n");
- return false;
- }
-
- gDvm.offJavaLangVMThread_thread =
- dvmFindFieldOffset(gDvm.classJavaLangVMThread,
- "thread", "Ljava/lang/Thread;");
- gDvm.offJavaLangVMThread_vmData =
- dvmFindFieldOffset(gDvm.classJavaLangVMThread, "vmData", "I");
- if (gDvm.offJavaLangVMThread_thread < 0 ||
- gDvm.offJavaLangVMThread_vmData < 0)
- {
- LOGE("Unable to find all fields in java.lang.VMThread\n");
- return false;
- }
-
- /*
- * Cache the vtable offset for "run()".
- *
- * We don't want to keep the Method* because then we won't find see
- * methods defined in subclasses.
- */
- Method* meth;
- meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThread, "run", "()V");
- if (meth == NULL) {
- LOGE("Unable to find run() in java.lang.Thread\n");
- return false;
- }
- gDvm.voffJavaLangThread_run = meth->methodIndex;
-
- /*
- * Cache vtable offsets for ThreadGroup methods.
- */
- meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThreadGroup,
- "removeThread", "(Ljava/lang/Thread;)V");
- if (meth == NULL) {
- LOGE("Unable to find removeThread(Thread) in java.lang.ThreadGroup\n");
- return false;
- }
- gDvm.voffJavaLangThreadGroup_removeThread = meth->methodIndex;
-
- return true;
-}
-
-/*
* All threads should be stopped by now. Clean up some thread globals.
*/
void dvmThreadShutdown(void)
@@ -1418,7 +1332,7 @@
char* threadName = dvmCreateCstrFromString(nameStr);
bool profilerThread = strcmp(threadName, "SamplingProfiler") == 0;
if (!profilerThread) {
- dvmThrowExceptionFmtByClass(gDvm.exIllegalStateException,
+ dvmThrowExceptionFmt(gDvm.exIllegalStateException,
"No new threads in -Xzygote mode. "
"Found thread named '%s'", threadName);
diff --git a/vm/Thread.h b/vm/Thread.h
index 4aa2663..a14e400 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -67,7 +67,6 @@
/* initialization */
bool dvmThreadStartup(void);
-bool dvmThreadObjStartup(void);
void dvmThreadShutdown(void);
void dvmSlayDaemons(void);
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index c925225..cd94a7f 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -1088,6 +1088,22 @@
return !isMarked((Object *)obj, &gDvm.gcHeap->markContext);
}
+#ifdef USE_INDIRECT_REF
+void sweepWeakJniGlobals(void)
+{
+ 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) {
+ if (entry[i] != NULL && !isMarked(entry[i], ctx)) {
+ entry[i] = NULL;
+ }
+ }
+}
+#endif
+
/*
* Process all the internal system structures that behave like
* weakly-held objects.
@@ -1096,6 +1112,9 @@
{
dvmGcDetachDeadInternedStrings(isUnmarkedObject);
dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
+#ifdef USE_INDIRECT_REF
+ sweepWeakJniGlobals();
+#endif
}
/*
diff --git a/vm/alloc/Visit.c b/vm/alloc/Visit.c
index a17eea8..a90b0f3 100644
--- a/vm/alloc/Visit.c
+++ b/vm/alloc/Visit.c
@@ -81,6 +81,24 @@
}
}
+#ifdef USE_INDIRECT_REF
+/*
+ * Visits all entries in the indirect reference table.
+ */
+static void visitIndirectRefTable(RootVisitor *visitor, IndirectRefTable *table,
+ u4 threadId, RootType type, void *arg)
+{
+ assert(visitor != NULL);
+ assert(table != NULL);
+ Object **entry = table->table;
+ int numEntries = dvmIndirectRefTableEntries(table);
+ int i;
+ for (i = 0; i < numEntries; ++i) {
+ (*visitor)(&entry[i], threadId, type, arg);
+ }
+}
+#endif
+
/*
* Visits a large heap reference table. These objects are list heads.
* As such, it is valid for table to be NULL.
@@ -192,7 +210,11 @@
(*visitor)(&thread->threadObj, threadId, ROOT_THREAD_OBJECT, arg);
(*visitor)(&thread->exception, threadId, ROOT_NATIVE_STACK, arg);
visitReferenceTable(visitor, &thread->internalLocalRefTable, threadId, ROOT_NATIVE_STACK, arg);
+#ifdef USE_INDIRECT_REF
+ visitIndirectRefTable(visitor, &thread->jniLocalRefTable, threadId, ROOT_JNI_LOCAL, arg);
+#else
visitReferenceTable(visitor, &thread->jniLocalRefTable, threadId, ROOT_JNI_LOCAL, arg);
+#endif
if (thread->jniMonitorRefTable.table != NULL) {
visitReferenceTable(visitor, &thread->jniMonitorRefTable, threadId, ROOT_JNI_MONITOR, arg);
}
@@ -231,7 +253,11 @@
visitHashTable(visitor, gDvm.literalStrings, ROOT_INTERNED_STRING, arg);
}
dvmLockMutex(&gDvm.jniGlobalRefLock);
+#ifdef USE_INDIRECT_REF
+ visitIndirectRefTable(visitor, &gDvm.jniGlobalRefTable, 0, ROOT_JNI_GLOBAL, arg);
+#else
visitReferenceTable(visitor, &gDvm.jniGlobalRefTable, 0, ROOT_JNI_GLOBAL, arg);
+#endif
dvmUnlockMutex(&gDvm.jniGlobalRefLock);
dvmLockMutex(&gDvm.jniPinRefLock);
visitReferenceTable(visitor, &gDvm.jniPinRefTable, 0, ROOT_VM_INTERNAL, arg);
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 1fff44b..1894d5d 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -3306,10 +3306,10 @@
/* nothing to do */
break;
case 3:
- dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns+2, OP_NOP);
+ dvmUpdateCodeUnit(meth, oldInsns+2, OP_NOP);
break;
case 5:
- dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns+4, OP_NOP);
+ dvmUpdateCodeUnit(meth, oldInsns+4, OP_NOP);
break;
default:
/* whoops */
@@ -3324,15 +3324,15 @@
assert(width == 4 || width == 5);
u2 newVal = (u2) ((OP_THROW_VERIFICATION_ERROR_JUMBO << 8) |
OP_DISPATCH_FF);
- dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns, newVal);
+ dvmUpdateCodeUnit(meth, oldInsns, newVal);
newVal = failure | (refType << kVerifyErrorRefTypeShift);
- dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns+3, newVal);
+ dvmUpdateCodeUnit(meth, oldInsns+3, newVal);
} else {
/* encode the opcode, with the failure code in the high byte */
assert(width == 2 || width == 3);
u2 newVal = OP_THROW_VERIFICATION_ERROR |
(failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift));
- dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns, newVal);
+ dvmUpdateCodeUnit(meth, oldInsns, newVal);
}
result = true;
diff --git a/vm/analysis/DexPrepare.c b/vm/analysis/DexPrepare.c
index eb856e8..0f82cbf 100644
--- a/vm/analysis/DexPrepare.c
+++ b/vm/analysis/DexPrepare.c
@@ -42,8 +42,8 @@
/* fwd */
-static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags,
- DexClassLookup** ppClassLookup);
+static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
+ DexClassLookup** ppClassLookup, DvmDex** ppDvmDex);
static bool loadAllClasses(DvmDex* pDvmDex);
static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify,
bool doOpt);
@@ -479,7 +479,6 @@
{
DexClassLookup* pClassLookup = NULL;
RegisterMapBuilder* pRegMapBuilder = NULL;
- u4 headerFlags = 0;
assert(gDvm.optimizing);
@@ -521,6 +520,24 @@
goto bail;
}
+ bool doVerify, doOpt;
+ if (gDvm.classVerifyMode == VERIFY_MODE_NONE) {
+ doVerify = false;
+ } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) {
+ doVerify = !gDvm.optimizingBootstrapClass;
+ } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ {
+ doVerify = true;
+ }
+
+ if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) {
+ doOpt = false;
+ } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED ||
+ gDvm.dexOptMode == OPTIMIZE_MODE_FULL) {
+ doOpt = doVerify;
+ } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ {
+ doOpt = true;
+ }
+
/*
* Rewrite the file. Byte reordering, structure realigning,
* class verification, and bytecode optimization are all performed
@@ -530,11 +547,10 @@
* In practice this would be annoying to deal with, so the file
* layout is designed so that it can always be rewritten in place.
*
- * This sets "headerFlags" and creates the class lookup table as
- * part of doing the processing.
+ * This creates the class lookup table as part of doing the processing.
*/
success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
- &headerFlags, &pClassLookup);
+ doVerify, doOpt, &pClassLookup, NULL);
if (success) {
DvmDex* pDvmDex = NULL;
@@ -656,8 +672,11 @@
optHdr.depsLength = (u4) depsLength;
optHdr.optOffset = (u4) optOffset;
optHdr.optLength = (u4) optLength;
-
- optHdr.flags = headerFlags;
+#if __BYTE_ORDER != __LITTLE_ENDIAN
+ optHdr.flags = DEX_OPT_FLAG_BIG;
+#else
+ optHdr.flags = 0;
+#endif
optHdr.checksum = optChecksum;
fsync(fd); /* ensure previous writes go before header is written */
@@ -677,52 +696,62 @@
return result;
}
+/*
+ * Prepare an in-memory DEX file.
+ *
+ * The data was presented to the VM as a byte array rather than a file.
+ * We want to do the same basic set of operations, but we can just leave
+ * them in memory instead of writing them out to a cached optimized DEX file.
+ */
+bool dvmPrepareDexInMemory(u1* addr, size_t len, DvmDex** ppDvmDex)
+{
+ DexClassLookup* pClassLookup = NULL;
+
+ /*
+ * Byte-swap, realign, verify basic DEX file structure.
+ *
+ * We could load + verify + optimize here as well, but that's probably
+ * not desirable.
+ *
+ * (The bulk-verification code is currently only setting the DEX
+ * file's "verified" flag, not updating the ClassObject. This would
+ * also need to be changed, or we will try to verify the class twice,
+ * and possibly reject it when optimized opcodes are encountered.)
+ */
+ if (!rewriteDex(addr, len, false, false, &pClassLookup, ppDvmDex)) {
+ return false;
+ }
+
+ (*ppDvmDex)->pDexFile->pClassLookup = pClassLookup;
+
+ return true;
+}
/*
* Perform in-place rewrites on a memory-mapped DEX file.
*
- * This happens in a short-lived child process, so we can go nutty with
- * loading classes and allocating memory.
+ * If this is called from a short-lived child process (dexopt), we can
+ * go nutty with loading classes and allocating memory. When it's
+ * called to prepare classes provided in a byte array, we may want to
+ * be more conservative.
+ *
+ * If "ppClassLookup" is non-NULL, a pointer to a newly-allocated
+ * DexClassLookup will be returned on success.
+ *
+ * If "ppDvmDex" is non-NULL, a newly-allocated DvmDex struct will be
+ * returned on success.
*/
-static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags,
- DexClassLookup** ppClassLookup)
+static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
+ DexClassLookup** ppClassLookup, DvmDex** ppDvmDex)
{
+ DexClassLookup* pClassLookup = NULL;
u8 prepWhen, loadWhen, verifyOptWhen;
DvmDex* pDvmDex = NULL;
- bool doVerify, doOpt;
bool result = false;
- *pHeaderFlags = 0;
-
/* if the DEX is in the wrong byte order, swap it now */
if (dexSwapAndVerify(addr, len) != 0)
goto bail;
-#if __BYTE_ORDER != __LITTLE_ENDIAN
- *pHeaderFlags |= DEX_OPT_FLAG_BIG;
-#endif
-
- if (gDvm.classVerifyMode == VERIFY_MODE_NONE) {
- doVerify = false;
- } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) {
- doVerify = !gDvm.optimizingBootstrapClass;
- } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ {
- doVerify = true;
- }
-
- if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) {
- doOpt = false;
- } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED ||
- gDvm.dexOptMode == OPTIMIZE_MODE_FULL) {
- doOpt = doVerify;
- } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ {
- doOpt = true;
- }
-
- /* TODO: decide if this is actually useful */
- if (doVerify)
- *pHeaderFlags |= DEX_FLAG_VERIFIED;
- if (doOpt)
- *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
/*
* Now that the DEX file can be read directly, create a DexFile struct
@@ -736,10 +765,14 @@
/*
* Create the class lookup table. This will eventually be appended
* to the end of the .odex.
+ *
+ * We create a temporary link from the DexFile for the benefit of
+ * class loading, below.
*/
- *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
- if (*ppClassLookup == NULL)
+ pClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
+ if (pClassLookup == NULL)
goto bail;
+ pDvmDex->pDexFile->pClassLookup = pClassLookup;
/*
* If we're not going to attempt to verify or optimize the classes,
@@ -750,9 +783,6 @@
goto bail;
}
- /* this is needed for the next part */
- pDvmDex->pDexFile->pClassLookup = *ppClassLookup;
-
prepWhen = dvmGetRelativeTimeUsec();
/*
@@ -798,8 +828,23 @@
result = true;
bail:
- /* free up storage */
- dvmDexFileFree(pDvmDex);
+ /*
+ * On success, return the pieces that the caller asked for.
+ */
+ if (ppDvmDex == NULL || !result) {
+ dvmDexFileFree(pDvmDex);
+ } else {
+ *ppDvmDex = pDvmDex;
+ }
+
+ if (ppClassLookup == NULL || !result) {
+ free(pClassLookup);
+ } else {
+ *ppClassLookup = pClassLookup;
+ }
+
+ /* break link between the two */
+ pDvmDex->pDexFile->pClassLookup = NULL;
return result;
}
@@ -854,8 +899,8 @@
* that contains Object, and only when Object comes first in the
* list, but it costs very little to do it in all cases.)
*/
- if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) {
- LOGE("ERROR: java.lang.Class does not exist!\n");
+ if (!dvmInitClass(gDvm.classJavaLangClass)) {
+ LOGE("ERROR: failed to initialize the class Class!\n");
return false;
}
@@ -1125,29 +1170,13 @@
/*
* Do the header flags match up with what we want?
*
- * This is useful because it allows us to automatically regenerate
- * a file when settings change (e.g. verification is now mandatory),
- * but can cause difficulties if the bootstrap classes we depend upon
- * were handled differently than the current options specify. We get
- * upset because they're not verified or optimized, but we're not able
- * to regenerate them because the installer won't let us.
- *
- * (This is also of limited value when !sourceAvail.)
- *
- * So, for now, we essentially ignore "expectVerify" and "expectOpt"
- * by limiting the match mask.
- *
- * The only thing we really can't handle is incorrect byte-ordering.
+ * The only thing we really can't handle is incorrect byte ordering.
*/
const u4 matchMask = DEX_OPT_FLAG_BIG;
u4 expectedFlags = 0;
#if __BYTE_ORDER != __LITTLE_ENDIAN
expectedFlags |= DEX_OPT_FLAG_BIG;
#endif
- if (expectVerify)
- expectedFlags |= DEX_FLAG_VERIFIED;
- if (expectOpt)
- expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
expectedFlags, optHdr.flags, matchMask);
diff --git a/vm/analysis/DexPrepare.h b/vm/analysis/DexPrepare.h
index a424b9c..0ee76e5 100644
--- a/vm/analysis/DexPrepare.h
+++ b/vm/analysis/DexPrepare.h
@@ -124,6 +124,11 @@
const char* fileName, u4 modWhen, u4 crc, bool isBootstrap);
/*
+ * Prepare DEX data that is only available to the VM as in-memory data.
+ */
+bool dvmPrepareDexInMemory(u1* addr, size_t len, DvmDex** ppDvmDex);
+
+/*
* Prep data structures.
*/
bool dvmCreateInlineSubsTable(void);
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.c
index ae6eebe..2bacc5b 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.c
@@ -338,16 +338,19 @@
}
/*
- * Update a 16-bit code unit in "meth".
+ * Update a 16-bit code unit in "meth". The way in which the DEX data was
+ * loaded determines how we go about the write.
*/
-static inline void updateCodeUnit(const Method* meth, u2* ptr, u2 newVal)
+void dvmUpdateCodeUnit(const Method* meth, u2* ptr, u2 newVal)
{
- if (gDvm.optimizing) {
- /* dexopt time, alter the output directly */
+ DvmDex* pDvmDex = meth->clazz->pDvmDex;
+
+ if (!pDvmDex->isMappedReadOnly) {
+ /* in-memory DEX (dexopt or byte[]), alter the output directly */
*ptr = newVal;
} else {
- /* runtime, toggle the page read/write status */
- dvmDexChangeDex2(meth->clazz->pDvmDex, ptr, newVal);
+ /* memory-mapped file, toggle the page read/write status */
+ dvmDexChangeDex2(pDvmDex, ptr, newVal);
}
}
@@ -356,7 +359,7 @@
*/
static inline void updateOpcode(const Method* meth, u2* ptr, Opcode opcode)
{
- updateCodeUnit(meth, ptr, (ptr[0] & 0xff00) | (u2) opcode);
+ dvmUpdateCodeUnit(meth, ptr, (ptr[0] & 0xff00) | (u2) opcode);
}
/*
@@ -671,7 +674,7 @@
instField->field.clazz->descriptor, instField->field.name);
} else if (quickOpc != OP_NOP) {
updateOpcode(method, insns, quickOpc);
- updateCodeUnit(method, insns+1, (u2) instField->byteOffset);
+ dvmUpdateCodeUnit(method, insns+1, (u2) instField->byteOffset);
LOGV("DexOpt: rewrote ifield access %s.%s --> %d\n",
instField->field.clazz->descriptor, instField->field.name,
instField->byteOffset);
@@ -885,7 +888,7 @@
* initial load.
*/
updateOpcode(method, insns, newOpc);
- updateCodeUnit(method, insns+1, baseMethod->methodIndex);
+ dvmUpdateCodeUnit(method, insns+1, baseMethod->methodIndex);
//LOGI("DexOpt: rewrote call to %s.%s --> %s.%s\n",
// method->clazz->descriptor, method->name,
@@ -933,7 +936,8 @@
*/
u1 origOp = insns[0] & 0xff;
if (origOp == OP_INVOKE_DIRECT) {
- updateCodeUnit(method, insns, OP_INVOKE_OBJECT_INIT_RANGE | 0x100);
+ dvmUpdateCodeUnit(method, insns,
+ OP_INVOKE_OBJECT_INIT_RANGE | 0x100);
} else {
assert(origOp == OP_INVOKE_DIRECT_RANGE);
assert((insns[0] >> 8) == 1);
@@ -1053,7 +1057,7 @@
(insns[0] & 0xff) == OP_INVOKE_STATIC ||
(insns[0] & 0xff) == OP_INVOKE_VIRTUAL);
updateOpcode(method, insns, OP_EXECUTE_INLINE);
- updateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);
+ dvmUpdateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);
//LOGI("DexOpt: execute-inline %s.%s --> %s.%s\n",
// method->clazz->descriptor, method->name,
@@ -1093,7 +1097,7 @@
(insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE ||
(insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE);
updateOpcode(method, insns, OP_EXECUTE_INLINE_RANGE);
- updateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);
+ dvmUpdateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);
//LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s\n",
// method->clazz->descriptor, method->name,
diff --git a/vm/analysis/Optimize.h b/vm/analysis/Optimize.h
index 3b3ba7e..75b6eab 100644
--- a/vm/analysis/Optimize.h
+++ b/vm/analysis/Optimize.h
@@ -26,6 +26,11 @@
void dvmOptimizeClass(ClassObject* clazz, bool essentialOnly);
/*
+ * Update a 16-bit code unit.
+ */
+void dvmUpdateCodeUnit(const Method* meth, u2* ptr, u2 newVal);
+
+/*
* Abbreviated resolution functions, for use by optimization and verification
* code.
*/
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index 9e94449..c671624 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -940,7 +940,7 @@
size = arrayData[2] | (((u4)arrayData[3]) << 16);
if (size > arrayObj->length) {
- dvmThrowArrayIndexOutOfBoundsException(size, arrayObj->length);
+ dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
return false;
}
copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
@@ -1154,43 +1154,43 @@
const int typeMask = 0xff << kVerifyErrorRefTypeShift;
VerifyError errorKind = kind & ~typeMask;
VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
- const char* exceptionName = "Ljava/lang/VerifyError;";
+ ClassObject* exceptionClass = gDvm.exVerifyError;
char* msg = NULL;
switch ((VerifyError) errorKind) {
case VERIFY_ERROR_NO_CLASS:
- exceptionName = "Ljava/lang/NoClassDefFoundError;";
+ exceptionClass = gDvm.exNoClassDefFoundError;
msg = classNameFromIndex(method, ref, refType, 0);
break;
case VERIFY_ERROR_NO_FIELD:
- exceptionName = "Ljava/lang/NoSuchFieldError;";
+ exceptionClass = gDvm.exNoSuchFieldError;
msg = fieldNameFromIndex(method, ref, refType, 0);
break;
case VERIFY_ERROR_NO_METHOD:
- exceptionName = "Ljava/lang/NoSuchMethodError;";
+ exceptionClass = gDvm.exNoSuchMethodError;
msg = methodNameFromIndex(method, ref, refType, 0);
break;
case VERIFY_ERROR_ACCESS_CLASS:
- exceptionName = "Ljava/lang/IllegalAccessError;";
+ exceptionClass = gDvm.exIllegalAccessError;
msg = classNameFromIndex(method, ref, refType,
kThrowShow_accessFromClass);
break;
case VERIFY_ERROR_ACCESS_FIELD:
- exceptionName = "Ljava/lang/IllegalAccessError;";
+ exceptionClass = gDvm.exIllegalAccessError;
msg = fieldNameFromIndex(method, ref, refType,
kThrowShow_accessFromClass);
break;
case VERIFY_ERROR_ACCESS_METHOD:
- exceptionName = "Ljava/lang/IllegalAccessError;";
+ exceptionClass = gDvm.exIllegalAccessError;
msg = methodNameFromIndex(method, ref, refType,
kThrowShow_accessFromClass);
break;
case VERIFY_ERROR_CLASS_CHANGE:
- exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
+ exceptionClass = gDvm.exIncompatibleClassChangeError;
msg = classNameFromIndex(method, ref, refType, 0);
break;
case VERIFY_ERROR_INSTANTIATION:
- exceptionName = "Ljava/lang/InstantiationError;";
+ exceptionClass = gDvm.exInstantiationError;
msg = classNameFromIndex(method, ref, refType, 0);
break;
@@ -1206,7 +1206,7 @@
/* no default clause -- want warning if enum updated */
}
- dvmThrowException(exceptionName, msg);
+ dvmThrowException(exceptionClass, msg);
free(msg);
}
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.c
index e7bfb68..84984a1 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.c
@@ -645,7 +645,7 @@
char* actualClassName = (arg != NULL)
? dvmHumanReadableDescriptor(arg->obj.clazz->descriptor)
: strdup("null");
- dvmThrowExceptionFmtByClass(gDvm.exIllegalArgumentException,
+ dvmThrowExceptionFmt(gDvm.exIllegalArgumentException,
"argument %d should have type %s, got %s",
argIndex + 1, expectedClassName, actualClassName);
free(expectedClassName);
@@ -681,7 +681,7 @@
else
argListLength = 0;
if (argListLength != (int) params->length) {
- dvmThrowExceptionFmtByClass(gDvm.exIllegalArgumentException,
+ dvmThrowExceptionFmt(gDvm.exIllegalArgumentException,
"wrong number of arguments; expected %d, got %d",
params->length, argListLength);
return NULL;
@@ -1064,7 +1064,7 @@
LOGW("Stack overflow while throwing exception\n");
dvmClearException(self);
}
- dvmThrowChainedExceptionByClass(gDvm.exStackOverflowError, NULL, excep);
+ dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep);
}
/*
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 0c6b0f4..73e8efa 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -990,14 +990,13 @@
/*
* Invalid array index. Note that our calling convention is strange; we use r1
* and r3 because those just happen to be the registers all our callers are
- * using. We shuffle them here before calling the C function.
+ * using. We move r3 before calling the C function, but r1 happens to match.
* r1: index
* r3: size
*/
common_errArrayIndex:
EXPORT_PC()
- mov r0, r1
- mov r1, r3
+ mov r0, r3
bl dvmThrowArrayIndexOutOfBoundsException
b common_exceptionThrown
diff --git a/vm/mterp/c/OP_APUT_OBJECT.c b/vm/mterp/c/OP_APUT_OBJECT.c
index f4c3326..950f18c 100644
--- a/vm/mterp/c/OP_APUT_OBJECT.c
+++ b/vm/mterp/c/OP_APUT_OBJECT.c
@@ -14,7 +14,7 @@
GOTO_exceptionThrown();
if (GET_REGISTER(vsrc2) >= arrayObj->length) {
dvmThrowArrayIndexOutOfBoundsException(
- GET_REGISTER(vsrc2), arrayObj->length);
+ arrayObj->length, GET_REGISTER(vsrc2));
GOTO_exceptionThrown();
}
obj = (Object*) GET_REGISTER(vdst);
diff --git a/vm/mterp/c/OP_NEW_INSTANCE.c b/vm/mterp/c/OP_NEW_INSTANCE.c
index e7e2952..155434f 100644
--- a/vm/mterp/c/OP_NEW_INSTANCE.c
+++ b/vm/mterp/c/OP_NEW_INSTANCE.c
@@ -32,7 +32,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
diff --git a/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c b/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
index b49adbf..2464b69 100644
--- a/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
+++ b/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
@@ -32,7 +32,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
diff --git a/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c
index 764245a..c4607ec 100644
--- a/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c
+++ b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR_JUMBO.c
@@ -1,7 +1,7 @@
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
- vsrc1 = FETCH(1);
- ref = FETCH(2) | (u4)FETCH(3) << 16; /* class/field/method ref */
+ vsrc1 = FETCH(3);
+ ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
dvmThrowVerificationError(curMethod, vsrc1, ref);
GOTO_exceptionThrown();
OP_END
diff --git a/vm/mterp/c/opcommon.c b/vm/mterp/c/opcommon.c
index 7ee07b3..fc7d9a2 100644
--- a/vm/mterp/c/opcommon.c
+++ b/vm/mterp/c/opcommon.c
@@ -453,7 +453,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -478,7 +478,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/config-x86-atom b/vm/mterp/config-x86-atom
index 18fb5cd..f99a4d2 100644
--- a/vm/mterp/config-x86-atom
+++ b/vm/mterp/config-x86-atom
@@ -61,7 +61,6 @@
#op OP_APUT_SHORT c
#op OP_APUT_WIDE c
#op OP_ARRAY_LENGTH c
-#op OP_BREAKPOINT c
#op OP_CHECK_CAST c
#op OP_CMPG_DOUBLE c
#op OP_CMPG_FLOAT c
@@ -92,7 +91,6 @@
#op OP_DOUBLE_TO_FLOAT c
#op OP_DOUBLE_TO_INT c
#op OP_DOUBLE_TO_LONG c
-#op OP_EXECUTE_INLINE_RANGE c
#op OP_EXECUTE_INLINE c
#op OP_FILL_ARRAY_DATA c
#op OP_FILLED_NEW_ARRAY_RANGE c
@@ -260,15 +258,6 @@
#op OP_UNUSED_73 c
#op OP_UNUSED_79 c
#op OP_UNUSED_7A c
-#op OP_UNUSED_E3 c
-#op OP_UNUSED_E4 c
-#op OP_UNUSED_E5 c
-#op OP_UNUSED_E6 c
-#op OP_UNUSED_E7 c
-#op OP_UNUSED_E8 c
-#op OP_UNUSED_E9 c
-#op OP_UNUSED_EA c
-#op OP_UNUSED_EB c
#op OP_UNUSED_F1 c
#op OP_UNUSED_FC c
#op OP_UNUSED_FD c
@@ -285,7 +274,10 @@
#op OP_XOR_INT c
#op OP_XOR_LONG_2ADDR c
#op OP_XOR_LONG c
+
# TODO: provide native implementations
+op OP_BREAKPOINT c
+op OP_EXECUTE_INLINE_RANGE c
op OP_IGET_VOLATILE c
op OP_IPUT_VOLATILE c
op OP_SGET_VOLATILE c
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index c42ca9d..19c152f 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -21316,14 +21316,13 @@
/*
* Invalid array index. Note that our calling convention is strange; we use r1
* and r3 because those just happen to be the registers all our callers are
- * using. We shuffle them here before calling the C function.
+ * using. We move r3 before calling the C function, but r1 happens to match.
* r1: index
* r3: size
*/
common_errArrayIndex:
EXPORT_PC()
- mov r0, r1
- mov r1, r3
+ mov r0, r3
bl dvmThrowArrayIndexOutOfBoundsException
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 627f1a4..a1977ee 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -21774,14 +21774,13 @@
/*
* Invalid array index. Note that our calling convention is strange; we use r1
* and r3 because those just happen to be the registers all our callers are
- * using. We shuffle them here before calling the C function.
+ * using. We move r3 before calling the C function, but r1 happens to match.
* r1: index
* r3: size
*/
common_errArrayIndex:
EXPORT_PC()
- mov r0, r1
- mov r1, r3
+ mov r0, r3
bl dvmThrowArrayIndexOutOfBoundsException
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index bbecc54..c7d3707 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -21254,14 +21254,13 @@
/*
* Invalid array index. Note that our calling convention is strange; we use r1
* and r3 because those just happen to be the registers all our callers are
- * using. We shuffle them here before calling the C function.
+ * using. We move r3 before calling the C function, but r1 happens to match.
* r1: index
* r3: size
*/
common_errArrayIndex:
EXPORT_PC()
- mov r0, r1
- mov r1, r3
+ mov r0, r3
bl dvmThrowArrayIndexOutOfBoundsException
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index ab58120..4756775 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -21254,14 +21254,13 @@
/*
* Invalid array index. Note that our calling convention is strange; we use r1
* and r3 because those just happen to be the registers all our callers are
- * using. We shuffle them here before calling the C function.
+ * using. We move r3 before calling the C function, but r1 happens to match.
* r1: index
* r3: size
*/
common_errArrayIndex:
EXPORT_PC()
- mov r0, r1
- mov r1, r3
+ mov r0, r3
bl dvmThrowArrayIndexOutOfBoundsException
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S
index 7a9c7a4..b92c634 100644
--- a/vm/mterp/out/InterpAsm-x86-atom.S
+++ b/vm/mterp/out/InterpAsm-x86-atom.S
@@ -295,44 +295,6 @@
jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
.endm
- .macro FGETOP_JMP2 _rFinish
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
- .endm
-
- .macro OLD_JMP_1 _count _rFinish
- movzbl (\_count*2)(rPC), \_rFinish
- shl $6, \_rFinish
- .endm
-
- .macro OLD_JMP_2 _rFinish
- addl $dvmAsmInstructionStart,\_rFinish
- .endm
-
- .macro OLD_JMP_3 _count
- addl $(\_count*2), rPC
- .endm
-
- .macro OLD_JMP_4 _rFinish
- movzbl 1(rPC), rINST
- jmp *\_rFinish
- .endm
-
- .macro OLD_JMP_A_1 _reg _rFinish
- movzbl (rPC, \_reg), \_rFinish
- shl $6, \_rFinish
- .endm
-
- .macro OLD_JMP_A_2 _rFinish
- addl $dvmAsmInstructionStart,\_rFinish
- .endm
-
- .macro OLD_JMP_A_3 _reg _rFinish
- addl \_reg, rPC
- movzbl 1(rPC, \_reg), rINST
- jmp *\_rFinish
- .endm
-
/*
* Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE
* by using a jump table. _rFinish and _reg should must be the same register for
@@ -571,6 +533,7 @@
GET_VREG rINST # rINST<- vB
SET_VREG rINST, %ecx # vA<- vB; %edx
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MOVE_FROM16: /* 0x02 */
@@ -693,6 +656,7 @@
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vB
movq %xmm0, (rFP, rINST, 4) # vA<- vB
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
@@ -836,6 +800,7 @@
SET_VREG rINST, %ecx # vA<- vB; %edx
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
@@ -1362,7 +1327,7 @@
*
* For: const/4
*
- * Description: Move the given literal value (right-sign-extended to 32
+ * Description: Move the given literal value (right-zero-extended to 32
* bits) into the specified register.
*
* Format: B|A|op (11n)
@@ -1372,12 +1337,12 @@
movl rINST, %edx # %edx<- BA
andl $15, rINST # rINST<- A
- FFETCH_ADV 1, %eax # %eax<- next i nstruction hi; fetch, advance
shl $24, %edx # %edx<- B000
- addl $2, rPC # update PC
sar $28, %edx # %edx<- right-zero-extended B
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %edx, rINST # vA<- %edx; literal
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_CONST_16: /* 0x13 */
@@ -1416,6 +1381,7 @@
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %edx rINST # vAA<- BBBB; literal
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_CONST: /* 0x14 */
@@ -1456,6 +1422,7 @@
FFETCH_ADV 3, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %ecx, rINST # vAA<- %ecx; literal
FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_CONST_HIGH16: /* 0x15 */
@@ -1537,6 +1504,7 @@
movl %edx, (rFP, rINST, 4) # vAA<- ssssBBBB
movl %ecx, 4(rFP, rINST, 4) # vAA+1<- ssssssss
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_CONST_WIDE_32: /* 0x17 */
@@ -1580,6 +1548,7 @@
movl %edx, (rFP, rINST, 4) # vAA<- BBBBBBBB
movl %ecx, 4(rFP, rINST, 4) # vAA+1<- ssssssss
FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_CONST_WIDE: /* 0x18 */
@@ -2038,10 +2007,10 @@
movl rINST, %eax # %eax<- BA
shr $4, %eax # %eax<- B
andl $15, rINST # rINST<- A
- FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance
GET_VREG %eax # %eax<- vB
- testl %eax, %eax # check for null array object
+ cmp $0, %eax # check for null array object
je common_errNullObject # handle null array object
+ FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance
movl offArrayObject_length(%eax), %eax # %eax<- array length
movl %eax, (rFP, rINST, 4) # vA<- %eax; array length
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
@@ -2395,6 +2364,7 @@
*/
movl rGLUE, %eax # %eax<- pMterpGlue
+ EXPORT_PC # export the pc
GET_VREG rINST # rINST<- vAA
cmp $0, rINST # check for null
movl offGlue_self(%eax), %ecx # %ecx<- glue->self
@@ -2440,7 +2410,7 @@
movsbl rINSTbl, %edx # %edx<- +AA
shl $1, %edx # %edx is shifted for byte offset
- js common_periodicChecks2 # do check on backwards branch
+ js common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
/* ------------------------------ */
@@ -2479,7 +2449,7 @@
FETCHs 1, %edx # %edx<- ssssAAAA (sign-extended)
shl $1, %edx # %edx is doubled to get the byte offset
- js common_periodicChecks2 # do check on backwards branch
+ js common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
/* ------------------------------ */
@@ -2521,7 +2491,7 @@
shl $16, %ecx # prepare to create +AAAAAAAA
or %ecx, %edx # %edx<- +AAAAAAAA
shl $1, %edx # %edx is doubled to get the byte offset
- jle common_periodicChecks2 # do check on backwards branch
+ jle common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
/* ------------------------------ */
@@ -2574,7 +2544,7 @@
shl $1, %eax # shift for byte offset
movl %eax, %edx # %edx<- offset
lea 8(%esp), %esp
- jle common_periodicChecks2 # do backward branch
+ jle common_periodicChecks_backwardBranch # do backward branch
jmp .LOP_PACKED_SWITCH_finish
/* ------------------------------ */
@@ -2647,7 +2617,7 @@
shl $1, %eax # shift for byte offset
movl %eax, %edx # %edx<- offset
lea 8(%esp), %esp
- jle common_periodicChecks2 # do backward branch
+ jle common_periodicChecks_backwardBranch # do backward branch
jmp .LOP_SPARSE_SWITCH_finish
@@ -2694,15 +2664,9 @@
FETCH_BB 1, %ecx # %ecx<- BB
FETCH_CC 1, %edx # %edx<- CC
-
- flds (rFP, %edx, 4)
- flds (rFP, %ecx, 4)
-
- fucompp
- fnstsw %ax
- sahf
-
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ movss (rFP, %ecx, 4), %xmm0 # %xmm0<- vBB
+ comiss (rFP, %edx, 4), %xmm0 # do comparison
ja .LOP_CMPL_FLOAT_greater
jp .LOP_CMPL_FLOAT_finalNan
jz .LOP_CMPL_FLOAT_final
@@ -2775,15 +2739,9 @@
FETCH_BB 1, %ecx # %ecx<- BB
FETCH_CC 1, %edx # %edx<- CC
-
- flds (rFP, %edx, 4)
- flds (rFP, %ecx, 4)
-
- fucompp
- fnstsw %ax
- sahf
-
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ movss (rFP, %ecx, 4), %xmm0 # %xmm0<- vBB
+ comiss (rFP, %edx, 4), %xmm0 # do comparison
ja .LOP_CMPG_FLOAT_greater
jp .LOP_CMPG_FLOAT_finalNan
jz .LOP_CMPG_FLOAT_final
@@ -2857,15 +2815,9 @@
FETCH_BB 1, %ecx # %ecx<- BB
FETCH_CC 1, %edx # %edx<- CC
-
- fldl (rFP, %edx, 4)
- fldl (rFP, %ecx, 4)
-
- fucompp
- fnstsw %ax
- sahf
-
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ movsd (rFP, %ecx, 4), %xmm0 # %xmm0<- vBB
+ comisd (rFP, %edx, 4), %xmm0 # do comparison
ja .LOP_CMPL_DOUBLE_greater
jp .LOP_CMPL_DOUBLE_finalNan
jz .LOP_CMPL_DOUBLE_final
@@ -2939,15 +2891,9 @@
FETCH_BB 1, %ecx # %ecx<- BB
FETCH_CC 1, %edx # %edx<- CC
-
- fldl (rFP, %edx, 4)
- fldl (rFP, %ecx, 4)
-
- fucompp
- fnstsw %ax
- sahf
-
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ movsd (rFP, %ecx, 4), %xmm0 # %xmm0<- vBB
+ comisd (rFP, %edx, 4), %xmm0 # do comparison
ja .LOP_CMPG_DOUBLE_greater
jp .LOP_CMPG_DOUBLE_finalNan
jz .LOP_CMPG_DOUBLE_final
@@ -3070,7 +3016,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3140,7 +3086,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3210,7 +3156,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3280,7 +3226,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3350,7 +3296,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3420,7 +3366,7 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3489,7 +3435,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3568,7 +3514,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3647,7 +3593,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3726,7 +3672,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3805,7 +3751,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -3884,7 +3830,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
@@ -4291,6 +4237,7 @@
# with one instr was not faster
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_WIDE: /* 0x45 */
@@ -4338,6 +4285,7 @@
movq offArrayObject_contents(%ecx, %edx, 8), %xmm0 # %xmm0<- vBB[vCC]
movq %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_OBJECT: /* 0x46 */
@@ -4415,6 +4363,7 @@
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_BOOLEAN: /* 0x47 */
@@ -4492,6 +4441,7 @@
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_BYTE: /* 0x48 */
@@ -4569,6 +4519,7 @@
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_CHAR: /* 0x49 */
@@ -4646,6 +4597,7 @@
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_AGET_SHORT: /* 0x4a */
@@ -4723,6 +4675,7 @@
SET_VREG %edx rINST # vAA<- %edx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT: /* 0x4b */
@@ -4776,6 +4729,7 @@
GET_VREG rINST # rINST<- vAA
movl rINST, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT_WIDE: /* 0x4c */
@@ -4823,6 +4777,7 @@
movq (rFP, rINST, 4), %xmm0 # %xmm0<- vAA
movq %xmm0, offArrayObject_contents(%ecx, %edx, 8) # vBB[vCC]<- %xmm0; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT_OBJECT: /* 0x4d */
@@ -4950,6 +4905,7 @@
movb rINSTbl, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT_BYTE: /* 0x4f */
@@ -5024,6 +4980,7 @@
movb rINSTbl, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT_CHAR: /* 0x50 */
@@ -5098,6 +5055,7 @@
movw rINSTw, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_APUT_SHORT: /* 0x51 */
@@ -5172,6 +5130,7 @@
movw rINSTw, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_IGET: /* 0x52 */
@@ -5796,26 +5755,6 @@
* limitations under the License.
*/
- /*
- * File: OP_IPUT_OBJECT.S
- */
-
-/* File: x86-atom/OP_IPUT.S */
- /* 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.
- */
-
/*
* File: OP_IPUT.S
*
@@ -5838,7 +5777,6 @@
* op vA, vB, field@CCCC
*/
-
movl rGLUE, %edx # %edx<- pMterpGlue
movl offGlue_methodClassDex(%edx), %edx # %edx<- pDvmDex
FETCH 1, %ecx # %ecx<- CCCC
@@ -5849,7 +5787,6 @@
movl rGLUE, %edx # %edx<- pMterpGlue
jmp .LOP_IPUT_OBJECT_finish
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -6674,26 +6611,6 @@
/*
* File: OP_SPUT_OBJECT.S
- */
-
-/* File: x86-atom/OP_SPUT.S */
- /* 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.
- */
-
- /*
- * File: OP_SPUT.S
*
* Code: Generic 32-bit static field "put" operation. Uses no substitutions.
*
@@ -6712,12 +6629,11 @@
movl offGlue_methodClassDex(%edx), %ecx # %ecx<- pDvmDex
FETCH 1, %eax # %eax<- BBBB
movl offDvmDex_pResFields(%ecx), %ecx # %ecx<- pResFields
- cmp $0, (%ecx, %eax, 4) # check for null ptr; resolved StaticField ptr
- movl (%ecx, %eax, 4), %ecx # %ecx<- resolved StaticField ptr
+ cmp $0, (%ecx, %eax, 4) # check for null ptr; resolved StaticField
+ movl (%ecx, %eax, 4), %ecx # %ecx<- resolved StaticField
je .LOP_SPUT_OBJECT_resolve
jmp .LOP_SPUT_OBJECT_finish
-
/* ------------------------------ */
.balign 64
.L_OP_SPUT_BOOLEAN: /* 0x6a */
@@ -7942,6 +7858,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_NOT_INT: /* 0x7c */
@@ -8009,6 +7926,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_NEG_LONG: /* 0x7d */
@@ -8212,6 +8130,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_NEG_DOUBLE: /* 0x80 */
@@ -8471,6 +8390,7 @@
SET_VREG rINST, %ecx # vA<- vB; %edx
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_LONG_TO_FLOAT: /* 0x85 */
@@ -8888,6 +8808,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_INT_TO_CHAR: /* 0x8e */
@@ -8955,6 +8876,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_INT_TO_SHORT: /* 0x8f */
@@ -9022,6 +8944,7 @@
SET_VREG %ecx, rINST # vA<- result
FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_ADD_INT: /* 0x90 */
@@ -9077,17 +9000,14 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- addl (rFP, %edx, 4), %ecx # %ecx<- vBB op vCC
+ GET_VREG %edx # %edx<- vCC
+ addl %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* ------------------------------ */
@@ -9145,17 +9065,14 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- subl (rFP, %edx, 4), %ecx # %ecx<- vBB op vCC
+ GET_VREG %edx # %edx<- vCC
+ subl %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* ------------------------------ */
@@ -9179,10 +9096,33 @@
/*
* File: OP_MUL_INT.S
+ */
+
+/* File: x86-atom/binop.S */
+ /* Copyright (C) 2008 The Android Open Source Project
*
- * Code: 32-bit multiply operation. Performs "%ecx = %ecx * %edx"
+ * 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
*
- * Description: Perform a multiplication operation on two source registers
+ * 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.
+ */
+
+ /*
+ * File: binop.S
+ *
+ * Code: Generic 32-bit binary operation. Provides an "instr" line to
+ * specify an instruction that performs "%ecx = %ecx op %edx"
+ *
+ * For: add-int, and-int, mul-int, or-int, sub-int, xor-int
+ *
+ * Description: Perform a binary operation on two source registers
* and store the result in a destination register.
*
* Format: AA|op CC|BB (23x)
@@ -9194,10 +9134,11 @@
FETCH_CC 1, %edx # %edx<- CC
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- addl $4, rPC # update PC
- imul (rFP, %edx, 4), %ecx # %ecx<- vBB * vCC
+ GET_VREG %edx # %edx<- vCC
+ imul %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -9255,29 +9196,25 @@
*/
-
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %eax # %eax<- BB
- GET_VREG %ecx # %ecx<- vCC
- testl %ecx, %ecx
+ FETCH_CC 1, %ecx # %ecx<- CC
GET_VREG %eax # %eax<- vBB
+ GET_VREG %ecx # %ecx<- vCC
+ cmp $0, %ecx # check for divide by zero
je common_errDivideByZero # handle divide by zero
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_DIV_INT_continue
+ jne .LOP_DIV_INT_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
je .LOP_DIV_INT_break
-.LOP_DIV_INT_continue:
+.LOP_DIV_INT_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if 1
- FFETCH_ADV 2 %edx
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 2 %edx
.else
- FFETCH_ADV 2 %eax
- SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 2 %eax
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .LOP_DIV_INT_break2
/* ------------------------------ */
@@ -9336,29 +9273,25 @@
*/
-
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %eax # %eax<- BB
- GET_VREG %ecx # %ecx<- vCC
- testl %ecx, %ecx
+ FETCH_CC 1, %ecx # %ecx<- CC
GET_VREG %eax # %eax<- vBB
+ GET_VREG %ecx # %ecx<- vCC
+ cmp $0, %ecx # check for divide by zero
je common_errDivideByZero # handle divide by zero
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_REM_INT_continue
+ jne .LOP_REM_INT_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
je .LOP_REM_INT_break
-.LOP_REM_INT_continue:
+.LOP_REM_INT_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if 0
- FFETCH_ADV 2 %edx
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 2 %edx
.else
- FFETCH_ADV 2 %eax
- SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 2 %eax
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .LOP_REM_INT_break2
/* ------------------------------ */
@@ -9416,17 +9349,14 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- andl (rFP, %edx, 4), %ecx # %ecx<- vBB op vCC
+ GET_VREG %edx # %edx<- vCC
+ andl %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* ------------------------------ */
@@ -9484,17 +9414,14 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- or (rFP, %edx, 4), %ecx # %ecx<- vBB op vCC
+ GET_VREG %edx # %edx<- vCC
+ or %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* ------------------------------ */
@@ -9552,17 +9479,14 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
- xor (rFP, %edx, 4), %ecx # %ecx<- vBB op vCC
+ GET_VREG %edx # %edx<- vCC
+ xor %edx, %ecx # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* ------------------------------ */
@@ -9620,15 +9544,15 @@
* Syntax: op vAA, vBB, vCC
*/
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %edx # %edx<- BB
+ FETCH_CC 1, %ecx # %ecx<- CC
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
- addl $4, rPC # update PC
- GET_VREG %ecx # %ecx<- vCC
GET_VREG %edx # %edx<- vBB
+ GET_VREG %ecx # %ecx<- vCC
sal %cl, %edx # %edx<- vBB op +CC
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -9685,15 +9609,15 @@
* Syntax: op vAA, vBB, vCC
*/
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %edx # %edx<- BB
+ FETCH_CC 1, %ecx # %ecx<- CC
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
- addl $4, rPC # update PC
- GET_VREG %ecx # %ecx<- vCC
GET_VREG %edx # %edx<- vBB
+ GET_VREG %ecx # %ecx<- vCC
sar %cl, %edx # %edx<- vBB op +CC
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -9750,15 +9674,15 @@
* Syntax: op vAA, vBB, vCC
*/
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %edx # %edx<- BB
+ FETCH_CC 1, %ecx # %ecx<- CC
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
- addl $4, rPC # update PC
- GET_VREG %ecx # %ecx<- vCC
GET_VREG %edx # %edx<- vBB
+ GET_VREG %ecx # %ecx<- vCC
shr %cl, %edx # %edx<- vBB op +CC
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -9825,6 +9749,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SUB_LONG: /* 0x9c */
@@ -9890,6 +9815,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MUL_LONG: /* 0x9d */
@@ -10145,6 +10071,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_OR_LONG: /* 0xa1 */
@@ -10210,6 +10137,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_XOR_LONG: /* 0xa2 */
@@ -10275,6 +10203,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SHL_LONG: /* 0xa3 */
@@ -10474,6 +10403,7 @@
movss %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SUB_FLOAT: /* 0xa7 */
@@ -10538,6 +10468,7 @@
movss %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MUL_FLOAT: /* 0xa8 */
@@ -10602,6 +10533,7 @@
movss %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_DIV_FLOAT: /* 0xa9 */
@@ -10757,6 +10689,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SUB_DOUBLE: /* 0xac */
@@ -10822,6 +10755,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MUL_DOUBLE: /* 0xad */
@@ -10887,6 +10821,7 @@
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_DIV_DOUBLE: /* 0xae */
@@ -11036,15 +10971,16 @@
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- addl %edx, (rFP, rINST, 4) # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ addl %edx, %ecx # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
/* ------------------------------ */
@@ -11106,15 +11042,16 @@
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- subl %edx, (rFP, rINST, 4) # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ subl %edx, %ecx # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
/* ------------------------------ */
@@ -11140,16 +11077,53 @@
* File: OP_MUL_INT_2ADDR.S
*/
+/* File: x86-atom/binop2addr.S */
+ /* 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.
+ */
+
+ /*
+ * File: binop2addr.S
+ *
+ * Code: Generic 32-bit "/2addr" binary operation. Provides an
+ * "instr" line to specify an instruction that performs
+ * "%ecx = %ecx op %edx".
+ *
+ * For: add-int/2addr, and-int/2addr, mul-int/2addr, or-int/2addr,
+ * sub-int/2addr, xor-int/2addr
+ *
+ * Description: Perform a binary operation on two sources registers
+ * and store the result in the first source register
+ *
+ * Format: B|A|op (12x)
+ *
+ * Syntax: op vA, vB
+ */
+
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
andl $15, rINST # rINST<- A
movl rINST, %ecx # %ecx<- A
FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
+ GET_VREG %edx # %edx<- vB
GET_VREG %ecx # %ecx<- vA
- imul (rFP, %edx, 4), %ecx # %ecx<- vA * vB
- addl $2, rPC # update PC
+ imul %edx, %ecx # %ecx<- vA op vB
SET_VREG %ecx, rINST # vAA<- %ecx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
+
/* ------------------------------ */
.balign 64
@@ -11208,30 +11182,28 @@
*/
movl rINST, %ecx # %ecx<- BA
- shr $4, %ecx # %ecx<- B
andl $15, rINST # rINST<- A, to be used as dest
movl rINST, %eax # %eax<- A
- GET_VREG %ecx # %edx<- vB
- testl %ecx, %ecx # check for divide by zero
+ shr $4, %ecx # %ecx<- B
GET_VREG %eax # %eax<- vA
- jz common_errDivideByZero # handle divide by zero
+ GET_VREG %ecx # %edx<- vB
+ cmp $0, %ecx # check for divide by zero
+ je common_errDivideByZero # handle divide by zero
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_DIV_INT_2ADDR_continue
- cmpl $0x80000000, %eax # handle min int special case divide error
+ jne .LOP_DIV_INT_2ADDR_noerror
+ cmpl $0x80000000,%eax # handle min int special case divide error
je .LOP_DIV_INT_2ADDR_break
-
-.LOP_DIV_INT_2ADDR_continue:
+.LOP_DIV_INT_2ADDR_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if 1
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
.else
- FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
.endif
+ jmp .LOP_DIV_INT_2ADDR_break2
+ #FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
+ #FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
@@ -11292,30 +11264,28 @@
*/
movl rINST, %ecx # %ecx<- BA
- shr $4, %ecx # %ecx<- B
andl $15, rINST # rINST<- A, to be used as dest
movl rINST, %eax # %eax<- A
- GET_VREG %ecx # %edx<- vB
- testl %ecx, %ecx # check for divide by zero
+ shr $4, %ecx # %ecx<- B
GET_VREG %eax # %eax<- vA
- jz common_errDivideByZero # handle divide by zero
+ GET_VREG %ecx # %edx<- vB
+ cmp $0, %ecx # check for divide by zero
+ je common_errDivideByZero # handle divide by zero
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_REM_INT_2ADDR_continue
- cmpl $0x80000000, %eax # handle min int special case divide error
+ jne .LOP_REM_INT_2ADDR_noerror
+ cmpl $0x80000000,%eax # handle min int special case divide error
je .LOP_REM_INT_2ADDR_break
-
-.LOP_REM_INT_2ADDR_continue:
+.LOP_REM_INT_2ADDR_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if 0
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
.else
- FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
.endif
+ jmp .LOP_REM_INT_2ADDR_break2
+ #FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
+ #FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
@@ -11378,15 +11348,16 @@
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- andl %edx, (rFP, rINST, 4) # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ andl %edx, %ecx # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
/* ------------------------------ */
@@ -11448,15 +11419,16 @@
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- or %edx, (rFP, rINST, 4) # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ or %edx, %ecx # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
/* ------------------------------ */
@@ -11518,15 +11490,16 @@
movl rINST, %edx # %edx<- BA
shr $4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- xor %edx, (rFP, rINST, 4) # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ xor %edx, %ecx # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
/* ------------------------------ */
@@ -11587,15 +11560,15 @@
movl rINST, %ecx # %ecx<- BA
shr $4, %ecx # %ecx<- B
- FFETCH_ADV 1, %eax # %ecx<- next i nstruction hi; fetch, advance
andl $15, rINST # rINST<- A
- addl $2, rPC # update PC
movl rINST, %edx # %edx<- A
+ FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vB
GET_VREG %edx # %edx<- vA
sal %cl, %edx # %edx<- vA op vB
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -11655,15 +11628,15 @@
movl rINST, %ecx # %ecx<- BA
shr $4, %ecx # %ecx<- B
- FFETCH_ADV 1, %eax # %ecx<- next i nstruction hi; fetch, advance
andl $15, rINST # rINST<- A
- addl $2, rPC # update PC
movl rINST, %edx # %edx<- A
+ FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vB
GET_VREG %edx # %edx<- vA
sar %cl, %edx # %edx<- vA op vB
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -11723,15 +11696,15 @@
movl rINST, %ecx # %ecx<- BA
shr $4, %ecx # %ecx<- B
- FFETCH_ADV 1, %eax # %ecx<- next i nstruction hi; fetch, advance
andl $15, rINST # rINST<- A
- addl $2, rPC # update PC
movl rINST, %edx # %edx<- A
+ FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vB
GET_VREG %edx # %edx<- vA
shr %cl, %edx # %edx<- vA op vB
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
@@ -11793,13 +11766,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
paddq %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -11861,13 +11833,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
psubq %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12122,13 +12093,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
pand %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12190,13 +12160,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
por %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12258,13 +12227,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
pxor %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12471,6 +12439,7 @@
movss %xmm0, (rFP, %ecx, 4) # vA<- %xmm0; result
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
@@ -12537,6 +12506,7 @@
movss %xmm0, (rFP, %ecx, 4) # vA<- %xmm0; result
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
@@ -12603,6 +12573,7 @@
movss %xmm0, (rFP, %ecx, 4) # vA<- %xmm0; result
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
@@ -12754,13 +12725,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
addsd %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12822,13 +12792,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
subsd %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -12890,13 +12859,12 @@
movl rINST, %edx # %edx<- BA
shr $4, rINST # rINST<- B
andl $15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
mulsd %xmm1, %xmm0 # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+ FINISH 1 # jump to next instruction
+
/* ------------------------------ */
.balign 64
@@ -13057,6 +13025,7 @@
SET_VREG %ecx, rINST # vA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_RSUB_INT: /* 0xd1 */
@@ -13100,6 +13069,7 @@
subl %ecx, %edx # %edx<- +CCCC sub vB
SET_VREG %edx, rINST # vA<- %edx; result
FINISH 2 # jump to next instruction
+
/* ------------------------------ */
.balign 64
.L_OP_MUL_INT_LIT16: /* 0xd2 */
@@ -13168,6 +13138,7 @@
SET_VREG %ecx, rINST # vA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_DIV_INT_LIT16: /* 0xd3 */
@@ -13228,29 +13199,24 @@
movl rINST, %eax # %eax<- BA
shr $4, %eax # %eax<- B
FETCHs 1, %ecx # %ecx<- +CCCC, sign-extended literal
- testl %ecx, %ecx # check for divide by zero
+ cmp $0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vB
je common_errDivideByZero # handle divide by zero
- addl $4, rPC # update PC
andl $15, rINST # rINST<- A
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_DIV_INT_LIT16_continue
+ jne .LOP_DIV_INT_LIT16_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
- je .LOP_DIV_INT_LIT16_break
-.LOP_DIV_INT_LIT16_continue:
+ je .LOP_DIV_INT_LIT16_break
+.LOP_DIV_INT_LIT16_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if 1
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vA<- %edx (remainder)
.endif
+ jmp .LOP_DIV_INT_LIT16_break2
@@ -13314,29 +13280,24 @@
movl rINST, %eax # %eax<- BA
shr $4, %eax # %eax<- B
FETCHs 1, %ecx # %ecx<- +CCCC, sign-extended literal
- testl %ecx, %ecx # check for divide by zero
+ cmp $0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vB
je common_errDivideByZero # handle divide by zero
- addl $4, rPC # update PC
andl $15, rINST # rINST<- A
cmpl $-1, %ecx # handle -1 special case divide error
- jnz .LOP_REM_INT_LIT16_continue
+ jne .LOP_REM_INT_LIT16_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
- je .LOP_REM_INT_LIT16_break
-.LOP_REM_INT_LIT16_continue:
+ je .LOP_REM_INT_LIT16_break
+.LOP_REM_INT_LIT16_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if 0
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vA<- %edx (remainder)
.endif
+ jmp .LOP_REM_INT_LIT16_break2
@@ -13408,6 +13369,7 @@
SET_VREG %ecx, rINST # vA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_OR_INT_LIT16: /* 0xd6 */
@@ -13476,6 +13438,7 @@
SET_VREG %ecx, rINST # vA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_XOR_INT_LIT16: /* 0xd7 */
@@ -13544,6 +13507,7 @@
SET_VREG %ecx, rINST # vA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_ADD_INT_LIT8: /* 0xd8 */
@@ -13609,6 +13573,7 @@
SET_VREG %ecx, rINST # vAA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_RSUB_INT_LIT8: /* 0xd9 */
@@ -13715,6 +13680,7 @@
SET_VREG %ecx, rINST # vAA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_DIV_INT_LIT8: /* 0xdb */
@@ -13772,30 +13738,26 @@
*/
- FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
- testl %ecx, %ecx # handle -1 special case divide error
FETCH_BB 1, %eax # %eax<- BB
- jz common_errDivideByZero # handle divide by zero
- addl $4, rPC # update PC
- cmpl $-1, %ecx
+ FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
+ cmp $0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vBB
- jnz .LOP_DIV_INT_LIT8_continue
+ je common_errDivideByZero # handle divide by zero
+
+ cmpl $-1, %ecx # handle -1 special case divide error
+ jne .LOP_DIV_INT_LIT8_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
- je .LOP_DIV_INT_LIT8_break
-.LOP_DIV_INT_LIT8_continue:
+ je .LOP_DIV_INT_LIT8_break
+.LOP_DIV_INT_LIT8_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if 1
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vAA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .LOP_DIV_INT_LIT8_break2
/* ------------------------------ */
@@ -13855,30 +13817,26 @@
*/
- FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
- testl %ecx, %ecx # handle -1 special case divide error
FETCH_BB 1, %eax # %eax<- BB
- jz common_errDivideByZero # handle divide by zero
- addl $4, rPC # update PC
- cmpl $-1, %ecx
+ FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
+ cmp $0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vBB
- jnz .LOP_REM_INT_LIT8_continue
+ je common_errDivideByZero # handle divide by zero
+
+ cmpl $-1, %ecx # handle -1 special case divide error
+ jne .LOP_REM_INT_LIT8_noerror
cmpl $0x80000000,%eax # handle min int special case divide error
- je .LOP_REM_INT_LIT8_break
-.LOP_REM_INT_LIT8_continue:
+ je .LOP_REM_INT_LIT8_break
+.LOP_REM_INT_LIT8_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if 0
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vAA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .LOP_REM_INT_LIT8_break2
/* ------------------------------ */
@@ -13946,6 +13904,7 @@
SET_VREG %ecx, rINST # vAA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_OR_INT_LIT8: /* 0xde */
@@ -14011,6 +13970,7 @@
SET_VREG %ecx, rINST # vAA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_XOR_INT_LIT8: /* 0xdf */
@@ -14076,6 +14036,7 @@
SET_VREG %ecx, rINST # vAA<- %ecx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SHL_INT_LIT8: /* 0xe0 */
@@ -14141,6 +14102,7 @@
SET_VREG %edx, rINST # vAA<- %edx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_SHR_INT_LIT8: /* 0xe1 */
@@ -14206,6 +14168,7 @@
SET_VREG %edx, rINST # vAA<- %edx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_USHR_INT_LIT8: /* 0xe2 */
@@ -14271,6 +14234,7 @@
SET_VREG %edx, rINST # vAA<- %edx; result
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+
/* ------------------------------ */
.balign 64
.L_OP_IGET_VOLATILE: /* 0xe3 */
@@ -14526,11 +14490,31 @@
/* ------------------------------ */
.balign 64
.L_OP_BREAKPOINT: /* 0xec */
-/* File: x86-atom/OP_BREAKPOINT.S */
-/* File: x86/unused.S */
- jmp common_abort
+ /* 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.
+ */
+ /*
+ * File: stub.S
+ */
+ SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer
+ pushl rGLUE # push parameter glue
+ call dvmMterp_OP_BREAKPOINT # call c-based implementation
+ lea 4(%esp), %esp
+ LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer
+ FINISH_A # jump to next instruction
/* ------------------------------ */
.balign 64
.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
@@ -14565,16 +14549,16 @@
* Syntax: op vAA, ref@BBBB
*/
- movl rGLUE, %edx # %edx<- pMterpGlue
- movl offGlue_method(%edx), %ecx # %ecx<- glue->method
- EXPORT_PC # in case an exception is thrown
- FETCH 1, %eax # %eax<- BBBB
- movl %eax, -4(%esp) # push parameter BBBB; ref
- movl rINST, -8(%esp) # push parameter AA
- movl %ecx, -12(%esp) # push parameter glue->method
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_method(%edx), %ecx # %ecx<- glue->method
+ EXPORT_PC # in case an exception is thrown
+ FETCH 1, %eax # %eax<- BBBB
+ movl %eax, -4(%esp) # push parameter BBBB; ref
+ movl rINST, -8(%esp) # push parameter AA
+ movl %ecx, -12(%esp) # push parameter glue->method
lea -12(%esp), %esp
- call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
- jmp common_exceptionThrown # failed; handle exception
+ call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
+ jmp common_exceptionThrown # failed; handle exception
/* ------------------------------ */
.balign 64
@@ -14607,14 +14591,14 @@
*
* Format:
*
- * Syntax: A, {vC, vD, vE, vF}, inline@BBBB
+ * Syntax: vAA, {vC, vD, vE, vF}, inline@BBBB
*/
FETCH 1, %ecx # %ecx<- BBBB
movl rGLUE, %eax # %eax<- MterpGlue pointer
addl $offGlue_retval, %eax # %eax<- &glue->retval
EXPORT_PC
- shr $4, rINST # rINST<- A
+ shr $4, rINST # rINST<- B
movl %eax, -8(%esp) # push parameter glue->retval
lea -24(%esp), %esp
jmp .LOP_EXECUTE_INLINE_continue
@@ -14622,8 +14606,7 @@
/* ------------------------------ */
.balign 64
.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
-/* File: x86-atom/OP_EXECUTE_INLINE_RANGE.S */
- /* Copyright (C) 2010 The Android Open Source Project
+ /* 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.
@@ -14639,28 +14622,15 @@
*/
/*
- * File: OP_EXECUTE_INLINE_RANGE.S
- *
- * Code: Executes a "native inline" instruction. Uses no substitutions.
- *
- * For: execute-inline
- *
- * Description: Executes a "native inline" instruction. This instruction
- * is generated by the optimizer.
- *
- * Format:
- *
- * Syntax: AA, {vCCCC..v(CCCC+AA-1)}, inline@BBBB
+ * File: stub.S
*/
- FETCH 1, %ecx # %ecx<- BBBB
- movl rGLUE, %eax # %eax<- MterpGlue pointer
- addl $offGlue_retval, %eax # %eax<- &glue->retval
- EXPORT_PC
- movl %eax, -8(%esp) # push parameter glue->retval
- lea -24(%esp), %esp
- jmp .LOP_EXECUTE_INLINE_RANGE_continue
-
+ SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer
+ pushl rGLUE # push parameter glue
+ call dvmMterp_OP_EXECUTE_INLINE_RANGE # call c-based implementation
+ lea 4(%esp), %esp
+ LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer
+ FINISH_A # jump to next instruction
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_OBJECT_INIT_RANGE: /* 0xf0 */
@@ -14972,26 +14942,6 @@
*/
/*
- * File: OP_IPUT_OBJECT_QUICK.S
- */
-
-/* File: x86-atom/OP_IPUT_QUICK.S */
- /* 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.
- */
-
- /*
* File: OP_IPUT_QUICK.S
* Code: Optimization for iput
*
@@ -15012,9 +14962,15 @@
FFETCH_ADV 2, %edx # %edx<- next instruction hi; fetch, advance
GET_VREG rINST # rINST<- vA
movl rINST, (%eax, %ecx) # object field<- vA
+ testl rINST, rINST # did we write a null object
+ je 1f
+ movl rGLUE, %ecx # get glue
+ movl offGlue_cardTable(%ecx), %ecx # get card table base
+ shrl $GC_CARD_SHIFT, %eax # get gc card index
+ movb %cl, (%eax, %ecx) # mark gc card in table
+1:
FGETOP_JMP 2, %edx # jump to next instruction; getop, jmp
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -24907,6 +24863,7 @@
je common_exceptionThrown # resolve failed; exception thrown
SET_VREG %eax, rINST # vAA<- %eax; pResString[BBBB]
FINISH 3 # jump to next instruction
+
/* continuation for OP_CONST_CLASS */
/*
@@ -24932,6 +24889,7 @@
je common_exceptionThrown # handle exception
SET_VREG %eax, rINST # vAA<- resolved class
FINISH 2 # jump to next instruction
+
/* continuation for OP_CHECK_CAST */
.LOP_CHECK_CAST_resolved:
@@ -25247,8 +25205,14 @@
.LOP_FILLED_NEW_ARRAY_continue:
movl offClassObject_descriptor(%eax), %eax # %eax<- arrayClass->descriptor
movzbl 1(%eax), %eax # %eax<- descriptor[1]
- cmp $'I', %eax # check if array of ints
+ cmpb $'I', %al # check if array of ints
+ je 1f
+ cmpb $'L', %al
+ je 1f
+ cmpb $'[', %al
jne .LOP_FILLED_NEW_ARRAY_notimpl # jump to not implemented
+1:
+ movl %eax, sReg0 # save type
movl rINST, -12(%esp) # push parameter length
movl %eax, -16(%esp) # push parameter descriptor[1]
movl $ALLOC_DONT_TRACK, -8(%esp) # push parameter to allocate flags
@@ -25301,6 +25265,14 @@
jns 1b # or continue at 2
.endif
2:
+ cmpb $'I', sReg0 # check for int array
+ je 3f
+ movl rGLUE, %ecx # %ecx<- MterpGlue pointer
+ movl offGlue_retval(%ecx), %eax # Object head
+ movl offGlue_cardTable(%ecx), %ecx # card table base
+ shrl $GC_CARD_SHIFT, %eax # convert to card num
+ movb %cl,(%ecx, %eax) # mark card based on object head
+3:
FINISH 3 # jump to next instruction
/*
@@ -25351,8 +25323,14 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
movl offClassObject_descriptor(%eax), %eax # %eax<- arrayClass->descriptor
movzbl 1(%eax), %eax # %eax<- descriptor[1]
- cmp $'I', %eax # check if array of ints
+ cmpb $'I', %al # check if array of ints
+ je 1f
+ cmpb $'L', %al
+ je 1f
+ cmpb $'[', %al
jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # jump to not implemented
+1:
+ movl %eax, sReg0 # save type
movl rINST, -12(%esp) # push parameter length
movl %eax, -16(%esp) # push parameter descriptor[1]
movl $ALLOC_DONT_TRACK, -8(%esp) # push parameter to allocate flags
@@ -25405,6 +25383,14 @@
jns 1b # or continue at 2
.endif
2:
+ cmpb $'I', sReg0 # check for int array
+ je 3f
+ movl rGLUE, %ecx # %ecx<- MterpGlue pointer
+ movl offGlue_retval(%ecx), %eax # Object head
+ movl offGlue_cardTable(%ecx), %ecx # card table base
+ shrl $GC_CARD_SHIFT, %eax # convert to card num
+ movb %cl,(%ecx, %eax) # mark card based on object head
+3:
FINISH 3 # jump to next instruction
/*
@@ -25507,6 +25493,7 @@
.LOP_APUT_OBJECT_finish:
movl %edx, sReg0 # save &vBB[vCC]
+ movl %eax, sReg1 # save object head
movl offObject_clazz(rINST), %edx # %edx<- obj->clazz
movl %edx, -8(%esp) # push parameter obj->clazz
movl offObject_clazz(%eax), %eax # %eax<- arrayObj->clazz
@@ -25516,10 +25503,17 @@
# call: ClassObject* elemClass, ClassObject* arrayClass)
# return: bool
lea 8(%esp), %esp
- cmp $0, %eax # check for invalid array value
+ testl %eax, %eax # check for invalid array value
je common_errArrayStore # handle invalid array value
movl sReg0, %edx # restore &vBB[vCC]
-
+ movl rINST, offArrayObject_contents(%edx)
+ movl rGLUE, %eax
+ FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
+ movl offGlue_cardTable(%eax), %eax # get card table base
+ movl sReg1, %edx # restore object head
+ shrl $GC_CARD_SHIFT, %edx # object head to card number
+ movb %al, (%eax, %edx) # mark card using object head
+ FGETOP_JMP 2, %ecx # jump to next instruction; getop, jmp
.LOP_APUT_OBJECT_skip_check:
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
movl rINST, offArrayObject_contents(%edx)
@@ -25800,10 +25794,17 @@
cmp $0, %ecx # check for null object
je common_errNullObject # handle null object
movl offInstField_byteOffset(%eax), %edx # %edx<- field offset
- FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG rINST # rINST<- vA
- movl rINST, (%edx, %ecx) # object field<- vA
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
+ movl rINST, (%edx, %ecx) # object field<- vA
+ FFETCH_ADV 2, %edx # %edx<- next instruction hi; fetch, advance
+ movl rGLUE, %eax # get glue
+ movl offGlue_cardTable(%eax), %eax # get card table base
+ testl rINST, rINST # test if we stored a null value
+ je 1f # skip card mark if null stored
+ shrl $GC_CARD_SHIFT, %ecx # set obeject head to card number
+ movb %al, (%eax, %ecx)
+1:
+ FGETOP_JMP 2, %edx # jump to next instruction; getop, jmp
/* continuation for OP_IPUT_BOOLEAN */
@@ -26138,7 +26139,17 @@
.LOP_SPUT_OBJECT_finish:
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG rINST # rINST<- vAA
+
+
movl rINST, offStaticField_value(%ecx) # field value<- vAA
+ testl rINST, rINST # stored null object ptr?
+ je 1f
+ movl rGLUE, %edx # get glue
+ movl offField_clazz(%ecx), %ecx # ecx<- field->clazz
+ movl offGlue_cardTable(%edx), %edx # get card table base
+ shrl $GC_CARD_SHIFT, %ecx # head to card number
+ movb %dl, (%edx, %ecx) # mark card
+1:
FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
/* continuation for OP_SPUT_BOOLEAN */
@@ -26342,6 +26353,7 @@
movl %eax, %ecx # %ecx<- method
jne common_invokeMethodNoRange # invoke method common code
jmp common_errNullObject # handle null object
+
/* continuation for OP_INVOKE_STATIC */
.LOP_INVOKE_STATIC_break:
@@ -26490,6 +26502,7 @@
movl %eax, %ecx # %ecx<- method
jne common_invokeMethodRange # invoke method common code
jmp common_errNullObject # handle null object
+
/* continuation for OP_INVOKE_STATIC_RANGE */
.LOP_INVOKE_STATIC_RANGE_break:
@@ -26645,22 +26658,24 @@
/* continuation for OP_DIV_INT */
.LOP_DIV_INT_break:
- FFETCH_ADV 2 %eax
.if 1
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- FGETOP_JMP 2 %eax
+.LOP_DIV_INT_break2:
+ FINISH 2 # jump to next instruction
+
/* continuation for OP_REM_INT */
.LOP_REM_INT_break:
- FFETCH_ADV 2 %eax
.if 0
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- FGETOP_JMP 2 %eax
+.LOP_REM_INT_break2:
+ FINISH 2 # jump to next instruction
+
/* continuation for OP_MUL_LONG */
/*
@@ -26728,24 +26743,28 @@
/* continuation for OP_DIV_INT_2ADDR */
.LOP_DIV_INT_2ADDR_break:
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
.if 1
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
+.LOP_DIV_INT_2ADDR_break2:
+ FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
/* continuation for OP_REM_INT_2ADDR */
.LOP_REM_INT_2ADDR_break:
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
.if 0
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
+.LOP_REM_INT_2ADDR_break2:
+ FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
/* continuation for OP_MUL_LONG_2ADDR */
/*
@@ -26779,6 +26798,7 @@
movl %edx, 4(rFP, rINST, 4) # vA<- return high
FFETCH_ADV 1, %ecx # %ecx<- next instruction hi; fetch, advance
FGETOP_JMP 1, %ecx # jump to next instruction; getop, jmp
+
/* continuation for OP_REM_LONG_2ADDR */
.LOP_REM_LONG_2ADDR_break:
movq %xmm0, -20(%esp) # push arg vA, vA+1
@@ -26789,6 +26809,7 @@
movl %edx, 4(rFP, rINST, 4) # vA<- return high
FFETCH_ADV 1, %ecx # %ecx<- next instruction hi; fetch, advance
FGETOP_JMP 1, %ecx # jump to next instruction; getop, jmp
+
/* continuation for OP_SHR_LONG_2ADDR */
.LOP_SHR_LONG_2ADDR_finish:
@@ -26813,47 +26834,49 @@
/* continuation for OP_DIV_INT_LIT16 */
.LOP_DIV_INT_LIT16_break:
- movzbl (rPC), %edx
.if 1
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+.LOP_DIV_INT_LIT16_break2:
+
+ FINISH 2 # jump to next instruction
/* continuation for OP_REM_INT_LIT16 */
.LOP_REM_INT_LIT16_break:
- movzbl (rPC), %edx
.if 0
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+.LOP_REM_INT_LIT16_break2:
+
+ FINISH 2 # jump to next instruction
/* continuation for OP_DIV_INT_LIT8 */
.LOP_DIV_INT_LIT8_break:
- movzbl (rPC), %edx
.if 1
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+
+.LOP_DIV_INT_LIT8_break2:
+ FINISH 2 # jump to next instruction
+ #FGETOP_JMP 2, %ecx # jump to next instruction; getop, jmp
/* continuation for OP_REM_INT_LIT8 */
.LOP_REM_INT_LIT8_break:
- movzbl (rPC), %edx
.if 0
movl $0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+
+.LOP_REM_INT_LIT8_break2:
+ FINISH 2 # jump to next instruction
+ #FGETOP_JMP 2, %ecx # jump to next instruction; getop, jmp
/* continuation for OP_EXECUTE_INLINE */
@@ -26903,44 +26926,6 @@
lea 24(%esp), %esp # update stack pointer
je common_exceptionThrown # handle exception
FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
-/* continuation for OP_EXECUTE_INLINE_RANGE */
-
- /*
- * Extract args, call function.
- * rINST = #of args (0-4)
- * %ecx = call index
- */
-
-.LOP_EXECUTE_INLINE_RANGE_continue:
- FETCH 2, %edx # %edx<- FEDC
- cmp $1, rINST # determine number of arguments
- jl 0f # handle zero args
- je 1f # handle one arg
- cmp $3, rINST
- jl 2f # handle two args
- je 3f # handle three args
-4:
- movl 12(rFP, %edx, 4), rINST # rINST<- vF
- movl rINST, 12(%esp) # push parameter vF
-3:
- movl 8(rFP, %edx, 4), rINST # rINST<- vE
- movl rINST, 8(%esp) # push parameter E
-2:
- movl 4(rFP, %edx, 4), rINST # rINST<- vD
- movl rINST, 4(%esp) # push parameter D
-1:
- movl (rFP, %edx, 4), %edx # rINST<- vC
- movl %edx, (%esp) # push parameter C
-0:
- shl $4, %ecx
- movl $gDvmInlineOpsTable, %eax # %eax<- address for table of inline operations
- call *(%eax, %ecx) # call function
-
- cmp $0, %eax # check boolean result of inline
- FFETCH_ADV 3, %eax # %eax<- next instruction hi; fetch, advance
- lea 24(%esp), %esp # update stack pointer
- je common_exceptionThrown # handle exception
- FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
@@ -26995,13 +26980,6 @@
*/
.macro MTERP_EXIT
- #lea 40(%ebp), %esp # correct stack pointer
- #movl 24(%ebp), %edi # restore %edi
- #movl 28(%ebp), %esi # restore %esi
- #movl 32(%ebp), %ebx # restore %ebx
- #movl 36(%ebp), %ebp # restore caller base pointer
- #ret # return
-
lea 40(%esp), %esp # correct stack pointer
movl -16(%esp), %edi # restore %edi
movl -12(%esp), %esi # restore %esi
@@ -27309,11 +27287,11 @@
.long .L_OP_SHL_INT_LIT8
.long .L_OP_SHR_INT_LIT8
.long .L_OP_USHR_INT_LIT8
-.long .L_OP_UNUSED_E3
-.long .L_OP_UNUSED_E4
-.long .L_OP_UNUSED_E5
-.long .L_OP_UNUSED_E6
-.long .L_OP_UNUSED_E7
+.long .L_OP_IGET_VOLATILE
+.long .L_OP_IPUT_VOLATILE
+.long .L_OP_SGET_VOLATILE
+.long .L_OP_SPUT_VOLATILE
+.long .L_OP_IGET_OBJECT_VOLATILE
.long .L_OP_IGET_WIDE_VOLATILE
.long .L_OP_IPUT_WIDE_VOLATILE
.long .L_OP_SGET_WIDE_VOLATILE
@@ -27334,9 +27312,9 @@
.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE
.long .L_OP_INVOKE_SUPER_QUICK
.long .L_OP_INVOKE_SUPER_QUICK_RANGE
-.long .L_OP_UNUSED_FC
-.long .L_OP_UNUSED_FD
-.long .L_OP_UNUSED_FE
+.long .L_OP_IPUT_OBJECT_VOLATILE
+.long .L_OP_SGET_OBJECT_VOLATILE
+.long .L_OP_SPUT_OBJECT_VOLATILE
.long .L_OP_DISPATCH_FF
/* File: x86-atom/footer.S */
@@ -27376,26 +27354,22 @@
movl rGLUE, %edx # %edx<- pMterpGlue
movl %ebx, -4(%esp) # save %ebx to the stack
movl offGlue_pSelfSuspendCount(%edx), %ebx # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
+4:
movl offGlue_pDebuggerActive(%edx), %eax # %eax<- pDebuggerActive
- movl (%eax), %eax # %eax<- get debuggerActive (boolean)
- and $7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
+ testl %eax, %eax
+ je 5f
+ movzbl (%eax), %eax # %eax<- get debuggerActive (boolean)
+5:
cmp $0, (%ebx) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(%edx), %ebx # %ebx<- activeProfilers (int)
- or (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
- cmp $0, %eax # check for debuggerActive
-#endif
- jne 3f # debugger or profiler active; switch interp
-#endif
+ orl (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive
movl -8(%esp), %edx # %edx<- restore %edx
+ jne 3f # debugger or profiler active; switch interp
movl -4(%esp), %ebx # %ebx<- restore %ebx
ret # return
2: # check suspended
+ EXPORT_PC
movl offGlue_self(%edx), %eax # %eax<- glue->self
movl %eax, -12(%esp) # push parameter boolean
lea -12(%esp), %esp
@@ -27404,11 +27378,12 @@
movl 4(%esp), %edx # %edx<- restore %edx
movl 8(%esp), %ebx # %ebx<- restore %ebx
lea 12(%esp), %esp
- ret # return
+ ret
3: # debugger/profiler enabled, bail out
- add -8(%esp), rPC # rPC<- pc adjustments
- movl %ecx, offGlue_entryPoint(%edx) # glue->entryPoint<- reentry type
- movl $1, %edx # switch to interp == true
+ leal (rPC, %edx, 2), rPC # adjust pc to show target
+ movl rGLUE, %ecx # %ecx<- pMterpGlue
+ movb $kInterpEntryInstr, offGlue_entryPoint(%ecx)
+ movl $1, %edx # switch interpreter
jmp common_gotoBail # bail
/*
@@ -27420,25 +27395,21 @@
* %edx is PC adjustment in bytes
*/
-common_periodicChecks2:
+common_periodicChecks_backwardBranch:
+ EXPORT_PC
movl rGLUE, %ecx # %ecx<- pMterpGlue
movl offGlue_pSelfSuspendCount(%ecx), rINST # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
- movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive
- movl (%eax), %eax # %eax<- get debuggerActive (boolean)
- and $7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
+4:
+ movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive
+ testl %eax, %eax # test for NULL pointer
+ je 5f
+ movzbl (%eax), %eax # %eax<- get debuggerActive count
+5:
cmp $0, (rINST) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(%ecx), rINST # %edx<- activeProfilers (int)
- or (rINST), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
- cmp $0, %eax # check for debuggerActive
-#endif
+ orl (rINST), %eax # %eax<- merge activeProfilers and debuggerActive
jne 3f # debugger or profiler active; switch interp
-#endif
FINISH_RB %edx, %ecx # jump to next instruction
2: # check suspended
movl offGlue_self(%ecx), %eax# %eax<- glue->self
@@ -27449,15 +27420,13 @@
# return: bool
movl rINST, %edx # %edx<- restore %edx
lea 12(%esp), %esp
- FINISH_RB %edx, %ecx # jump to next instruction
-
+ FINISH_RB %edx, %ecx
3: # debugger/profiler enabled, bail out
- add -8(%esp), rPC # rPC<- pc adjustments
- movl $kInterpEntryInstr, offGlue_entryPoint(%ecx) # glue->entryPoint<- reentry type
- movl $1, %edx # switch to interp<- true
+ leal (rPC, %edx, 2), rPC # adjust pc to show target
+ movb $kInterpEntryInstr, offGlue_entryPoint(%ecx)
+ movl $1, %edx # switch interpreter
jmp common_gotoBail # bail
-
/*
* The equivalent of "goto bail", this calls through the "bail handler".
* State registers will be saved to the "glue" area before bailing.
@@ -27675,13 +27644,13 @@
jne common_exceptionThrown # handle exception
FGETOP_JMP 3, %edx # jump to next instruction; getop, jmp
-.LstackOverflow: # %ecx=methodToCall
- movl %ecx, -4(%esp) # push parameter method to call
+.LstackOverflow:
+ movl %ecx, -4(%esp) # push method to call
movl rGLUE, %ecx # %ecx<- pMterpGlue
movl offGlue_self(%ecx), %ecx # %ecx<- glue->self
movl %ecx, -8(%esp) # push parameter self
lea -8(%esp), %esp
- call dvmHandleStackOverflow # call: (Thread* self, Method* method)
+ call dvmHandleStackOverflow # call: (Thread* self, Method *meth)
# return: void
lea 8(%esp), %esp
jmp common_exceptionThrown # handle exception
@@ -27703,22 +27672,15 @@
movl rGLUE, rINST # %ecx<- pMterpGlue
movl offGlue_pSelfSuspendCount(rINST), %edx # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
movl offGlue_pDebuggerActive(rINST), %eax # %eax<- pDebuggerActive
movl (%eax), %eax # %eax<- get debuggerActive (boolean)
and $7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
cmp $0, (%edx) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(rINST), %edx # %edx<- activeProfilers (int)
or (%edx), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
cmp $0, %eax # check for debuggerActive
-#endif
jne 3f # debugger or profiler active; switch interp
-#endif
jmp 4f
2: # check suspended
movl offGlue_self(rINST), %eax# %eax<- glue->self
@@ -27906,7 +27868,7 @@
jmp .LdeadFood
.LdeadFood:
-.word 0xdeadf00d
+.int 0xdeadf00d
/*
* Invalid array index.
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 13fffb0..e401224 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -7955,8 +7955,8 @@
movl 2(rPC),%eax # eax<- AAAAAAAA
movl offThread_methodClassDex(%ecx),%ecx# ecx<- self->methodClassDex
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
- FETCH_INST_OPCODE 4 %ecx
movl (%ecx,%eax,4),%eax # eax<- rResClasses[AAAAAAAA]
+ FETCH_INST_OPCODE 4 %ecx
testl %eax,%eax # resolved yet?
je .LOP_CONST_CLASS_JUMBO_resolve
SET_VREG %eax rINST # vBBBB<- rResClasses[AAAAAAAA]
@@ -21928,9 +21928,9 @@
common_errArrayIndex:
EXPORT_PC
movl offArrayObject_length(%eax), %eax
- movl %ecx,OUT_ARG0(%esp)
- movl %eax,OUT_ARG1(%esp)
- call dvmThrowArrayIndexOutOfBoundsException # args (index, length)
+ movl %eax,OUT_ARG0(%esp)
+ movl %ecx,OUT_ARG1(%esp)
+ call dvmThrowArrayIndexOutOfBoundsException # args (length, index)
jmp common_exceptionThrown
/*
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 632d62d..2d08590 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
@@ -1802,7 +1802,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -2169,7 +2169,7 @@
GOTO_exceptionThrown();
if (GET_REGISTER(vsrc2) >= arrayObj->length) {
dvmThrowArrayIndexOutOfBoundsException(
- GET_REGISTER(vsrc2), arrayObj->length);
+ arrayObj->length, GET_REGISTER(vsrc2));
GOTO_exceptionThrown();
}
obj = (Object*) GET_REGISTER(vdst);
@@ -3276,7 +3276,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -4351,8 +4351,8 @@
/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
- vsrc1 = FETCH(1);
- ref = FETCH(2) | (u4)FETCH(3) << 16; /* class/field/method ref */
+ vsrc1 = FETCH(3);
+ ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
dvmThrowVerificationError(curMethod, vsrc1, ref);
GOTO_exceptionThrown();
OP_END
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv5te-vfp.c
index 0e13835..e40583f 100644
--- a/vm/mterp/out/InterpC-armv5te-vfp.c
+++ b/vm/mterp/out/InterpC-armv5te-vfp.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/out/InterpC-armv5te.c b/vm/mterp/out/InterpC-armv5te.c
index 5847600..9cd0580 100644
--- a/vm/mterp/out/InterpC-armv5te.c
+++ b/vm/mterp/out/InterpC-armv5te.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/out/InterpC-armv7-a-neon.c b/vm/mterp/out/InterpC-armv7-a-neon.c
index 0e87b82..00259c1 100644
--- a/vm/mterp/out/InterpC-armv7-a-neon.c
+++ b/vm/mterp/out/InterpC-armv7-a-neon.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/out/InterpC-armv7-a.c b/vm/mterp/out/InterpC-armv7-a.c
index 92aeff1..c443bb3 100644
--- a/vm/mterp/out/InterpC-armv7-a.c
+++ b/vm/mterp/out/InterpC-armv7-a.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 090146f..edf7ec9 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -988,7 +988,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1013,7 +1013,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
@@ -2165,7 +2165,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -2532,7 +2532,7 @@
GOTO_exceptionThrown();
if (GET_REGISTER(vsrc2) >= arrayObj->length) {
dvmThrowArrayIndexOutOfBoundsException(
- GET_REGISTER(vsrc2), arrayObj->length);
+ arrayObj->length, GET_REGISTER(vsrc2));
GOTO_exceptionThrown();
}
obj = (Object*) GET_REGISTER(vdst);
@@ -3639,7 +3639,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -4714,8 +4714,8 @@
/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
- vsrc1 = FETCH(1);
- ref = FETCH(2) | (u4)FETCH(3) << 16; /* class/field/method ref */
+ vsrc1 = FETCH(3);
+ ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
dvmThrowVerificationError(curMethod, vsrc1, ref);
GOTO_exceptionThrown();
OP_END
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index e71511e..0b6ff7c 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -979,7 +979,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1004,7 +1004,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
@@ -1915,7 +1915,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -2282,7 +2282,7 @@
GOTO_exceptionThrown();
if (GET_REGISTER(vsrc2) >= arrayObj->length) {
dvmThrowArrayIndexOutOfBoundsException(
- GET_REGISTER(vsrc2), arrayObj->length);
+ arrayObj->length, GET_REGISTER(vsrc2));
GOTO_exceptionThrown();
}
obj = (Object*) GET_REGISTER(vdst);
@@ -3389,7 +3389,7 @@
* Verifier now tests for interface/abstract class.
*/
//if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
- // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+ // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
// clazz->descriptor);
// GOTO_exceptionThrown();
//}
@@ -4464,8 +4464,8 @@
/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
EXPORT_PC();
- vsrc1 = FETCH(1);
- ref = FETCH(2) | (u4)FETCH(3) << 16; /* class/field/method ref */
+ vsrc1 = FETCH(3);
+ ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
dvmThrowVerificationError(curMethod, vsrc1, ref);
GOTO_exceptionThrown();
OP_END
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
index e8013da..5d5e7a8 100644
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ b/vm/mterp/out/InterpC-x86-atom.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
@@ -1330,6 +1330,82 @@
HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
+/* File: c/OP_BREAKPOINT.c */
+HANDLE_OPCODE(OP_BREAKPOINT)
+#if (INTERP_TYPE == INTERP_DBG)
+ {
+ /*
+ * 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);
+ }
+#else
+ LOGE("Breakpoint hit in non-debug interpreter\n");
+ dvmAbort();
+#endif
+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 INTERP_TYPE == INTERP_DBG
+ if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
+ GOTO_exceptionThrown();
+#else
+ if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
+ GOTO_exceptionThrown();
+#endif
+ }
+ 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*/)
{
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 00ac495..c84b236 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -996,7 +996,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
SET_REGISTER##_regsize(vdst, \
@@ -1021,7 +1021,7 @@
GOTO_exceptionThrown(); \
if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
dvmThrowArrayIndexOutOfBoundsException( \
- GET_REGISTER(vsrc2), arrayObj->length); \
+ arrayObj->length, GET_REGISTER(vsrc2)); \
GOTO_exceptionThrown(); \
} \
ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
diff --git a/vm/mterp/x86-atom/OP_ADD_FLOAT_2ADDR.S b/vm/mterp/x86-atom/OP_ADD_FLOAT_2ADDR.S
index 7d3aa71..3d62703 100644
--- a/vm/mterp/x86-atom/OP_ADD_FLOAT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_ADD_FLOAT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_ADD_FLOAT_2ADDR.S
*/
-%include "x86-atom/binopF2addr.S" {"instr":"addss %xmm1, %xmm0"}
\ No newline at end of file
+%include "x86-atom/binopF2addr.S" {"instr":"addss %xmm1, %xmm0"}
diff --git a/vm/mterp/x86-atom/OP_ADD_INT.S b/vm/mterp/x86-atom/OP_ADD_INT.S
index 4f14bbd..a423e75 100644
--- a/vm/mterp/x86-atom/OP_ADD_INT.S
+++ b/vm/mterp/x86-atom/OP_ADD_INT.S
@@ -17,4 +17,4 @@
* File: OP_ADD_INT.S
*/
-%include "x86-atom/binop.S" {"instr":"addl (rFP, %edx, 4), %ecx"}
\ No newline at end of file
+%include "x86-atom/binop.S" {"instr":"addl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_ADD_INT_2ADDR.S b/vm/mterp/x86-atom/OP_ADD_INT_2ADDR.S
index 0bdceaa..2a91f41 100644
--- a/vm/mterp/x86-atom/OP_ADD_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_ADD_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_ADD_INT_2ADDR.S
*/
-%include "x86-atom/binop2addr.S" {"instr":"addl %edx, (rFP, rINST, 4)"}
+%include "x86-atom/binop2addr.S" {"instr":"addl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_ADD_INT_LIT16.S b/vm/mterp/x86-atom/OP_ADD_INT_LIT16.S
index dbfddcc..72479ba 100644
--- a/vm/mterp/x86-atom/OP_ADD_INT_LIT16.S
+++ b/vm/mterp/x86-atom/OP_ADD_INT_LIT16.S
@@ -17,4 +17,4 @@
* File: OP_ADD_INT_LIT16.S
*/
-%include "x86-atom/binopLit16.S" {"instr":"addl %edx, %ecx"}
\ No newline at end of file
+%include "x86-atom/binopLit16.S" {"instr":"addl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_AGET.S b/vm/mterp/x86-atom/OP_AGET.S
index 11e88d1..73a27ab 100644
--- a/vm/mterp/x86-atom/OP_AGET.S
+++ b/vm/mterp/x86-atom/OP_AGET.S
@@ -50,4 +50,4 @@
# doing this and the previous instr
# with one instr was not faster
SET_VREG %edx rINST # vAA<- %edx; value
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_AGET_BOOLEAN.S b/vm/mterp/x86-atom/OP_AGET_BOOLEAN.S
index 1579026..1d28745 100644
--- a/vm/mterp/x86-atom/OP_AGET_BOOLEAN.S
+++ b/vm/mterp/x86-atom/OP_AGET_BOOLEAN.S
@@ -17,4 +17,4 @@
* File: OP_AGET_BOOLEAN.S
*/
-%include "x86-atom/OP_AGET.S" { "mov":"zbl", "scale":"1" }
\ No newline at end of file
+%include "x86-atom/OP_AGET.S" { "mov":"zbl", "scale":"1" }
diff --git a/vm/mterp/x86-atom/OP_AGET_BYTE.S b/vm/mterp/x86-atom/OP_AGET_BYTE.S
index 98df227..60e4266 100644
--- a/vm/mterp/x86-atom/OP_AGET_BYTE.S
+++ b/vm/mterp/x86-atom/OP_AGET_BYTE.S
@@ -17,4 +17,4 @@
* File: OP_AGET_BYTE.S
*/
-%include "x86-atom/OP_AGET.S" { "mov":"sbl", "scale":"1" }
\ No newline at end of file
+%include "x86-atom/OP_AGET.S" { "mov":"sbl", "scale":"1" }
diff --git a/vm/mterp/x86-atom/OP_AGET_CHAR.S b/vm/mterp/x86-atom/OP_AGET_CHAR.S
index 3ee5f9f..114d02d 100644
--- a/vm/mterp/x86-atom/OP_AGET_CHAR.S
+++ b/vm/mterp/x86-atom/OP_AGET_CHAR.S
@@ -17,4 +17,4 @@
* File: OP_AGET_CHAR.S
*/
-%include "x86-atom/OP_AGET.S" { "mov":"zwl", "scale":"2" }
\ No newline at end of file
+%include "x86-atom/OP_AGET.S" { "mov":"zwl", "scale":"2" }
diff --git a/vm/mterp/x86-atom/OP_AGET_SHORT.S b/vm/mterp/x86-atom/OP_AGET_SHORT.S
index dd05637..3ddb9b9 100644
--- a/vm/mterp/x86-atom/OP_AGET_SHORT.S
+++ b/vm/mterp/x86-atom/OP_AGET_SHORT.S
@@ -17,4 +17,4 @@
* File: OP_AGET_SHORT.S
*/
-%include "x86-atom/OP_AGET.S" { "mov":"swl", "scale":"2" }
\ No newline at end of file
+%include "x86-atom/OP_AGET.S" { "mov":"swl", "scale":"2" }
diff --git a/vm/mterp/x86-atom/OP_AGET_WIDE.S b/vm/mterp/x86-atom/OP_AGET_WIDE.S
index 413ea1e..db5a930 100644
--- a/vm/mterp/x86-atom/OP_AGET_WIDE.S
+++ b/vm/mterp/x86-atom/OP_AGET_WIDE.S
@@ -40,4 +40,4 @@
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
movq offArrayObject_contents(%ecx, %edx, 8), %xmm0 # %xmm0<- vBB[vCC]
movq %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; value
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_AND_INT.S b/vm/mterp/x86-atom/OP_AND_INT.S
index 2f84b34..10d223b 100644
--- a/vm/mterp/x86-atom/OP_AND_INT.S
+++ b/vm/mterp/x86-atom/OP_AND_INT.S
@@ -17,4 +17,4 @@
* File: OP_AND_INT.S
*/
-%include "x86-atom/binop.S" {"instr":"andl (rFP, %edx, 4), %ecx"}
+%include "x86-atom/binop.S" {"instr":"andl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_AND_INT_2ADDR.S b/vm/mterp/x86-atom/OP_AND_INT_2ADDR.S
index bd3ccf5..dcbd531 100644
--- a/vm/mterp/x86-atom/OP_AND_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_AND_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_AND_INT_2ADDR.S
*/
-%include "x86-atom/binop2addr.S" {"instr":"andl %edx, (rFP, rINST, 4)"}
\ No newline at end of file
+%include "x86-atom/binop2addr.S" {"instr":"andl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_AND_INT_LIT16.S b/vm/mterp/x86-atom/OP_AND_INT_LIT16.S
index 6935ebd..7e6493d 100644
--- a/vm/mterp/x86-atom/OP_AND_INT_LIT16.S
+++ b/vm/mterp/x86-atom/OP_AND_INT_LIT16.S
@@ -17,4 +17,4 @@
* File: OP_AND_INT_LIT16.S
*/
-%include "x86-atom/binopLit16.S" {"instr":"andl %edx, %ecx"}
\ No newline at end of file
+%include "x86-atom/binopLit16.S" {"instr":"andl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_APUT.S b/vm/mterp/x86-atom/OP_APUT.S
index e46294b..93b3866 100644
--- a/vm/mterp/x86-atom/OP_APUT.S
+++ b/vm/mterp/x86-atom/OP_APUT.S
@@ -47,4 +47,4 @@
lea (%ecx, %edx, $scale), %ecx # %ecx<- &vBB[vCC]
GET_VREG rINST # rINST<- vAA
mov$mov $value, offArrayObject_contents(%ecx) # vBB[vCC]<- rINSTx; value
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_APUT_BYTE.S b/vm/mterp/x86-atom/OP_APUT_BYTE.S
index 8d3c650..29cb708 100644
--- a/vm/mterp/x86-atom/OP_APUT_BYTE.S
+++ b/vm/mterp/x86-atom/OP_APUT_BYTE.S
@@ -17,4 +17,4 @@
* File: OP_APUT_BYTE.S
*/
-%include "x86-atom/OP_APUT.S" { "mov":"b", "scale":"1", "value":"rINSTbl" }
\ No newline at end of file
+%include "x86-atom/OP_APUT.S" { "mov":"b", "scale":"1", "value":"rINSTbl" }
diff --git a/vm/mterp/x86-atom/OP_APUT_CHAR.S b/vm/mterp/x86-atom/OP_APUT_CHAR.S
index 9aa2067..d43e540 100644
--- a/vm/mterp/x86-atom/OP_APUT_CHAR.S
+++ b/vm/mterp/x86-atom/OP_APUT_CHAR.S
@@ -17,4 +17,4 @@
* File: OP_APUT_CHAR.S
*/
-%include "x86-atom/OP_APUT.S" { "mov":"w", "scale":"2", "value":"rINSTw" }
\ No newline at end of file
+%include "x86-atom/OP_APUT.S" { "mov":"w", "scale":"2", "value":"rINSTw" }
diff --git a/vm/mterp/x86-atom/OP_APUT_OBJECT.S b/vm/mterp/x86-atom/OP_APUT_OBJECT.S
index 8d71400..0e23d71 100644
--- a/vm/mterp/x86-atom/OP_APUT_OBJECT.S
+++ b/vm/mterp/x86-atom/OP_APUT_OBJECT.S
@@ -50,6 +50,7 @@
.L${opcode}_finish:
movl %edx, sReg0 # save &vBB[vCC]
+ movl %eax, sReg1 # save object head
movl offObject_clazz(rINST), %edx # %edx<- obj->clazz
movl %edx, -8(%esp) # push parameter obj->clazz
movl offObject_clazz(%eax), %eax # %eax<- arrayObj->clazz
@@ -59,10 +60,17 @@
# call: ClassObject* elemClass, ClassObject* arrayClass)
# return: bool
lea 8(%esp), %esp
- cmp $$0, %eax # check for invalid array value
+ testl %eax, %eax # check for invalid array value
je common_errArrayStore # handle invalid array value
movl sReg0, %edx # restore &vBB[vCC]
-
+ movl rINST, offArrayObject_contents(%edx)
+ movl rGLUE, %eax
+ FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
+ movl offGlue_cardTable(%eax), %eax # get card table base
+ movl sReg1, %edx # restore object head
+ shrl $$GC_CARD_SHIFT, %edx # object head to card number
+ movb %al, (%eax, %edx) # mark card using object head
+ FGETOP_JMP 2, %ecx # jump to next instruction; getop, jmp
.L${opcode}_skip_check:
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
movl rINST, offArrayObject_contents(%edx)
diff --git a/vm/mterp/x86-atom/OP_APUT_SHORT.S b/vm/mterp/x86-atom/OP_APUT_SHORT.S
index b6cbc98..daef0d8 100644
--- a/vm/mterp/x86-atom/OP_APUT_SHORT.S
+++ b/vm/mterp/x86-atom/OP_APUT_SHORT.S
@@ -17,4 +17,4 @@
* File: OP_APUT_SHORT.S
*/
-%include "x86-atom/OP_APUT.S" { "mov":"w", "scale":"2", "value":"rINSTw" }
\ No newline at end of file
+%include "x86-atom/OP_APUT.S" { "mov":"w", "scale":"2", "value":"rINSTw" }
diff --git a/vm/mterp/x86-atom/OP_APUT_WIDE.S b/vm/mterp/x86-atom/OP_APUT_WIDE.S
index dceb67b..b1b9e6a 100644
--- a/vm/mterp/x86-atom/OP_APUT_WIDE.S
+++ b/vm/mterp/x86-atom/OP_APUT_WIDE.S
@@ -40,4 +40,4 @@
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm0 # %xmm0<- vAA
movq %xmm0, offArrayObject_contents(%ecx, %edx, 8) # vBB[vCC]<- %xmm0; value
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_ARRAY_LENGTH.S b/vm/mterp/x86-atom/OP_ARRAY_LENGTH.S
index 16427f2..485f815 100644
--- a/vm/mterp/x86-atom/OP_ARRAY_LENGTH.S
+++ b/vm/mterp/x86-atom/OP_ARRAY_LENGTH.S
@@ -31,10 +31,10 @@
movl rINST, %eax # %eax<- BA
shr $$4, %eax # %eax<- B
andl $$15, rINST # rINST<- A
- FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance
GET_VREG %eax # %eax<- vB
- testl %eax, %eax # check for null array object
+ cmp $$0, %eax # check for null array object
je common_errNullObject # handle null array object
+ FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance
movl offArrayObject_length(%eax), %eax # %eax<- array length
movl %eax, (rFP, rINST, 4) # vA<- %eax; array length
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_BREAKPOINT.S b/vm/mterp/x86-atom/OP_BREAKPOINT.S
index 31d98c1..e69de29 100644
--- a/vm/mterp/x86-atom/OP_BREAKPOINT.S
+++ b/vm/mterp/x86-atom/OP_BREAKPOINT.S
@@ -1 +0,0 @@
-%include "x86/unused.S"
diff --git a/vm/mterp/x86-atom/OP_CMPG_DOUBLE.S b/vm/mterp/x86-atom/OP_CMPG_DOUBLE.S
index 7008394..87f8a3b 100644
--- a/vm/mterp/x86-atom/OP_CMPG_DOUBLE.S
+++ b/vm/mterp/x86-atom/OP_CMPG_DOUBLE.S
@@ -17,4 +17,4 @@
* File: OP_CMPG_DOUBLE.S
*/
-%include "x86-atom/OP_CMPL_FLOAT.S" { "nan":"$0x1", "sod":"l"}
+%include "x86-atom/OP_CMPL_FLOAT.S" { "nan":"$0x1", "sod":"d"}
diff --git a/vm/mterp/x86-atom/OP_CMPL_DOUBLE.S b/vm/mterp/x86-atom/OP_CMPL_DOUBLE.S
index 010b266..2a603a4 100644
--- a/vm/mterp/x86-atom/OP_CMPL_DOUBLE.S
+++ b/vm/mterp/x86-atom/OP_CMPL_DOUBLE.S
@@ -17,4 +17,4 @@
* File: OP_CMPL_DOUBLE.S
*/
-%include "x86-atom/OP_CMPL_FLOAT.S" { "sod":"l" }
+%include "x86-atom/OP_CMPL_FLOAT.S" { "sod":"d" }
diff --git a/vm/mterp/x86-atom/OP_CMPL_FLOAT.S b/vm/mterp/x86-atom/OP_CMPL_FLOAT.S
index 2a95e89..5cb3ec7 100644
--- a/vm/mterp/x86-atom/OP_CMPL_FLOAT.S
+++ b/vm/mterp/x86-atom/OP_CMPL_FLOAT.S
@@ -38,15 +38,9 @@
FETCH_BB 1, %ecx # %ecx<- BB
FETCH_CC 1, %edx # %edx<- CC
-
- fld$sod (rFP, %edx, 4)
- fld$sod (rFP, %ecx, 4)
-
- fucompp
- fnstsw %ax
- sahf
-
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ movs$sod (rFP, %ecx, 4), %xmm0 # %xmm0<- vBB
+ comis$sod (rFP, %edx, 4), %xmm0 # do comparison
ja .L${opcode}_greater
jp .L${opcode}_finalNan
jz .L${opcode}_final
diff --git a/vm/mterp/x86-atom/OP_CONST.S b/vm/mterp/x86-atom/OP_CONST.S
index 94fe963..7ff4c23 100644
--- a/vm/mterp/x86-atom/OP_CONST.S
+++ b/vm/mterp/x86-atom/OP_CONST.S
@@ -33,4 +33,4 @@
or %edx, %ecx # %ecx<- #+BBBBBBBB
FFETCH_ADV 3, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %ecx, rINST # vAA<- %ecx; literal
- FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_CONST_16.S b/vm/mterp/x86-atom/OP_CONST_16.S
index 13e1cb3..f340696 100644
--- a/vm/mterp/x86-atom/OP_CONST_16.S
+++ b/vm/mterp/x86-atom/OP_CONST_16.S
@@ -31,4 +31,4 @@
FETCHs 1, %edx # %edx<- BBBB
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %edx rINST # vAA<- BBBB; literal
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_CONST_4.S b/vm/mterp/x86-atom/OP_CONST_4.S
index d99f151..5396d72 100644
--- a/vm/mterp/x86-atom/OP_CONST_4.S
+++ b/vm/mterp/x86-atom/OP_CONST_4.S
@@ -20,7 +20,7 @@
*
* For: const/4
*
- * Description: Move the given literal value (right-sign-extended to 32
+ * Description: Move the given literal value (right-zero-extended to 32
* bits) into the specified register.
*
* Format: B|A|op (11n)
@@ -30,9 +30,8 @@
movl rINST, %edx # %edx<- BA
andl $$15, rINST # rINST<- A
- FFETCH_ADV 1, %eax # %eax<- next i nstruction hi; fetch, advance
shl $$24, %edx # %edx<- B000
- addl $$2, rPC # update PC
sar $$28, %edx # %edx<- right-zero-extended B
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
SET_VREG %edx, rINST # vA<- %edx; literal
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_CONST_CLASS.S b/vm/mterp/x86-atom/OP_CONST_CLASS.S
index 9000e11..bc6657c 100644
--- a/vm/mterp/x86-atom/OP_CONST_CLASS.S
+++ b/vm/mterp/x86-atom/OP_CONST_CLASS.S
@@ -64,4 +64,4 @@
cmp $$0, %eax # check for null pointer
je common_exceptionThrown # handle exception
SET_VREG %eax, rINST # vAA<- resolved class
- FINISH 2 # jump to next instruction
\ No newline at end of file
+ FINISH 2 # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_CONST_STRING_JUMBO.S b/vm/mterp/x86-atom/OP_CONST_STRING_JUMBO.S
index 54e5ea7..09d045d 100644
--- a/vm/mterp/x86-atom/OP_CONST_STRING_JUMBO.S
+++ b/vm/mterp/x86-atom/OP_CONST_STRING_JUMBO.S
@@ -63,4 +63,4 @@
cmp $$0, %eax # check if resolved string failed
je common_exceptionThrown # resolve failed; exception thrown
SET_VREG %eax, rINST # vAA<- %eax; pResString[BBBB]
- FINISH 3 # jump to next instruction
\ No newline at end of file
+ FINISH 3 # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_CONST_WIDE_16.S b/vm/mterp/x86-atom/OP_CONST_WIDE_16.S
index e2df8f2..c980f10 100644
--- a/vm/mterp/x86-atom/OP_CONST_WIDE_16.S
+++ b/vm/mterp/x86-atom/OP_CONST_WIDE_16.S
@@ -34,4 +34,4 @@
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
movl %edx, (rFP, rINST, 4) # vAA<- ssssBBBB
movl %ecx, 4(rFP, rINST, 4) # vAA+1<- ssssssss
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_CONST_WIDE_32.S b/vm/mterp/x86-atom/OP_CONST_WIDE_32.S
index 333e991..92f8450 100644
--- a/vm/mterp/x86-atom/OP_CONST_WIDE_32.S
+++ b/vm/mterp/x86-atom/OP_CONST_WIDE_32.S
@@ -36,4 +36,4 @@
FFETCH_ADV 3, %eax # %eax<- next instruction hi; fetch, advance
movl %edx, (rFP, rINST, 4) # vAA<- BBBBBBBB
movl %ecx, 4(rFP, rINST, 4) # vAA+1<- ssssssss
- FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_EXECUTE_INLINE.S b/vm/mterp/x86-atom/OP_EXECUTE_INLINE.S
index 5309c26..4f01cef 100644
--- a/vm/mterp/x86-atom/OP_EXECUTE_INLINE.S
+++ b/vm/mterp/x86-atom/OP_EXECUTE_INLINE.S
@@ -25,14 +25,14 @@
*
* Format:
*
- * Syntax: A, {vC, vD, vE, vF}, inline@BBBB
+ * Syntax: vAA, {vC, vD, vE, vF}, inline@BBBB
*/
FETCH 1, %ecx # %ecx<- BBBB
movl rGLUE, %eax # %eax<- MterpGlue pointer
addl $$offGlue_retval, %eax # %eax<- &glue->retval
EXPORT_PC
- shr $$4, rINST # rINST<- A
+ shr $$4, rINST # rINST<- B
movl %eax, -8(%esp) # push parameter glue->retval
lea -24(%esp), %esp
jmp .L${opcode}_continue
@@ -83,4 +83,4 @@
FFETCH_ADV 3, %eax # %eax<- next instruction hi; fetch, advance
lea 24(%esp), %esp # update stack pointer
je common_exceptionThrown # handle exception
- FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_FILLED_NEW_ARRAY.S b/vm/mterp/x86-atom/OP_FILLED_NEW_ARRAY.S
index c6236d7..f804f3e 100644
--- a/vm/mterp/x86-atom/OP_FILLED_NEW_ARRAY.S
+++ b/vm/mterp/x86-atom/OP_FILLED_NEW_ARRAY.S
@@ -80,8 +80,14 @@
.L${opcode}_continue:
movl offClassObject_descriptor(%eax), %eax # %eax<- arrayClass->descriptor
movzbl 1(%eax), %eax # %eax<- descriptor[1]
- cmp $$'I', %eax # check if array of ints
+ cmpb $$'I', %al # check if array of ints
+ je 1f
+ cmpb $$'L', %al
+ je 1f
+ cmpb $$'[', %al
jne .L${opcode}_notimpl # jump to not implemented
+1:
+ movl %eax, sReg0 # save type
movl rINST, -12(%esp) # push parameter length
movl %eax, -16(%esp) # push parameter descriptor[1]
movl $$ALLOC_DONT_TRACK, -8(%esp) # push parameter to allocate flags
@@ -134,6 +140,14 @@
jns 1b # or continue at 2
.endif
2:
+ cmpb $$'I', sReg0 # check for int array
+ je 3f
+ movl rGLUE, %ecx # %ecx<- MterpGlue pointer
+ movl offGlue_retval(%ecx), %eax # Object head
+ movl offGlue_cardTable(%ecx), %ecx # card table base
+ shrl $$GC_CARD_SHIFT, %eax # convert to card num
+ movb %cl,(%ecx, %eax) # mark card based on object head
+3:
FINISH 3 # jump to next instruction
/*
diff --git a/vm/mterp/x86-atom/OP_GOTO.S b/vm/mterp/x86-atom/OP_GOTO.S
index 12d847e..7bd9956 100644
--- a/vm/mterp/x86-atom/OP_GOTO.S
+++ b/vm/mterp/x86-atom/OP_GOTO.S
@@ -32,5 +32,5 @@
movsbl rINSTbl, %edx # %edx<- +AA
shl $$1, %edx # %edx is shifted for byte offset
- js common_periodicChecks2 # do check on backwards branch
+ js common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_GOTO_16.S b/vm/mterp/x86-atom/OP_GOTO_16.S
index 6e6e0ac..931d215 100644
--- a/vm/mterp/x86-atom/OP_GOTO_16.S
+++ b/vm/mterp/x86-atom/OP_GOTO_16.S
@@ -30,5 +30,5 @@
FETCHs 1, %edx # %edx<- ssssAAAA (sign-extended)
shl $$1, %edx # %edx is doubled to get the byte offset
- js common_periodicChecks2 # do check on backwards branch
+ js common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_GOTO_32.S b/vm/mterp/x86-atom/OP_GOTO_32.S
index 2dadda6..d00c3a4 100644
--- a/vm/mterp/x86-atom/OP_GOTO_32.S
+++ b/vm/mterp/x86-atom/OP_GOTO_32.S
@@ -33,5 +33,5 @@
shl $$16, %ecx # prepare to create +AAAAAAAA
or %ecx, %edx # %edx<- +AAAAAAAA
shl $$1, %edx # %edx is doubled to get the byte offset
- jle common_periodicChecks2 # do check on backwards branch
+ jle common_periodicChecks_backwardBranch # do check on backwards branch
FINISH_RB %edx, %ecx # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_IF_EQ.S b/vm/mterp/x86-atom/OP_IF_EQ.S
index ba1a2d2..61781a0 100644
--- a/vm/mterp/x86-atom/OP_IF_EQ.S
+++ b/vm/mterp/x86-atom/OP_IF_EQ.S
@@ -17,4 +17,4 @@
* File: OP_IF_EQ.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"ne" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"ne" }
diff --git a/vm/mterp/x86-atom/OP_IF_EQZ.S b/vm/mterp/x86-atom/OP_IF_EQZ.S
index 5aacfc7..2f7c140 100644
--- a/vm/mterp/x86-atom/OP_IF_EQZ.S
+++ b/vm/mterp/x86-atom/OP_IF_EQZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_EQZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"ne" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"ne" }
diff --git a/vm/mterp/x86-atom/OP_IF_GE.S b/vm/mterp/x86-atom/OP_IF_GE.S
index 6fbfca5..e90a1e5 100644
--- a/vm/mterp/x86-atom/OP_IF_GE.S
+++ b/vm/mterp/x86-atom/OP_IF_GE.S
@@ -17,4 +17,4 @@
* File: OP_IF_GE.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"l" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"l" }
diff --git a/vm/mterp/x86-atom/OP_IF_GEZ.S b/vm/mterp/x86-atom/OP_IF_GEZ.S
index a953318..8ee71a8 100644
--- a/vm/mterp/x86-atom/OP_IF_GEZ.S
+++ b/vm/mterp/x86-atom/OP_IF_GEZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_GEZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"l" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"l" }
diff --git a/vm/mterp/x86-atom/OP_IF_GT.S b/vm/mterp/x86-atom/OP_IF_GT.S
index fa6f8ee..7f19db9 100644
--- a/vm/mterp/x86-atom/OP_IF_GT.S
+++ b/vm/mterp/x86-atom/OP_IF_GT.S
@@ -17,4 +17,4 @@
* File: OP_IF_GT.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"le" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"le" }
diff --git a/vm/mterp/x86-atom/OP_IF_GTZ.S b/vm/mterp/x86-atom/OP_IF_GTZ.S
index 397561f..3f8039f 100644
--- a/vm/mterp/x86-atom/OP_IF_GTZ.S
+++ b/vm/mterp/x86-atom/OP_IF_GTZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_GTZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"le" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"le" }
diff --git a/vm/mterp/x86-atom/OP_IF_LE.S b/vm/mterp/x86-atom/OP_IF_LE.S
index 480c2a1..287bd0d 100644
--- a/vm/mterp/x86-atom/OP_IF_LE.S
+++ b/vm/mterp/x86-atom/OP_IF_LE.S
@@ -17,4 +17,4 @@
* File: OP_IF_LE.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"g" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"g" }
diff --git a/vm/mterp/x86-atom/OP_IF_LEZ.S b/vm/mterp/x86-atom/OP_IF_LEZ.S
index ed9048b..b7d31d1 100644
--- a/vm/mterp/x86-atom/OP_IF_LEZ.S
+++ b/vm/mterp/x86-atom/OP_IF_LEZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_LEZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"g" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"g" }
diff --git a/vm/mterp/x86-atom/OP_IF_LT.S b/vm/mterp/x86-atom/OP_IF_LT.S
index 16c86b8..7e58e18 100644
--- a/vm/mterp/x86-atom/OP_IF_LT.S
+++ b/vm/mterp/x86-atom/OP_IF_LT.S
@@ -17,4 +17,4 @@
* File: OP_IF_LT.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"ge" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"ge" }
diff --git a/vm/mterp/x86-atom/OP_IF_LTZ.S b/vm/mterp/x86-atom/OP_IF_LTZ.S
index acdf95e..0a3e56b 100644
--- a/vm/mterp/x86-atom/OP_IF_LTZ.S
+++ b/vm/mterp/x86-atom/OP_IF_LTZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_LTZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"ge" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"ge" }
diff --git a/vm/mterp/x86-atom/OP_IF_NE.S b/vm/mterp/x86-atom/OP_IF_NE.S
index 5c3da51..929bd05 100644
--- a/vm/mterp/x86-atom/OP_IF_NE.S
+++ b/vm/mterp/x86-atom/OP_IF_NE.S
@@ -17,4 +17,4 @@
* File: OP_IF_NE.S
*/
-%include "x86-atom/bincmp.S" { "revcmp":"e" }
\ No newline at end of file
+%include "x86-atom/bincmp.S" { "revcmp":"e" }
diff --git a/vm/mterp/x86-atom/OP_IF_NEZ.S b/vm/mterp/x86-atom/OP_IF_NEZ.S
index c3286f0..07f2c87 100644
--- a/vm/mterp/x86-atom/OP_IF_NEZ.S
+++ b/vm/mterp/x86-atom/OP_IF_NEZ.S
@@ -17,4 +17,4 @@
* File: OP_IF_NEZ.S
*/
-%include "x86-atom/zcmp.S" { "revcmp":"e" }
\ No newline at end of file
+%include "x86-atom/zcmp.S" { "revcmp":"e" }
diff --git a/vm/mterp/x86-atom/OP_IGET_OBJECT_VOLATILE.S b/vm/mterp/x86-atom/OP_IGET_OBJECT_VOLATILE.S
new file mode 100644
index 0000000..5de2fa3
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_IGET_OBJECT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_IGET.S"
diff --git a/vm/mterp/x86-atom/OP_IGET_VOLATILE.S b/vm/mterp/x86-atom/OP_IGET_VOLATILE.S
new file mode 100644
index 0000000..5de2fa3
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_IGET_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_IGET.S"
diff --git a/vm/mterp/x86-atom/OP_INT_TO_BYTE.S b/vm/mterp/x86-atom/OP_INT_TO_BYTE.S
index 7d0a89d..27cafe9 100644
--- a/vm/mterp/x86-atom/OP_INT_TO_BYTE.S
+++ b/vm/mterp/x86-atom/OP_INT_TO_BYTE.S
@@ -17,4 +17,4 @@
* File: OP_INT_TO_BYTE.S
*/
-%include "x86-atom/unop.S" { "preinstr":"sal $24, %ecx", "instr":"sar $24, %ecx" }
\ No newline at end of file
+%include "x86-atom/unop.S" { "preinstr":"sal $24, %ecx", "instr":"sar $24, %ecx" }
diff --git a/vm/mterp/x86-atom/OP_INVOKE_DIRECT.S b/vm/mterp/x86-atom/OP_INVOKE_DIRECT.S
index 8f2a987..78b6c06 100644
--- a/vm/mterp/x86-atom/OP_INVOKE_DIRECT.S
+++ b/vm/mterp/x86-atom/OP_INVOKE_DIRECT.S
@@ -89,4 +89,4 @@
cmp $$0, %edx # check for null "this"
movl %eax, %ecx # %ecx<- method
jne common_invokeMethod${routine} # invoke method common code
- jmp common_errNullObject # handle null object
\ No newline at end of file
+ jmp common_errNullObject # handle null object
diff --git a/vm/mterp/x86-atom/OP_INVOKE_OBJECT_INIT_RANGE.S b/vm/mterp/x86-atom/OP_INVOKE_OBJECT_INIT_RANGE.S
index faf1565..2459a3c 100644
--- a/vm/mterp/x86-atom/OP_INVOKE_OBJECT_INIT_RANGE.S
+++ b/vm/mterp/x86-atom/OP_INVOKE_OBJECT_INIT_RANGE.S
@@ -23,3 +23,7 @@
* Format: B|A|op CCCC G|F|E|D (35c)
*/
+<<<<<<< HEAD:vm/mterp/x86-atom/OP_INVOKE_OBJECT_INIT_RANGE.S
+=======
+ FINISH 3
+>>>>>>> 10185db0:vm/mterp/x86-atom/OP_INVOKE_DIRECT_EMPTY.S
diff --git a/vm/mterp/x86-atom/OP_IPUT_OBJECT.S b/vm/mterp/x86-atom/OP_IPUT_OBJECT.S
index 33727ca..302cf44 100644
--- a/vm/mterp/x86-atom/OP_IPUT_OBJECT.S
+++ b/vm/mterp/x86-atom/OP_IPUT_OBJECT.S
@@ -13,8 +13,69 @@
* limitations under the License.
*/
- /*
- * File: OP_IPUT_OBJECT.S
+ /*
+ * File: OP_IPUT.S
+ *
+ * Code: Generic 32-bit instance field "put" operation. Provides a
+ * "mov" variable which determines the type of mov performed.
+ * Currently, none of the iput's use this variable - may want
+ * to change this, but seems ok for now.
+ *
+ * For: iput-boolean, iput-byte, iput-char, iput-object, iput
+ * iput-short
+ *
+ * Description: Perform the object instance field "get" operation
+ * with the identified field; load the instance value into
+ * the value register.
+ *
+ *
+ * Format: B|A|op CCCC (22c)
+ *
+ * Syntax: op vA, vB, type@CCCC
+ * op vA, vB, field@CCCC
*/
-%include "x86-atom/OP_IPUT.S"
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_methodClassDex(%edx), %edx # %edx<- pDvmDex
+ FETCH 1, %ecx # %ecx<- CCCC
+ movl offDvmDex_pResFields(%edx), %edx # %edx<- pDvmDex->pResFields
+ cmp $$0, (%edx, %ecx, 4) # check for null ptr; resolved InstField ptr
+ movl (%edx, %ecx, 4), %eax # %eax<- resolved InstField ptr
+ jne .L${opcode}_finish2
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ jmp .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+ movl offGlue_method(%edx), %edx # %edx<- glue->method
+ EXPORT_PC # in case an exception is thrown
+ movl %ecx, -4(%esp) # push parameter CCCC; field ref
+ movl offMethod_clazz(%edx), %edx # %edx<- method->clazz
+ lea -8(%esp), %esp
+ movl %edx, (%esp) # push parameter method->clazz
+ call dvmResolveInstField # call: (const ClassObject* referrer, u4 ifieldIdx)
+ # return: InstField*
+ lea 8(%esp), %esp
+ cmp $$0, %eax # check if resolved
+ jne .L${opcode}_finish2
+ jmp common_exceptionThrown # not resolved; handle exception
+
+.L${opcode}_finish2:
+ movl rINST, %ecx # %ecx<- BA+
+ shr $$4, %ecx # %ecx<- B
+ and $$15, rINST # rINST<- A
+ GET_VREG %ecx # %ecx<- vB
+ cmp $$0, %ecx # check for null object
+ je common_errNullObject # handle null object
+ movl offInstField_byteOffset(%eax), %edx # %edx<- field offset
+ GET_VREG rINST # rINST<- vA
+ movl rINST, (%edx, %ecx) # object field<- vA
+ FFETCH_ADV 2, %edx # %edx<- next instruction hi; fetch, advance
+ movl rGLUE, %eax # get glue
+ movl offGlue_cardTable(%eax), %eax # get card table base
+ testl rINST, rINST # test if we stored a null value
+ je 1f # skip card mark if null stored
+ shrl $$GC_CARD_SHIFT, %ecx # set obeject head to card number
+ movb %al, (%eax, %ecx)
+1:
+ FGETOP_JMP 2, %edx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_IPUT_OBJECT_QUICK.S b/vm/mterp/x86-atom/OP_IPUT_OBJECT_QUICK.S
index b1edd5e..eee88e9 100644
--- a/vm/mterp/x86-atom/OP_IPUT_OBJECT_QUICK.S
+++ b/vm/mterp/x86-atom/OP_IPUT_OBJECT_QUICK.S
@@ -14,7 +14,31 @@
*/
/*
- * File: OP_IPUT_OBJECT_QUICK.S
+ * File: OP_IPUT_QUICK.S
+ * Code: Optimization for iput
+ *
+ * For: iput-quick
+ *
+ * Format: B|A|op CCCC (22c)
+ *
+ * Syntax: op vA, vB, offset@CCCC
*/
-%include "x86-atom/OP_IPUT_QUICK.S"
+ movl rINST, %eax # %eax<- BA
+ shr $$4, %eax # %eax<- B
+ and $$15, rINST # rINST<- A
+ GET_VREG %eax # %eax<- vB; object to operate on
+ FETCH 1, %ecx # %ecx<- CCCC; field byte offset
+ cmp $$0, %eax # check if object is null
+ je common_errNullObject # handle null object
+ FFETCH_ADV 2, %edx # %edx<- next instruction hi; fetch, advance
+ GET_VREG rINST # rINST<- vA
+ movl rINST, (%eax, %ecx) # object field<- vA
+ testl rINST, rINST # did we write a null object
+ je 1f
+ movl rGLUE, %ecx # get glue
+ movl offGlue_cardTable(%ecx), %ecx # get card table base
+ shrl $$GC_CARD_SHIFT, %eax # get gc card index
+ movb %cl, (%eax, %ecx) # mark gc card in table
+1:
+ FGETOP_JMP 2, %edx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_IPUT_OBJECT_VOLATILE.S b/vm/mterp/x86-atom/OP_IPUT_OBJECT_VOLATILE.S
new file mode 100644
index 0000000..4b024d0
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_IPUT_OBJECT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_IPUT_OBJECT.S"
diff --git a/vm/mterp/x86-atom/OP_IPUT_VOLATILE.S b/vm/mterp/x86-atom/OP_IPUT_VOLATILE.S
new file mode 100644
index 0000000..475a0c5
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_IPUT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_IPUT.S"
diff --git a/vm/mterp/x86-atom/OP_LONG_TO_INT.S b/vm/mterp/x86-atom/OP_LONG_TO_INT.S
index 3397fc2..0984bc0 100644
--- a/vm/mterp/x86-atom/OP_LONG_TO_INT.S
+++ b/vm/mterp/x86-atom/OP_LONG_TO_INT.S
@@ -17,4 +17,4 @@
* File: OP_LONG_TO_INT.S
*/
-%include "x86-atom/OP_MOVE.S"
\ No newline at end of file
+%include "x86-atom/OP_MOVE.S"
diff --git a/vm/mterp/x86-atom/OP_MOVE.S b/vm/mterp/x86-atom/OP_MOVE.S
index ebc4989..9982ced 100644
--- a/vm/mterp/x86-atom/OP_MOVE.S
+++ b/vm/mterp/x86-atom/OP_MOVE.S
@@ -35,4 +35,4 @@
FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG rINST # rINST<- vB
SET_VREG rINST, %ecx # vA<- vB; %edx
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_MOVE_OBJECT.S b/vm/mterp/x86-atom/OP_MOVE_OBJECT.S
index 9abc5d0..1cd22cb 100644
--- a/vm/mterp/x86-atom/OP_MOVE_OBJECT.S
+++ b/vm/mterp/x86-atom/OP_MOVE_OBJECT.S
@@ -17,4 +17,4 @@
* File: OP_MOVE_OBJECT.S
*/
-%include "x86-atom/OP_MOVE.S"
\ No newline at end of file
+%include "x86-atom/OP_MOVE.S"
diff --git a/vm/mterp/x86-atom/OP_MOVE_OBJECT_FROM16.S b/vm/mterp/x86-atom/OP_MOVE_OBJECT_FROM16.S
index 1c8e661..bfca7da 100644
--- a/vm/mterp/x86-atom/OP_MOVE_OBJECT_FROM16.S
+++ b/vm/mterp/x86-atom/OP_MOVE_OBJECT_FROM16.S
@@ -17,4 +17,4 @@
* File: OP_MOVE_OBJECT_FROM16.S
*/
-%include "x86-atom/OP_MOVE_FROM16.S"
\ No newline at end of file
+%include "x86-atom/OP_MOVE_FROM16.S"
diff --git a/vm/mterp/x86-atom/OP_MOVE_WIDE.S b/vm/mterp/x86-atom/OP_MOVE_WIDE.S
index 9a91d2a..909243b 100644
--- a/vm/mterp/x86-atom/OP_MOVE_WIDE.S
+++ b/vm/mterp/x86-atom/OP_MOVE_WIDE.S
@@ -34,4 +34,4 @@
FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vB
movq %xmm0, (rFP, rINST, 4) # vA<- vB
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_MUL_FLOAT.S b/vm/mterp/x86-atom/OP_MUL_FLOAT.S
index 1529dd5..34eba58 100644
--- a/vm/mterp/x86-atom/OP_MUL_FLOAT.S
+++ b/vm/mterp/x86-atom/OP_MUL_FLOAT.S
@@ -17,4 +17,4 @@
* File: OP_MUL_FLOAT.S
*/
-%include "x86-atom/binopF.S" {"instr":"mulss %xmm1, %xmm0"}
\ No newline at end of file
+%include "x86-atom/binopF.S" {"instr":"mulss %xmm1, %xmm0"}
diff --git a/vm/mterp/x86-atom/OP_MUL_FLOAT_2ADDR.S b/vm/mterp/x86-atom/OP_MUL_FLOAT_2ADDR.S
index 4345ce7..dbd615d 100644
--- a/vm/mterp/x86-atom/OP_MUL_FLOAT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_MUL_FLOAT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_MUL_FLOAT_2ADDR.S
*/
-%include "x86-atom/binopF2addr.S" {"instr":"mulss %xmm1, %xmm0"}
\ No newline at end of file
+%include "x86-atom/binopF2addr.S" {"instr":"mulss %xmm1, %xmm0"}
diff --git a/vm/mterp/x86-atom/OP_MUL_INT.S b/vm/mterp/x86-atom/OP_MUL_INT.S
index b01ecda..8f5dac5 100644
--- a/vm/mterp/x86-atom/OP_MUL_INT.S
+++ b/vm/mterp/x86-atom/OP_MUL_INT.S
@@ -15,22 +15,6 @@
/*
* File: OP_MUL_INT.S
- *
- * Code: 32-bit multiply operation. Performs "%ecx = %ecx * %edx"
- *
- * Description: Perform a multiplication operation on two source registers
- * and store the result in a destination register.
- *
- * Format: AA|op CC|BB (23x)
- *
- * Syntax: op vAA, vBB, vCC
*/
- FETCH_BB 1, %ecx # %ecx<- BB
- FETCH_CC 1, %edx # %edx<- CC
- FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
- GET_VREG %ecx # %ecx<- vBB
- addl $$4, rPC # update PC
- imul (rFP, %edx, 4), %ecx # %ecx<- vBB * vCC
- SET_VREG %ecx, rINST # vAA<- %ecx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+%include "x86-atom/binop.S" {"instr":"imul %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_MUL_INT_2ADDR.S b/vm/mterp/x86-atom/OP_MUL_INT_2ADDR.S
index e907178..b544df7 100644
--- a/vm/mterp/x86-atom/OP_MUL_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_MUL_INT_2ADDR.S
@@ -17,13 +17,4 @@
* File: OP_MUL_INT_2ADDR.S
*/
- movl rINST, %edx # %edx<- BA
- shr $$4, %edx # %edx<- B
- andl $$15, rINST # rINST<- A
- movl rINST, %ecx # %ecx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- GET_VREG %ecx # %ecx<- vA
- imul (rFP, %edx, 4), %ecx # %ecx<- vA * vB
- addl $$2, rPC # update PC
- SET_VREG %ecx, rINST # vAA<- %ecx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
+%include "x86-atom/binop2addr.S" {"instr":"imul %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_MUL_INT_LIT16.S b/vm/mterp/x86-atom/OP_MUL_INT_LIT16.S
index 7f3a27a..241531f 100644
--- a/vm/mterp/x86-atom/OP_MUL_INT_LIT16.S
+++ b/vm/mterp/x86-atom/OP_MUL_INT_LIT16.S
@@ -17,4 +17,4 @@
* File: OP_MUL_INT_LIT16.S
*/
-%include "x86-atom/binopLit16.S" {"instr":"imul %edx, %ecx"}
\ No newline at end of file
+%include "x86-atom/binopLit16.S" {"instr":"imul %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_NEG_INT.S b/vm/mterp/x86-atom/OP_NEG_INT.S
index 6770216..68acb89 100644
--- a/vm/mterp/x86-atom/OP_NEG_INT.S
+++ b/vm/mterp/x86-atom/OP_NEG_INT.S
@@ -17,4 +17,4 @@
* File: OP_NEG_INT.S
*/
-%include "x86-atom/unop.S" {"instr":"neg %ecx"}
\ No newline at end of file
+%include "x86-atom/unop.S" {"instr":"neg %ecx"}
diff --git a/vm/mterp/x86-atom/OP_OR_INT.S b/vm/mterp/x86-atom/OP_OR_INT.S
index 59e39a3..0ece38c 100644
--- a/vm/mterp/x86-atom/OP_OR_INT.S
+++ b/vm/mterp/x86-atom/OP_OR_INT.S
@@ -17,4 +17,4 @@
* File: OP_OR_INT.S
*/
-%include "x86-atom/binop.S" {"instr":"or (rFP, %edx, 4), %ecx"}
\ No newline at end of file
+%include "x86-atom/binop.S" {"instr":"or %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_OR_INT_2ADDR.S b/vm/mterp/x86-atom/OP_OR_INT_2ADDR.S
index ddc20ed..693e099 100644
--- a/vm/mterp/x86-atom/OP_OR_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_OR_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_OR_INT_2ADDR.S
*/
-%include "x86-atom/binop2addr.S" {"instr":"or %edx, (rFP, rINST, 4)"}
\ No newline at end of file
+%include "x86-atom/binop2addr.S" {"instr":"or %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_OR_INT_LIT16.S b/vm/mterp/x86-atom/OP_OR_INT_LIT16.S
index 3715781..5c63867 100644
--- a/vm/mterp/x86-atom/OP_OR_INT_LIT16.S
+++ b/vm/mterp/x86-atom/OP_OR_INT_LIT16.S
@@ -17,4 +17,4 @@
* File: OP_OR_INT_LIT16.S
*/
-%include "x86-atom/binopLit16.S" {"instr":"or %edx, %ecx"}
\ No newline at end of file
+%include "x86-atom/binopLit16.S" {"instr":"or %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_PACKED_SWITCH.S b/vm/mterp/x86-atom/OP_PACKED_SWITCH.S
index 7cb6d64..debac02 100644
--- a/vm/mterp/x86-atom/OP_PACKED_SWITCH.S
+++ b/vm/mterp/x86-atom/OP_PACKED_SWITCH.S
@@ -45,7 +45,7 @@
shl $$1, %eax # shift for byte offset
movl %eax, %edx # %edx<- offset
lea 8(%esp), %esp
- jle common_periodicChecks2 # do backward branch
+ jle common_periodicChecks_backwardBranch # do backward branch
jmp .L${opcode}_finish
%break
.L${opcode}_finish:
diff --git a/vm/mterp/x86-atom/OP_REM_INT.S b/vm/mterp/x86-atom/OP_REM_INT.S
index 2cd8a26..5f62d66 100644
--- a/vm/mterp/x86-atom/OP_REM_INT.S
+++ b/vm/mterp/x86-atom/OP_REM_INT.S
@@ -17,4 +17,4 @@
* File: OP_REM_INT.S
*/
-%include "x86-atom/binopD.S" {"div":"0"}
\ No newline at end of file
+%include "x86-atom/binopD.S" {"div":"0"}
diff --git a/vm/mterp/x86-atom/OP_RETURN_OBJECT.S b/vm/mterp/x86-atom/OP_RETURN_OBJECT.S
index 48308df..3b9c10c 100644
--- a/vm/mterp/x86-atom/OP_RETURN_OBJECT.S
+++ b/vm/mterp/x86-atom/OP_RETURN_OBJECT.S
@@ -17,4 +17,4 @@
* File: OP_RETURN_OBJECT.S
*/
-%include "x86-atom/OP_RETURN_COMMON.S"
\ No newline at end of file
+%include "x86-atom/OP_RETURN_COMMON.S"
diff --git a/vm/mterp/x86-atom/OP_RSUB_INT.S b/vm/mterp/x86-atom/OP_RSUB_INT.S
index 647a98e..87498f9 100644
--- a/vm/mterp/x86-atom/OP_RSUB_INT.S
+++ b/vm/mterp/x86-atom/OP_RSUB_INT.S
@@ -36,4 +36,4 @@
GET_VREG %ecx # %ecx<- vB
subl %ecx, %edx # %edx<- +CCCC sub vB
SET_VREG %edx, rINST # vA<- %edx; result
- FINISH 2 # jump to next instruction
\ No newline at end of file
+ FINISH 2 # jump to next instruction
diff --git a/vm/mterp/x86-atom/OP_SGET_OBJECT_VOLATILE.S b/vm/mterp/x86-atom/OP_SGET_OBJECT_VOLATILE.S
new file mode 100644
index 0000000..5f64fb5
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_SGET_OBJECT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_SGET.S"
diff --git a/vm/mterp/x86-atom/OP_SGET_VOLATILE.S b/vm/mterp/x86-atom/OP_SGET_VOLATILE.S
new file mode 100644
index 0000000..5f64fb5
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_SGET_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_SGET.S"
diff --git a/vm/mterp/x86-atom/OP_SHL_INT.S b/vm/mterp/x86-atom/OP_SHL_INT.S
index ac0f0cc..13e4a11 100644
--- a/vm/mterp/x86-atom/OP_SHL_INT.S
+++ b/vm/mterp/x86-atom/OP_SHL_INT.S
@@ -17,4 +17,4 @@
* File: OP_SHL_INT.S
*/
-%include "x86-atom/binopS.S" {"instr":"sal %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopS.S" {"instr":"sal %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SHL_INT_2ADDR.S b/vm/mterp/x86-atom/OP_SHL_INT_2ADDR.S
index 27be297..a27e09a 100644
--- a/vm/mterp/x86-atom/OP_SHL_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_SHL_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_SHL_INT_2ADDR.S
*/
-%include "x86-atom/binopS2addr.S" {"instr":"sal %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopS2addr.S" {"instr":"sal %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SHL_INT_LIT8.S b/vm/mterp/x86-atom/OP_SHL_INT_LIT8.S
index 6e0e4f8..5141e5c 100644
--- a/vm/mterp/x86-atom/OP_SHL_INT_LIT8.S
+++ b/vm/mterp/x86-atom/OP_SHL_INT_LIT8.S
@@ -17,4 +17,4 @@
* File: OP_SHL_INT_LIT8.S
*/
-%include "x86-atom/binopLit8S.S" {"instr":"sal %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopLit8S.S" {"instr":"sal %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SHR_INT.S b/vm/mterp/x86-atom/OP_SHR_INT.S
index 2780f30..e7fd28b 100644
--- a/vm/mterp/x86-atom/OP_SHR_INT.S
+++ b/vm/mterp/x86-atom/OP_SHR_INT.S
@@ -17,4 +17,4 @@
* File: OP_SHR_INT.S
*/
-%include "x86-atom/binopS.S" {"instr":"sar %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopS.S" {"instr":"sar %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SHR_INT_2ADDR.S b/vm/mterp/x86-atom/OP_SHR_INT_2ADDR.S
index 4229f7d..0d0b461 100644
--- a/vm/mterp/x86-atom/OP_SHR_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_SHR_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_SHR_INT_2ADDR.S
*/
-%include "x86-atom/binopS2addr.S" {"instr":"sar %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopS2addr.S" {"instr":"sar %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SHR_INT_LIT8.S b/vm/mterp/x86-atom/OP_SHR_INT_LIT8.S
index 2cf2e39..3467bf5 100644
--- a/vm/mterp/x86-atom/OP_SHR_INT_LIT8.S
+++ b/vm/mterp/x86-atom/OP_SHR_INT_LIT8.S
@@ -17,4 +17,4 @@
* File: OP_SHR_INT_LIT8.S
*/
-%include "x86-atom/binopLit8S.S" {"instr":"sar %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopLit8S.S" {"instr":"sar %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_SPUT_OBJECT.S b/vm/mterp/x86-atom/OP_SPUT_OBJECT.S
index 60afb97..88ebaf7 100644
--- a/vm/mterp/x86-atom/OP_SPUT_OBJECT.S
+++ b/vm/mterp/x86-atom/OP_SPUT_OBJECT.S
@@ -15,6 +15,56 @@
/*
* File: OP_SPUT_OBJECT.S
+ *
+ * Code: Generic 32-bit static field "put" operation. Uses no substitutions.
+ *
+ * For: sput-boolean, sput-byte, sput-char, sput-object, sput, sput-short
+ *
+ * Description: Perform the identified object static field operation
+ * with the identified static field; store the field value
+ * register.
+ *
+ * Format: AA|op BBBB (21c)
+ *
+ * Syntax: op vAA, string@BBBB
*/
-%include "x86-atom/OP_SPUT.S"
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_methodClassDex(%edx), %ecx # %ecx<- pDvmDex
+ FETCH 1, %eax # %eax<- BBBB
+ movl offDvmDex_pResFields(%ecx), %ecx # %ecx<- pResFields
+ cmp $$0, (%ecx, %eax, 4) # check for null ptr; resolved StaticField
+ movl (%ecx, %eax, 4), %ecx # %ecx<- resolved StaticField
+ je .L${opcode}_resolve
+ jmp .L${opcode}_finish
+%break
+
+.L${opcode}_resolve:
+ movl offGlue_method(%edx), %edx # %edx <- glue->method
+ EXPORT_PC # in case an exception is thrown
+ movl %eax, -4(%esp) # push parameter CCCC; field ref
+ movl offMethod_clazz(%edx), %edx # %edx<- method->clazz
+ movl %edx, -8(%esp) # push parameter method->clazz
+ lea -8(%esp), %esp
+ call dvmResolveStaticField # call: (const ClassObject* referrer, u4 ifieldIdx)
+ # return: StaticField*
+ cmp $$0, %eax # check if initalization failed
+ lea 8(%esp), %esp
+ je common_exceptionThrown # failed; handle exception
+ movl %eax, %ecx # %ecx<- result
+
+.L${opcode}_finish:
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
+ GET_VREG rINST # rINST<- vAA
+
+
+ movl rINST, offStaticField_value(%ecx) # field value<- vAA
+ testl rINST, rINST # stored null object ptr?
+ je 1f
+ movl rGLUE, %edx # get glue
+ movl offField_clazz(%ecx), %ecx # ecx<- field->clazz
+ movl offGlue_cardTable(%edx), %edx # get card table base
+ shrl $$GC_CARD_SHIFT, %ecx # head to card number
+ movb %dl, (%edx, %ecx) # mark card
+1:
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/OP_SPUT_OBJECT_VOLATILE.S b/vm/mterp/x86-atom/OP_SPUT_OBJECT_VOLATILE.S
new file mode 100644
index 0000000..b368e31
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_SPUT_OBJECT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_SPUT_OBJECT.S"
diff --git a/vm/mterp/x86-atom/OP_SPUT_VOLATILE.S b/vm/mterp/x86-atom/OP_SPUT_VOLATILE.S
new file mode 100644
index 0000000..7ee4140
--- /dev/null
+++ b/vm/mterp/x86-atom/OP_SPUT_VOLATILE.S
@@ -0,0 +1 @@
+%include "x86/OP_SPUT.S"
diff --git a/vm/mterp/x86-atom/OP_SUB_FLOAT.S b/vm/mterp/x86-atom/OP_SUB_FLOAT.S
index c41f75e..eb79d79 100644
--- a/vm/mterp/x86-atom/OP_SUB_FLOAT.S
+++ b/vm/mterp/x86-atom/OP_SUB_FLOAT.S
@@ -17,4 +17,4 @@
* File: OP_SUB_FLOAT.S
*/
-%include "x86-atom/binopF.S" {"instr":"subss %xmm1, %xmm0"}
\ No newline at end of file
+%include "x86-atom/binopF.S" {"instr":"subss %xmm1, %xmm0"}
diff --git a/vm/mterp/x86-atom/OP_SUB_FLOAT_2ADDR.S b/vm/mterp/x86-atom/OP_SUB_FLOAT_2ADDR.S
index dad1b7c..77f23f1 100644
--- a/vm/mterp/x86-atom/OP_SUB_FLOAT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_SUB_FLOAT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_SUB_FLOAT_2ADDR.S
*/
-%include "x86-atom/binopF2addr.S" {"instr":"subss %xmm1, %xmm0"}
\ No newline at end of file
+%include "x86-atom/binopF2addr.S" {"instr":"subss %xmm1, %xmm0"}
diff --git a/vm/mterp/x86-atom/OP_SUB_INT.S b/vm/mterp/x86-atom/OP_SUB_INT.S
index be530aa..8d342cd 100644
--- a/vm/mterp/x86-atom/OP_SUB_INT.S
+++ b/vm/mterp/x86-atom/OP_SUB_INT.S
@@ -17,4 +17,4 @@
* File: OP_SUB_INT.S
*/
-%include "x86-atom/binop.S" {"instr":"subl (rFP, %edx, 4), %ecx"}
+%include "x86-atom/binop.S" {"instr":"subl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_SUB_INT_2ADDR.S b/vm/mterp/x86-atom/OP_SUB_INT_2ADDR.S
index 0ecbb57..4d295a4 100644
--- a/vm/mterp/x86-atom/OP_SUB_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_SUB_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_SUB_INT_2ADDR.S
*/
-%include "x86-atom/binop2addr.S" {"instr":"subl %edx, (rFP, rINST, 4)"}
\ No newline at end of file
+%include "x86-atom/binop2addr.S" {"instr":"subl %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_THROW.S b/vm/mterp/x86-atom/OP_THROW.S
index 85afa7a..120b1e9 100644
--- a/vm/mterp/x86-atom/OP_THROW.S
+++ b/vm/mterp/x86-atom/OP_THROW.S
@@ -28,6 +28,7 @@
*/
movl rGLUE, %eax # %eax<- pMterpGlue
+ EXPORT_PC # export the pc
GET_VREG rINST # rINST<- vAA
cmp $$0, rINST # check for null
movl offGlue_self(%eax), %ecx # %ecx<- glue->self
diff --git a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
index fcd42c7..f920b50 100644
--- a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
+++ b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
@@ -28,13 +28,13 @@
* Syntax: op vAA, ref@BBBB
*/
- movl rGLUE, %edx # %edx<- pMterpGlue
- movl offGlue_method(%edx), %ecx # %ecx<- glue->method
- EXPORT_PC # in case an exception is thrown
- FETCH 1, %eax # %eax<- BBBB
- movl %eax, -4(%esp) # push parameter BBBB; ref
- movl rINST, -8(%esp) # push parameter AA
- movl %ecx, -12(%esp) # push parameter glue->method
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_method(%edx), %ecx # %ecx<- glue->method
+ EXPORT_PC # in case an exception is thrown
+ FETCH 1, %eax # %eax<- BBBB
+ movl %eax, -4(%esp) # push parameter BBBB; ref
+ movl rINST, -8(%esp) # push parameter AA
+ movl %ecx, -12(%esp) # push parameter glue->method
lea -12(%esp), %esp
- call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
- jmp common_exceptionThrown # failed; handle exception
+ call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
+ jmp common_exceptionThrown # failed; handle exception
diff --git a/vm/mterp/x86-atom/OP_USHR_INT_LIT8.S b/vm/mterp/x86-atom/OP_USHR_INT_LIT8.S
index 38516c5..5a54df7 100644
--- a/vm/mterp/x86-atom/OP_USHR_INT_LIT8.S
+++ b/vm/mterp/x86-atom/OP_USHR_INT_LIT8.S
@@ -17,4 +17,4 @@
* File: OP_USHR_INT_LIT8.S
*/
-%include "x86-atom/binopLit8S.S" {"instr":"shr %cl, %edx"}
\ No newline at end of file
+%include "x86-atom/binopLit8S.S" {"instr":"shr %cl, %edx"}
diff --git a/vm/mterp/x86-atom/OP_XOR_INT.S b/vm/mterp/x86-atom/OP_XOR_INT.S
index 6c8e26d..d36b83f 100644
--- a/vm/mterp/x86-atom/OP_XOR_INT.S
+++ b/vm/mterp/x86-atom/OP_XOR_INT.S
@@ -17,4 +17,4 @@
* File: OP_XOR_INT.S
*/
-%include "x86-atom/binop.S" {"instr":"xor (rFP, %edx, 4), %ecx"}
\ No newline at end of file
+%include "x86-atom/binop.S" {"instr":"xor %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_XOR_INT_2ADDR.S b/vm/mterp/x86-atom/OP_XOR_INT_2ADDR.S
index d2b8338..0bab865 100644
--- a/vm/mterp/x86-atom/OP_XOR_INT_2ADDR.S
+++ b/vm/mterp/x86-atom/OP_XOR_INT_2ADDR.S
@@ -17,4 +17,4 @@
* File: OP_XOR_INT_2ADDR.S
*/
-%include "x86-atom/binop2addr.S" {"instr":"xor %edx, (rFP, rINST, 4)"}
\ No newline at end of file
+%include "x86-atom/binop2addr.S" {"instr":"xor %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/OP_XOR_INT_LIT16.S b/vm/mterp/x86-atom/OP_XOR_INT_LIT16.S
index bb841cd..a26bcc5 100644
--- a/vm/mterp/x86-atom/OP_XOR_INT_LIT16.S
+++ b/vm/mterp/x86-atom/OP_XOR_INT_LIT16.S
@@ -17,4 +17,4 @@
* File: OP_XOR_INT_LIT16.S
*/
-%include "x86-atom/binopLit16.S" {"instr":"xor %edx, %ecx"}
\ No newline at end of file
+%include "x86-atom/binopLit16.S" {"instr":"xor %edx, %ecx"}
diff --git a/vm/mterp/x86-atom/TODO.txt b/vm/mterp/x86-atom/TODO.txt
index 1c0acc8..da14adc 100644
--- a/vm/mterp/x86-atom/TODO.txt
+++ b/vm/mterp/x86-atom/TODO.txt
@@ -19,7 +19,7 @@
(md) Correct OP_MONITOR_EXIT (need to adjust PC before throw)
(md) OP_THROW needs to export the PC
-(md) Use dvmThrowArrayIndexOutOfBoundsException(index, length) for
+(md) Use dvmThrowArrayIndexOutOfBoundsException(length, index) for
array bounds errors.
(md) Use dvmThrowClassCastException(actual, desired) for class cast errors.
(md) Use dvmThrowArrayStoreException(actual, desired) for array store errors.
@@ -27,7 +27,6 @@
(md) Replace any remaining use of dvmThrowException with proper helper function
(lo) Implement OP_BREAKPOINT
-(lo) Implement OP_EXECUTE_INLINE_RANGE
(lo) Implement OP_*_VOLATILE (12 instructions)
(lo) Implement OP_RETURN_VOID_BARRIER
(lo) Implement OP_INVOKE_OBJECT_INIT
diff --git a/vm/mterp/x86-atom/bincmp.S b/vm/mterp/x86-atom/bincmp.S
index b56a0e1..a8fbed5 100644
--- a/vm/mterp/x86-atom/bincmp.S
+++ b/vm/mterp/x86-atom/bincmp.S
@@ -39,6 +39,6 @@
# comparison is true
FETCHs 1, %edx # %edx<- +CCCC, Branch offset
sal $$1, %edx
- js common_periodicChecks2
+ js common_periodicChecks_backwardBranch
1:
FINISH_RB %edx, %ecx # jump to next instruction
diff --git a/vm/mterp/x86-atom/binop.S b/vm/mterp/x86-atom/binop.S
index 0343190..1706b72 100644
--- a/vm/mterp/x86-atom/binop.S
+++ b/vm/mterp/x86-atom/binop.S
@@ -29,14 +29,11 @@
* Syntax: op vAA, vBB, vCC
*/
-
-
FETCH_BB 1, %ecx # %ecx<- BB
- OLD_JMP_1 2, %eax
- OLD_JMP_2 %eax
FETCH_CC 1, %edx # %edx<- CC
- OLD_JMP_3 2
+ FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vBB
+ GET_VREG %edx # %edx<- vCC
$instr # %ecx<- vBB op vCC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- OLD_JMP_4 %eax
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binop2addr.S b/vm/mterp/x86-atom/binop2addr.S
index af135a7..b26b25a 100644
--- a/vm/mterp/x86-atom/binop2addr.S
+++ b/vm/mterp/x86-atom/binop2addr.S
@@ -33,12 +33,13 @@
movl rINST, %edx # %edx<- BA
shr $$4, %edx # %edx<- B
- #FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
- OLD_JMP_1 1, %eax
- andl $$15, rINST # rINST<- A
- OLD_JMP_2 %eax
+ andl $$15, rINST # rINST<- A
+ movl rINST, %ecx # %ecx<- A
+ FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
GET_VREG %edx # %edx<- vB
- OLD_JMP_3 1
- $instr # %ecx<- vA op vB
- #FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
- OLD_JMP_4 %eax
+ GET_VREG %ecx # %ecx<- vA
+ $instr # %ecx<- vA op vB
+ SET_VREG %ecx, rINST # vAA<- %ecx; result
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
+
+
diff --git a/vm/mterp/x86-atom/binopD.S b/vm/mterp/x86-atom/binopD.S
index a3565f3..20a2e9a 100644
--- a/vm/mterp/x86-atom/binopD.S
+++ b/vm/mterp/x86-atom/binopD.S
@@ -31,35 +31,31 @@
%default {"div":"1"}
-
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %eax # %eax<- BB
- GET_VREG %ecx # %ecx<- vCC
- testl %ecx, %ecx
+ FETCH_CC 1, %ecx # %ecx<- CC
GET_VREG %eax # %eax<- vBB
+ GET_VREG %ecx # %ecx<- vCC
+ cmp $$0, %ecx # check for divide by zero
je common_errDivideByZero # handle divide by zero
cmpl $$-1, %ecx # handle -1 special case divide error
- jnz .L${opcode}_continue
+ jne .L${opcode}_noerror
cmpl $$0x80000000,%eax # handle min int special case divide error
je .L${opcode}_break
-.L${opcode}_continue:
+.L${opcode}_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if $div
- FFETCH_ADV 2 %edx
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 2 %edx
.else
- FFETCH_ADV 2 %eax
- SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 2 %eax
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .L${opcode}_break2
%break
.L${opcode}_break:
- FFETCH_ADV 2 %eax
.if $div
movl $$0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $$0, (rFP, rINST, 4) # vAA<- 0
.endif
- FGETOP_JMP 2 %eax
\ No newline at end of file
+.L${opcode}_break2:
+ FINISH 2 # jump to next instruction
diff --git a/vm/mterp/x86-atom/binopD2addr.S b/vm/mterp/x86-atom/binopD2addr.S
index a4fcf65..392b46b 100644
--- a/vm/mterp/x86-atom/binopD2addr.S
+++ b/vm/mterp/x86-atom/binopD2addr.S
@@ -32,37 +32,37 @@
%default {"div":"1"}
movl rINST, %ecx # %ecx<- BA
- shr $$4, %ecx # %ecx<- B
andl $$15, rINST # rINST<- A, to be used as dest
movl rINST, %eax # %eax<- A
- GET_VREG %ecx # %edx<- vB
- testl %ecx, %ecx # check for divide by zero
+ shr $$4, %ecx # %ecx<- B
GET_VREG %eax # %eax<- vA
- jz common_errDivideByZero # handle divide by zero
+ GET_VREG %ecx # %edx<- vB
+ cmp $$0, %ecx # check for divide by zero
+ je common_errDivideByZero # handle divide by zero
cmpl $$-1, %ecx # handle -1 special case divide error
- jnz .L${opcode}_continue
- cmpl $$0x80000000, %eax # handle min int special case divide error
+ jne .L${opcode}_noerror
+ cmpl $$0x80000000,%eax # handle min int special case divide error
je .L${opcode}_break
-
-.L${opcode}_continue:
+.L${opcode}_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
.if $div
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
SET_VREG %eax rINST # vAA<- %eax (quotient)
- FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
.else
- FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
SET_VREG %edx rINST # vAA<- %edx (remainder)
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
.endif
+ jmp .L${opcode}_break2
+ #FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
+ #FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
%break
.L${opcode}_break:
- FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
.if $div
movl $$0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $$0, (rFP, rINST, 4) # vAA<- 0
.endif
+.L${opcode}_break2:
+ FFETCH_ADV 1, %edx # %ecx<- next instruction hi; fetch, advance
FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
+
diff --git a/vm/mterp/x86-atom/binopDLit16.S b/vm/mterp/x86-atom/binopDLit16.S
index 86bb937..3e67d0a 100644
--- a/vm/mterp/x86-atom/binopDLit16.S
+++ b/vm/mterp/x86-atom/binopDLit16.S
@@ -35,37 +35,32 @@
movl rINST, %eax # %eax<- BA
shr $$4, %eax # %eax<- B
FETCHs 1, %ecx # %ecx<- +CCCC, sign-extended literal
- testl %ecx, %ecx # check for divide by zero
+ cmp $$0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vB
je common_errDivideByZero # handle divide by zero
- addl $$4, rPC # update PC
andl $$15, rINST # rINST<- A
cmpl $$-1, %ecx # handle -1 special case divide error
- jnz .L${opcode}_continue
+ jne .L${opcode}_noerror
cmpl $$0x80000000,%eax # handle min int special case divide error
- je .L${opcode}_break
-.L${opcode}_continue:
+ je .L${opcode}_break
+.L${opcode}_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if $div
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vA<- %edx (remainder)
.endif
+ jmp .L${opcode}_break2
%break
.L${opcode}_break:
- movzbl (rPC), %edx
.if $div
movl $$0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $$0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+.L${opcode}_break2:
+
+ FINISH 2 # jump to next instruction
diff --git a/vm/mterp/x86-atom/binopDLit8.S b/vm/mterp/x86-atom/binopDLit8.S
index 295a770..f197714 100644
--- a/vm/mterp/x86-atom/binopDLit8.S
+++ b/vm/mterp/x86-atom/binopDLit8.S
@@ -32,37 +32,34 @@
%default {"div":"1"}
- FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
- testl %ecx, %ecx # handle -1 special case divide error
FETCH_BB 1, %eax # %eax<- BB
- jz common_errDivideByZero # handle divide by zero
- addl $$4, rPC # update PC
- cmpl $$-1, %ecx
+ FETCH_CCs 1, %ecx # %ecx<- +CC, sign-extended literal
+ cmp $$0, %ecx # check for divide by zero
GET_VREG %eax # %eax<- vBB
- jnz .L${opcode}_continue
+ je common_errDivideByZero # handle divide by zero
+
+ cmpl $$-1, %ecx # handle -1 special case divide error
+ jne .L${opcode}_noerror
cmpl $$0x80000000,%eax # handle min int special case divide error
- je .L${opcode}_break
-.L${opcode}_continue:
+ je .L${opcode}_break
+.L${opcode}_noerror:
cdq # sign-extend %eax to %edx
idiv %ecx # divide %edx:%eax by %ecx
+ #FFETCH_ADV 2, %ecx # %ecx<- next instruction hi; fetch, advance
.if $div
- movzbl (rPC), %edx
- SET_VREG %eax, rINST # vA<- %eax (quotient)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+ SET_VREG %eax rINST # vAA<- %eax (quotient)
.else
- movzbl (rPC), %eax
- SET_VREG %edx, rINST # vA<- %edx (remainder)
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %eax, 4)
+ SET_VREG %edx rINST # vAA<- %edx (remainder)
.endif
+ jmp .L${opcode}_break2
%break
.L${opcode}_break:
- movzbl (rPC), %edx
.if $div
movl $$0x80000000, (rFP, rINST, 4) # vAA<- min int
.else
movl $$0, (rFP, rINST, 4) # vAA<- 0
.endif
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(, %edx, 4)
+
+.L${opcode}_break2:
+ FINISH 2 # jump to next instruction
+ #FGETOP_JMP 2, %ecx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopDivRemLong2Addr.S b/vm/mterp/x86-atom/binopDivRemLong2Addr.S
index d50f776..aa427de 100644
--- a/vm/mterp/x86-atom/binopDivRemLong2Addr.S
+++ b/vm/mterp/x86-atom/binopDivRemLong2Addr.S
@@ -51,4 +51,4 @@
movl %eax, (rFP, rINST, 4) # vA<- return low
movl %edx, 4(rFP, rINST, 4) # vA<- return high
FFETCH_ADV 1, %ecx # %ecx<- next instruction hi; fetch, advance
- FGETOP_JMP 1, %ecx # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %ecx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopF.S b/vm/mterp/x86-atom/binopF.S
index a2b408f..0c07b97 100644
--- a/vm/mterp/x86-atom/binopF.S
+++ b/vm/mterp/x86-atom/binopF.S
@@ -36,4 +36,4 @@
movss (rFP, %edx, 4), %xmm1 # %xmm1<- vCC
$instr # %xmm0<- vBB op vCC
movss %xmm0, (rFP, rINST, 4) # vAA<- %xmm0; result
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopF2addr.S b/vm/mterp/x86-atom/binopF2addr.S
index df1fdf7..135ca0c 100644
--- a/vm/mterp/x86-atom/binopF2addr.S
+++ b/vm/mterp/x86-atom/binopF2addr.S
@@ -38,4 +38,4 @@
movss (rFP, rINST, 4), %xmm1 # %xmm1<- vB
$instr # %xmm0<- vA op vB
movss %xmm0, (rFP, %ecx, 4) # vA<- %xmm0; result
- FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopLit16.S b/vm/mterp/x86-atom/binopLit16.S
index 8b1cbd1..4972b4d 100644
--- a/vm/mterp/x86-atom/binopLit16.S
+++ b/vm/mterp/x86-atom/binopLit16.S
@@ -40,4 +40,4 @@
GET_VREG %ecx # %ecx<- vB
$instr # %ecx<- vA op vB
SET_VREG %ecx, rINST # vA<- %ecx; result
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopLit8.S b/vm/mterp/x86-atom/binopLit8.S
index f6c4a6b..239e443 100644
--- a/vm/mterp/x86-atom/binopLit8.S
+++ b/vm/mterp/x86-atom/binopLit8.S
@@ -37,4 +37,4 @@
GET_VREG %ecx # %ecx<- vBB
$instr # %ecx<- vBB op +CC
SET_VREG %ecx, rINST # vAA<- %ecx; result
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopLit8S.S b/vm/mterp/x86-atom/binopLit8S.S
index c400063..c0360aa 100644
--- a/vm/mterp/x86-atom/binopLit8S.S
+++ b/vm/mterp/x86-atom/binopLit8S.S
@@ -37,4 +37,4 @@
GET_VREG %edx # %edx<- vBB
$instr # %edx<- vBB op +CC
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopS.S b/vm/mterp/x86-atom/binopS.S
index b9c3e26..b09f5c2 100644
--- a/vm/mterp/x86-atom/binopS.S
+++ b/vm/mterp/x86-atom/binopS.S
@@ -29,12 +29,11 @@
* Syntax: op vAA, vBB, vCC
*/
- FETCH_CC 1, %ecx # %ecx<- CC
FETCH_BB 1, %edx # %edx<- BB
+ FETCH_CC 1, %ecx # %ecx<- CC
FFETCH_ADV 2, %eax # %eax<- next instruction hi; fetch, advance
- addl $$4, rPC # update PC
- GET_VREG %ecx # %ecx<- vCC
GET_VREG %edx # %edx<- vBB
+ GET_VREG %ecx # %ecx<- vCC
$instr # %edx<- vBB op +CC
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopS2addr.S b/vm/mterp/x86-atom/binopS2addr.S
index 453f38f..0c3c29a 100644
--- a/vm/mterp/x86-atom/binopS2addr.S
+++ b/vm/mterp/x86-atom/binopS2addr.S
@@ -32,12 +32,11 @@
movl rINST, %ecx # %ecx<- BA
shr $$4, %ecx # %ecx<- B
- FFETCH_ADV 1, %eax # %ecx<- next i nstruction hi; fetch, advance
andl $$15, rINST # rINST<- A
- addl $$2, rPC # update PC
movl rINST, %edx # %edx<- A
+ FFETCH_ADV 1, %eax # %ecx<- next instruction hi; fetch, advance
GET_VREG %ecx # %ecx<- vB
GET_VREG %edx # %edx<- vA
$instr # %edx<- vA op vB
SET_VREG %edx, rINST # vAA<- %edx; result
- FGETOP_JMP2 %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopWide.S b/vm/mterp/x86-atom/binopWide.S
index 3b27f60..3cd3e52 100644
--- a/vm/mterp/x86-atom/binopWide.S
+++ b/vm/mterp/x86-atom/binopWide.S
@@ -37,4 +37,4 @@
movq (rFP, %edx, 4), %xmm1 # %xmm1<- vCC
$instr # %xmm0<- vBB op vCC
movq %xmm0, (rFP, rINST, 4) # vAA<- %ecx
- FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 2, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/binopWide2addr.S b/vm/mterp/x86-atom/binopWide2addr.S
index a051c2b..f9aa29c 100644
--- a/vm/mterp/x86-atom/binopWide2addr.S
+++ b/vm/mterp/x86-atom/binopWide2addr.S
@@ -34,10 +34,8 @@
movl rINST, %edx # %edx<- BA
shr $$4, rINST # rINST<- B
andl $$15, %edx # %edx<- A
- FFETCH_ADV 1, %eax # %eax<- next instruction hi; fetch, advance
movq (rFP, rINST, 4), %xmm1 # %xmm1<- vB
movq (rFP, %edx, 4), %xmm0 # %xmm0<- vA
$instr # %xmm0<- vA op vB
movq %xmm0, (rFP, %edx, 4) # vA<- %xmm0; result
- #FINISH 1 # jump to next instruction
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FINISH 1 # jump to next instruction
diff --git a/vm/mterp/x86-atom/entry.S b/vm/mterp/x86-atom/entry.S
index ff6ab0b..3b8a3da 100644
--- a/vm/mterp/x86-atom/entry.S
+++ b/vm/mterp/x86-atom/entry.S
@@ -46,13 +46,6 @@
*/
.macro MTERP_EXIT
- #lea 40(%ebp), %esp # correct stack pointer
- #movl 24(%ebp), %edi # restore %edi
- #movl 28(%ebp), %esi # restore %esi
- #movl 32(%ebp), %ebx # restore %ebx
- #movl 36(%ebp), %ebp # restore caller base pointer
- #ret # return
-
lea 40(%esp), %esp # correct stack pointer
movl -16(%esp), %edi # restore %edi
movl -12(%esp), %esi # restore %esi
@@ -360,11 +353,11 @@
.long .L_OP_SHL_INT_LIT8
.long .L_OP_SHR_INT_LIT8
.long .L_OP_USHR_INT_LIT8
-.long .L_OP_UNUSED_E3
-.long .L_OP_UNUSED_E4
-.long .L_OP_UNUSED_E5
-.long .L_OP_UNUSED_E6
-.long .L_OP_UNUSED_E7
+.long .L_OP_IGET_VOLATILE
+.long .L_OP_IPUT_VOLATILE
+.long .L_OP_SGET_VOLATILE
+.long .L_OP_SPUT_VOLATILE
+.long .L_OP_IGET_OBJECT_VOLATILE
.long .L_OP_IGET_WIDE_VOLATILE
.long .L_OP_IPUT_WIDE_VOLATILE
.long .L_OP_SGET_WIDE_VOLATILE
@@ -385,7 +378,7 @@
.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE
.long .L_OP_INVOKE_SUPER_QUICK
.long .L_OP_INVOKE_SUPER_QUICK_RANGE
-.long .L_OP_UNUSED_FC
-.long .L_OP_UNUSED_FD
-.long .L_OP_UNUSED_FE
+.long .L_OP_IPUT_OBJECT_VOLATILE
+.long .L_OP_SGET_OBJECT_VOLATILE
+.long .L_OP_SPUT_OBJECT_VOLATILE
.long .L_OP_DISPATCH_FF
diff --git a/vm/mterp/x86-atom/footer.S b/vm/mterp/x86-atom/footer.S
index 4b2818c..7b5ed9c 100644
--- a/vm/mterp/x86-atom/footer.S
+++ b/vm/mterp/x86-atom/footer.S
@@ -34,26 +34,22 @@
movl rGLUE, %edx # %edx<- pMterpGlue
movl %ebx, -4(%esp) # save %ebx to the stack
movl offGlue_pSelfSuspendCount(%edx), %ebx # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
+4:
movl offGlue_pDebuggerActive(%edx), %eax # %eax<- pDebuggerActive
- movl (%eax), %eax # %eax<- get debuggerActive (boolean)
- and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
+ testl %eax, %eax
+ je 5f
+ movzbl (%eax), %eax # %eax<- get debuggerActive (boolean)
+5:
cmp $$0, (%ebx) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(%edx), %ebx # %ebx<- activeProfilers (int)
- or (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
- cmp $$0, %eax # check for debuggerActive
-#endif
- jne 3f # debugger or profiler active; switch interp
-#endif
+ orl (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive
movl -8(%esp), %edx # %edx<- restore %edx
+ jne 3f # debugger or profiler active; switch interp
movl -4(%esp), %ebx # %ebx<- restore %ebx
ret # return
2: # check suspended
+ EXPORT_PC
movl offGlue_self(%edx), %eax # %eax<- glue->self
movl %eax, -12(%esp) # push parameter boolean
lea -12(%esp), %esp
@@ -62,11 +58,12 @@
movl 4(%esp), %edx # %edx<- restore %edx
movl 8(%esp), %ebx # %ebx<- restore %ebx
lea 12(%esp), %esp
- ret # return
+ ret
3: # debugger/profiler enabled, bail out
- add -8(%esp), rPC # rPC<- pc adjustments
- movl %ecx, offGlue_entryPoint(%edx) # glue->entryPoint<- reentry type
- movl $$1, %edx # switch to interp == true
+ leal (rPC, %edx, 2), rPC # adjust pc to show target
+ movl rGLUE, %ecx # %ecx<- pMterpGlue
+ movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx)
+ movl $$1, %edx # switch interpreter
jmp common_gotoBail # bail
/*
@@ -78,25 +75,21 @@
* %edx is PC adjustment in bytes
*/
-common_periodicChecks2:
+common_periodicChecks_backwardBranch:
+ EXPORT_PC
movl rGLUE, %ecx # %ecx<- pMterpGlue
movl offGlue_pSelfSuspendCount(%ecx), rINST # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
- movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive
- movl (%eax), %eax # %eax<- get debuggerActive (boolean)
- and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
+4:
+ movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive
+ testl %eax, %eax # test for NULL pointer
+ je 5f
+ movzbl (%eax), %eax # %eax<- get debuggerActive count
+5:
cmp $$0, (rINST) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(%ecx), rINST # %edx<- activeProfilers (int)
- or (rINST), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
- cmp $$0, %eax # check for debuggerActive
-#endif
+ orl (rINST), %eax # %eax<- merge activeProfilers and debuggerActive
jne 3f # debugger or profiler active; switch interp
-#endif
FINISH_RB %edx, %ecx # jump to next instruction
2: # check suspended
movl offGlue_self(%ecx), %eax# %eax<- glue->self
@@ -107,15 +100,13 @@
# return: bool
movl rINST, %edx # %edx<- restore %edx
lea 12(%esp), %esp
- FINISH_RB %edx, %ecx # jump to next instruction
-
+ FINISH_RB %edx, %ecx
3: # debugger/profiler enabled, bail out
- add -8(%esp), rPC # rPC<- pc adjustments
- movl $$kInterpEntryInstr, offGlue_entryPoint(%ecx) # glue->entryPoint<- reentry type
- movl $$1, %edx # switch to interp<- true
+ leal (rPC, %edx, 2), rPC # adjust pc to show target
+ movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx)
+ movl $$1, %edx # switch interpreter
jmp common_gotoBail # bail
-
/*
* The equivalent of "goto bail", this calls through the "bail handler".
* State registers will be saved to the "glue" area before bailing.
@@ -333,13 +324,13 @@
jne common_exceptionThrown # handle exception
FGETOP_JMP 3, %edx # jump to next instruction; getop, jmp
-.LstackOverflow: # %ecx=methodToCall
- movl %ecx, -4(%esp) # push parameter method to call
+.LstackOverflow:
+ movl %ecx, -4(%esp) # push method to call
movl rGLUE, %ecx # %ecx<- pMterpGlue
movl offGlue_self(%ecx), %ecx # %ecx<- glue->self
movl %ecx, -8(%esp) # push parameter self
lea -8(%esp), %esp
- call dvmHandleStackOverflow # call: (Thread* self, Method* method)
+ call dvmHandleStackOverflow # call: (Thread* self, Method *meth)
# return: void
lea 8(%esp), %esp
jmp common_exceptionThrown # handle exception
@@ -361,22 +352,15 @@
movl rGLUE, rINST # %ecx<- pMterpGlue
movl offGlue_pSelfSuspendCount(rINST), %edx # %ebx<- pSuspendCount (int)
-#if defined(WITH_DEBUGGER)
movl offGlue_pDebuggerActive(rINST), %eax # %eax<- pDebuggerActive
movl (%eax), %eax # %eax<- get debuggerActive (boolean)
and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?)
-#endif
cmp $$0, (%edx) # check if suspend is pending
jne 2f # handle suspend
-#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
-#if defined(WITH_PROFILER)
movl offGlue_pActiveProfilers(rINST), %edx # %edx<- activeProfilers (int)
or (%edx), %eax # %eax<- merge activeProfilers and debuggerActive
-#else
cmp $$0, %eax # check for debuggerActive
-#endif
jne 3f # debugger or profiler active; switch interp
-#endif
jmp 4f
2: # check suspended
movl offGlue_self(rINST), %eax# %eax<- glue->self
@@ -564,7 +548,7 @@
jmp .LdeadFood
.LdeadFood:
-.word 0xdeadf00d
+.int 0xdeadf00d
/*
* Invalid array index.
diff --git a/vm/mterp/x86-atom/header.S b/vm/mterp/x86-atom/header.S
index 5b8303a..28c19d6 100644
--- a/vm/mterp/x86-atom/header.S
+++ b/vm/mterp/x86-atom/header.S
@@ -288,44 +288,6 @@
jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
.endm
- .macro FGETOP_JMP2 _rFinish
- movzbl 1(rPC), rINST
- jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4)
- .endm
-
- .macro OLD_JMP_1 _count _rFinish
- movzbl (\_count*2)(rPC), \_rFinish
- shl $$${handler_size_bits}, \_rFinish
- .endm
-
- .macro OLD_JMP_2 _rFinish
- addl $$dvmAsmInstructionStart,\_rFinish
- .endm
-
- .macro OLD_JMP_3 _count
- addl $$(\_count*2), rPC
- .endm
-
- .macro OLD_JMP_4 _rFinish
- movzbl 1(rPC), rINST
- jmp *\_rFinish
- .endm
-
- .macro OLD_JMP_A_1 _reg _rFinish
- movzbl (rPC, \_reg), \_rFinish
- shl $$${handler_size_bits}, \_rFinish
- .endm
-
- .macro OLD_JMP_A_2 _rFinish
- addl $$dvmAsmInstructionStart,\_rFinish
- .endm
-
- .macro OLD_JMP_A_3 _reg _rFinish
- addl \_reg, rPC
- movzbl 1(rPC, \_reg), rINST
- jmp *\_rFinish
- .endm
-
/*
* Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE
* by using a jump table. _rFinish and _reg should must be the same register for
diff --git a/vm/mterp/x86-atom/unop.S b/vm/mterp/x86-atom/unop.S
index 09af3d0..00f9f8d 100644
--- a/vm/mterp/x86-atom/unop.S
+++ b/vm/mterp/x86-atom/unop.S
@@ -40,4 +40,4 @@
$preinstr # do operation part 1
$instr # do operation part 2
SET_VREG %ecx, rINST # vA<- result
- FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
\ No newline at end of file
+ FGETOP_JMP 1, %eax # jump to next instruction; getop, jmp
diff --git a/vm/mterp/x86-atom/zcmp.S b/vm/mterp/x86-atom/zcmp.S
index f93566e..6614dba 100644
--- a/vm/mterp/x86-atom/zcmp.S
+++ b/vm/mterp/x86-atom/zcmp.S
@@ -38,7 +38,7 @@
* Inline common_backwardBranch
*/
- js common_periodicChecks2 # jump on backwards branch
+ js common_periodicChecks_backwardBranch # jump on backwards branch
1:
FINISH_RB %edx, %ecx # jump to next instruction
diff --git a/vm/mterp/x86/OP_CONST_CLASS_JUMBO.S b/vm/mterp/x86/OP_CONST_CLASS_JUMBO.S
index 44162da..ce64823 100644
--- a/vm/mterp/x86/OP_CONST_CLASS_JUMBO.S
+++ b/vm/mterp/x86/OP_CONST_CLASS_JUMBO.S
@@ -6,8 +6,8 @@
movl 2(rPC),%eax # eax<- AAAAAAAA
movl offThread_methodClassDex(%ecx),%ecx# ecx<- self->methodClassDex
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
- FETCH_INST_OPCODE 4 %ecx
movl (%ecx,%eax,4),%eax # eax<- rResClasses[AAAAAAAA]
+ FETCH_INST_OPCODE 4 %ecx
testl %eax,%eax # resolved yet?
je .L${opcode}_resolve
SET_VREG %eax rINST # vBBBB<- rResClasses[AAAAAAAA]
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index a185096..643deb8 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -623,9 +623,9 @@
common_errArrayIndex:
EXPORT_PC
movl offArrayObject_length(%eax), %eax
- movl %ecx,OUT_ARG0(%esp)
- movl %eax,OUT_ARG1(%esp)
- call dvmThrowArrayIndexOutOfBoundsException # args (index, length)
+ movl %eax,OUT_ARG0(%esp)
+ movl %ecx,OUT_ARG1(%esp)
+ call dvmThrowArrayIndexOutOfBoundsException # args (length, index)
jmp common_exceptionThrown
/*
diff --git a/vm/native/InternalNative.c b/vm/native/InternalNative.c
index 726c391..49e0c08 100644
--- a/vm/native/InternalNative.c
+++ b/vm/native/InternalNative.c
@@ -169,7 +169,7 @@
char* actualClassName = (obj != NULL)
? dvmHumanReadableDescriptor(obj->clazz->descriptor)
: strdup("null");
- dvmThrowExceptionFmtByClass(exceptionClass,
+ dvmThrowExceptionFmt(exceptionClass,
"expected receiver of type %s, but got %s",
expectedClassName, actualClassName);
free(expectedClassName);
diff --git a/vm/native/dalvik_system_DexFile.c b/vm/native/dalvik_system_DexFile.c
index af7eb89..9c9a6e1 100644
--- a/vm/native/dalvik_system_DexFile.c
+++ b/vm/native/dalvik_system_DexFile.c
@@ -259,7 +259,7 @@
RETURN_VOID();
}
- /* TODO: Avoid making a copy of the array. */
+ /* TODO: Avoid making a copy of the array. (note array *is* modified) */
length = fileContentsObj->length;
pBytes = (u1*) malloc(length);
@@ -360,7 +360,8 @@
name = dvmCreateCstrFromString(nameObj);
descriptor = dvmDotToDescriptor(name);
- LOGV("--- Explicit class load '%s' 0x%08x\n", descriptor, cookie);
+ LOGV("--- Explicit class load '%s' l=%p c=0x%08x\n",
+ descriptor, loader, cookie);
free(name);
if (!validateCookie(cookie))
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index 78c12f8..d511a8f 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -280,7 +280,7 @@
fd = dup(origFd);
if (fd < 0) {
- dvmThrowExceptionFmt("Ljava/lang/RuntimeException;",
+ dvmThrowExceptionFmt(gDvm.exRuntimeException,
"dup(%d) failed: %s", origFd, strerror(errno));
RETURN_VOID();
}
diff --git a/vm/native/java_lang_System.c b/vm/native/java_lang_System.c
index c3e7a80..5402a7b 100644
--- a/vm/native/java_lang_System.c
+++ b/vm/native/java_lang_System.c
@@ -136,7 +136,7 @@
/* make sure it's an array */
if (!dvmIsArray(srcArray) || !dvmIsArray(dstArray)) {
- dvmThrowExceptionFmtByClass(gDvm.exArrayStoreException,
+ dvmThrowExceptionFmt(gDvm.exArrayStoreException,
"source and destination must be arrays, but were %s and %s",
((Object*)srcArray)->clazz->descriptor,
((Object*)dstArray)->clazz->descriptor);
@@ -148,7 +148,7 @@
srcPos > (int) srcArray->length - length ||
dstPos > (int) dstArray->length - length)
{
- dvmThrowExceptionFmtByClass(gDvm.exArrayIndexOutOfBoundsException,
+ dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
"src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
srcArray->length, srcPos, dstArray->length, dstPos, length);
RETURN_VOID();
@@ -167,7 +167,7 @@
dstPrim = (dstType != '[' && dstType != 'L');
if (srcPrim || dstPrim) {
if (srcPrim != dstPrim || srcType != dstType) {
- dvmThrowExceptionFmtByClass(gDvm.exArrayStoreException,
+ dvmThrowExceptionFmt(gDvm.exArrayStoreException,
"source and destination arrays are incompatible: %s and %s",
srcClass->descriptor, dstClass->descriptor);
RETURN_VOID();
@@ -283,7 +283,7 @@
copyCount * width);
dvmWriteBarrierArray(dstArray, 0, copyCount);
if (copyCount != length) {
- dvmThrowExceptionFmtByClass(gDvm.exArrayStoreException,
+ dvmThrowExceptionFmt(gDvm.exArrayStoreException,
"source[%d] of type %s cannot be stored in destination array of type %s",
copyCount, srcObj[copyCount]->clazz->descriptor,
dstClass->descriptor);
diff --git a/vm/oo/Array.c b/vm/oo/Array.c
index 0fa0f80..33b0f97 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.c
@@ -51,9 +51,8 @@
size_t totalSize = elementSize + headerSize;
if (elementSize >> elementShift != length || totalSize < elementSize) {
char *descriptor = dvmHumanReadableDescriptor(arrayClass->descriptor);
- dvmThrowExceptionFmt("Ljava/lang/OutOfMemoryError;",
- "%s of length %zd exceeds the VM limit",
- descriptor, length);
+ dvmThrowExceptionFmt(gDvm.exOutOfMemoryError,
+ "%s of length %zd exceeds the VM limit", descriptor, length);
free(descriptor);
return NULL;
}
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 3bd0298..16fb5d3 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -363,27 +363,6 @@
}
/*
- * We should be able to find classes now. Get the vtable index for
- * the class loader loadClass() method.
- *
- * This doesn't work in dexopt when operating on core.jar, because
- * there aren't any classes to load.
- */
-bool dvmBaseClassStartup(void)
-{
- ClassObject* clClass = dvmFindSystemClassNoInit("Ljava/lang/ClassLoader;");
- Method* meth = dvmFindVirtualMethodByDescriptor(clClass, "loadClass",
- "(Ljava/lang/String;)Ljava/lang/Class;");
- if (meth == NULL) {
- LOGE("Unable to find loadClass() in java.lang.ClassLoader\n");
- return false;
- }
- gDvm.voffJavaLangClassLoader_loadClass = meth->methodIndex;
-
- return true;
-}
-
-/*
* Clean up.
*/
void dvmClassShutdown(void)
@@ -1300,8 +1279,7 @@
#endif
dvmAddTrackedAlloc(excep, self);
dvmClearException(self);
- dvmThrowChainedExceptionWithClassMessage(
- "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
+ dvmThrowChainedNoClassDefFoundError(descriptor, excep);
dvmReleaseTrackedAlloc(excep, self);
clazz = NULL;
goto bail;
@@ -3717,7 +3695,7 @@
if (clazz->verifyErrorClass == NULL) {
dvmThrowNoClassDefFoundError(clazz->descriptor);
} else {
- dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
+ dvmThrowExceptionWithClassMessage(clazz->verifyErrorClass,
clazz->descriptor);
}
}
diff --git a/vm/oo/Class.h b/vm/oo/Class.h
index 9ec6f12..e27ef79 100644
--- a/vm/oo/Class.h
+++ b/vm/oo/Class.h
@@ -48,7 +48,6 @@
} ClassPathEntry;
bool dvmClassStartup(void);
-bool dvmBaseClassStartup(void);
void dvmClassShutdown(void);
bool dvmPrepBootClassPath(bool isNormalStart);
diff --git a/vm/reflect/Annotation.c b/vm/reflect/Annotation.c
index f333fa5..0fcf80d 100644
--- a/vm/reflect/Annotation.c
+++ b/vm/reflect/Annotation.c
@@ -54,67 +54,6 @@
static const char* kDescrSignature = "Ldalvik/annotation/Signature;";
static const char* kDescrThrows = "Ldalvik/annotation/Throws;";
-
-/*
- * Perform Annotation setup.
- */
-bool dvmReflectAnnotationStartup(void)
-{
- Method* meth;
-
- /*
- * Find some standard Annotation classes.
- */
- gDvm.classJavaLangAnnotationAnnotationArray =
- dvmFindArrayClass("[Ljava/lang/annotation/Annotation;", NULL);
- gDvm.classJavaLangAnnotationAnnotationArrayArray =
- dvmFindArrayClass("[[Ljava/lang/annotation/Annotation;", NULL);
- if (gDvm.classJavaLangAnnotationAnnotationArray == NULL ||
- gDvm.classJavaLangAnnotationAnnotationArrayArray == NULL)
- {
- LOGE("Could not find Annotation-array classes\n");
- return false;
- }
-
- /*
- * VM-specific annotation classes.
- */
- gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory =
- dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationFactory;");
- gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember =
- dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationMember;");
- gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray =
- dvmFindArrayClass("[Lorg/apache/harmony/lang/annotation/AnnotationMember;", NULL);
- if (gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory == NULL ||
- gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember == NULL ||
- gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray == NULL)
- {
- LOGE("Could not find android.lang annotation classes\n");
- return false;
- }
-
- meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,
- "createAnnotation",
- "(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)Ljava/lang/annotation/Annotation;");
- if (meth == NULL) {
- LOGE("Unable to find createAnnotation() in android AnnotationFactory\n");
- return false;
- }
- gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation = meth;
-
- meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
- "<init>",
- "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V");
- if (meth == NULL) {
- LOGE("Unable to find 4-arg constructor in android AnnotationMember\n");
- return false;
- }
-
- gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init = meth;
-
- return true;
-}
-
/*
* Read an unsigned LEB128 value from a buffer. Advances "pBuf".
*/
diff --git a/vm/reflect/Proxy.c b/vm/reflect/Proxy.c
index e96aa1b..7b41360 100644
--- a/vm/reflect/Proxy.c
+++ b/vm/reflect/Proxy.c
@@ -49,70 +49,6 @@
#define kThrowsField 0
#define kProxySFieldCount 1
-
-/*
- * Perform Proxy setup.
- */
-bool dvmReflectProxyStartup()
-{
- /*
- * Standard methods we must provide in our proxy.
- */
- Method* methE;
- Method* methH;
- Method* methT;
- Method* methF;
- methE = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
- "equals", "(Ljava/lang/Object;)Z");
- methH = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
- "hashCode", "()I");
- methT = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
- "toString", "()Ljava/lang/String;");
- methF = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject,
- "finalize", "()V");
- if (methE == NULL || methH == NULL || methT == NULL || methF == NULL) {
- LOGE("Could not find equals/hashCode/toString/finalize in Object\n");
- return false;
- }
- gDvm.voffJavaLangObject_equals = methE->methodIndex;
- gDvm.voffJavaLangObject_hashCode = methH->methodIndex;
- gDvm.voffJavaLangObject_toString = methT->methodIndex;
- gDvm.voffJavaLangObject_finalize = methF->methodIndex;
-
- /*
- * The prototype signature needs to be cloned from a method in a
- * "real" DEX file. We declared this otherwise unused method just
- * for this purpose.
- */
- ClassObject* proxyClass;
- Method* meth;
- proxyClass = dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
- if (proxyClass == NULL) {
- LOGE("No java.lang.reflect.Proxy\n");
- return false;
- }
- meth = dvmFindDirectMethodByDescriptor(proxyClass, "constructorPrototype",
- "(Ljava/lang/reflect/InvocationHandler;)V");
- if (meth == NULL) {
- LOGE("Could not find java.lang.Proxy.constructorPrototype()\n");
- return false;
- }
- gDvm.methJavaLangReflectProxy_constructorPrototype = meth;
-
- /*
- * Get the offset of the "h" field in Proxy.
- */
- gDvm.offJavaLangReflectProxy_h = dvmFindFieldOffset(proxyClass, "h",
- "Ljava/lang/reflect/InvocationHandler;");
- if (gDvm.offJavaLangReflectProxy_h < 0) {
- LOGE("Unable to find 'h' field in java.lang.Proxy\n");
- return false;
- }
-
- return true;
-}
-
-
/*
* Generate a proxy class with the specified name, interfaces, and loader.
* "interfaces" is an array of class objects.
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index 62e4f67..dd87d44 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -21,118 +21,6 @@
#include <stdlib.h>
/*
- * Cache some classes.
- */
-bool dvmReflectStartup(void)
-{
- gDvm.classJavaLangReflectAccessibleObject =
- dvmFindSystemClassNoInit("Ljava/lang/reflect/AccessibleObject;");
- gDvm.classJavaLangReflectConstructor =
- dvmFindSystemClassNoInit("Ljava/lang/reflect/Constructor;");
- gDvm.classJavaLangReflectConstructorArray =
- dvmFindArrayClass("[Ljava/lang/reflect/Constructor;", NULL);
- gDvm.classJavaLangReflectField =
- dvmFindSystemClassNoInit("Ljava/lang/reflect/Field;");
- gDvm.classJavaLangReflectFieldArray =
- dvmFindArrayClass("[Ljava/lang/reflect/Field;", NULL);
- gDvm.classJavaLangReflectMethod =
- dvmFindSystemClassNoInit("Ljava/lang/reflect/Method;");
- gDvm.classJavaLangReflectMethodArray =
- dvmFindArrayClass("[Ljava/lang/reflect/Method;", NULL);
- gDvm.classJavaLangReflectProxy =
- dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
- if (gDvm.classJavaLangReflectAccessibleObject == NULL ||
- gDvm.classJavaLangReflectConstructor == NULL ||
- gDvm.classJavaLangReflectConstructorArray == NULL ||
- gDvm.classJavaLangReflectField == NULL ||
- gDvm.classJavaLangReflectFieldArray == NULL ||
- gDvm.classJavaLangReflectMethod == NULL ||
- gDvm.classJavaLangReflectMethodArray == NULL ||
- gDvm.classJavaLangReflectProxy == NULL)
- {
- LOGE("Could not find one or more reflection classes\n");
- return false;
- }
-
- gDvm.methJavaLangReflectConstructor_init =
- dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectConstructor, "<init>",
- "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V");
- gDvm.methJavaLangReflectField_init =
- dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectField, "<init>",
- "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
- gDvm.methJavaLangReflectMethod_init =
- dvmFindDirectMethodByDescriptor(gDvm.classJavaLangReflectMethod, "<init>",
- "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V");
- if (gDvm.methJavaLangReflectConstructor_init == NULL ||
- gDvm.methJavaLangReflectField_init == NULL ||
- gDvm.methJavaLangReflectMethod_init == NULL)
- {
- LOGE("Could not find reflection constructors\n");
- return false;
- }
-
- gDvm.classJavaLangClassArray =
- dvmFindArrayClass("[Ljava/lang/Class;", NULL);
- gDvm.classJavaLangObjectArray =
- dvmFindArrayClass("[Ljava/lang/Object;", NULL);
- if (gDvm.classJavaLangClassArray == NULL ||
- gDvm.classJavaLangObjectArray == NULL)
- {
- LOGE("Could not find class-array or object-array class\n");
- return false;
- }
-
- gDvm.offJavaLangReflectAccessibleObject_flag =
- dvmFindFieldOffset(gDvm.classJavaLangReflectAccessibleObject, "flag",
- "Z");
-
- gDvm.offJavaLangReflectConstructor_slot =
- dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor, "slot", "I");
- gDvm.offJavaLangReflectConstructor_declClass =
- dvmFindFieldOffset(gDvm.classJavaLangReflectConstructor,
- "declaringClass", "Ljava/lang/Class;");
-
- gDvm.offJavaLangReflectField_slot =
- dvmFindFieldOffset(gDvm.classJavaLangReflectField, "slot", "I");
- gDvm.offJavaLangReflectField_declClass =
- dvmFindFieldOffset(gDvm.classJavaLangReflectField,
- "declaringClass", "Ljava/lang/Class;");
-
- gDvm.offJavaLangReflectMethod_slot =
- dvmFindFieldOffset(gDvm.classJavaLangReflectMethod, "slot", "I");
- gDvm.offJavaLangReflectMethod_declClass =
- dvmFindFieldOffset(gDvm.classJavaLangReflectMethod,
- "declaringClass", "Ljava/lang/Class;");
-
- if (gDvm.offJavaLangReflectAccessibleObject_flag < 0 ||
- gDvm.offJavaLangReflectConstructor_slot < 0 ||
- gDvm.offJavaLangReflectConstructor_declClass < 0 ||
- gDvm.offJavaLangReflectField_slot < 0 ||
- gDvm.offJavaLangReflectField_declClass < 0 ||
- gDvm.offJavaLangReflectMethod_slot < 0 ||
- gDvm.offJavaLangReflectMethod_declClass < 0)
- {
- LOGE("Could not find reflection fields\n");
- return false;
- }
-
- if (!dvmReflectProxyStartup())
- return false;
- if (!dvmReflectAnnotationStartup())
- return false;
-
- return true;
-}
-
-/*
- * Clean up.
- */
-void dvmReflectShutdown(void)
-{
- // nothing to do
-}
-
-/*
* For some of the reflection stuff we need to un-box primitives, e.g.
* convert a java/lang/Integer to int or even a float. We assume that
* the first instance field holds the value.
diff --git a/vm/reflect/Reflect.h b/vm/reflect/Reflect.h
index 42b18c0..1ebdd2a 100644
--- a/vm/reflect/Reflect.h
+++ b/vm/reflect/Reflect.h
@@ -19,11 +19,6 @@
#ifndef _DALVIK_REFLECT_REFLECT
#define _DALVIK_REFLECT_REFLECT
-bool dvmReflectStartup(void);
-bool dvmReflectProxyStartup(void);
-bool dvmReflectAnnotationStartup(void);
-void dvmReflectShutdown(void);
-
/*
* During startup, validate the "box" classes, e.g. java/lang/Integer.
*/