Various fixes.
CHECK_xx arguments should be the "right" way round, not backwards like
ASSERT_xx and EXPECT_xx.
Use /mnt/sdcard/ rather than /sdcard/ to bypass FUSE and avoid getting
intermittent mkdir(2) "Device or resource busy" failures.
Better diagnostics when methods not found by test helpers.
Remove the whitelist from oatCompileMethod.
Leave evidence in the log of what we've compiled and where we put it.
Disable card marking by generated code until we have a cards to mark.
Distinguish between CanPutArrayElementFromCode and CanPutArrayElement.
Implement both.
Add a new test to see how much of the basic System and String/StringBuilder
facilities are working.
Change-Id: Ie24f2859e404ab912e6cc77d170ceb4df5ecdf19
diff --git a/build/Android.common.mk b/build/Android.common.mk
index de2622a..53f7667 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -165,4 +165,5 @@
ProtoCompare2 \
StaticLeafMethods \
Statics \
+ SystemMethods \
XandY
diff --git a/src/class_loader.h b/src/class_loader.h
index 3309a8a..ff62d12 100644
--- a/src/class_loader.h
+++ b/src/class_loader.h
@@ -16,7 +16,7 @@
static const std::vector<const DexFile*>& GetClassPath(const ClassLoader* class_loader);
void SetClassPath(std::vector<const DexFile*>& class_path) {
- DCHECK_EQ(0U, class_path_.size());
+ DCHECK_EQ(class_path_.size(), 0U);
// TODO: use setter
class_path_ = class_path;
}
diff --git a/src/common_test.h b/src/common_test.h
index 4689b28..4ed61f2 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -98,8 +98,10 @@
setenv("ANDROID_ROOT", root.c_str(), 1);
}
- android_data_ = (is_host_ ? "/tmp/art-data-XXXXXX" : "/sdcard/art-data-XXXXXX");
- ASSERT_TRUE(mkdtemp(&android_data_[0]) != NULL);
+ android_data_ = (is_host_ ? "/tmp/art-data-XXXXXX" : "/mnt/sdcard/art-data-XXXXXX");
+ if (mkdtemp(&android_data_[0]) == NULL) {
+ PLOG(FATAL) << "mkdtemp(\"" << &android_data_[0] << "\") failed";
+ }
setenv("ANDROID_DATA", android_data_.c_str(), 1);
art_cache_.append(android_data_.c_str());
art_cache_.append("/art-cache");
@@ -257,7 +259,8 @@
Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
CHECK(klass != NULL) << "Class not found " << class_name;
Method* method = klass->FindDirectMethod(method_name, signature);
- CHECK(method != NULL) << "Method not found " << method_name;
+ CHECK(method != NULL) << "Direct method not found: "
+ << class_name << "." << method_name << signature;
CompileMethod(method);
}
@@ -269,7 +272,8 @@
Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
CHECK(klass != NULL) << "Class not found " << class_name;
Method* method = klass->FindVirtualMethod(method_name, signature);
- CHECK(method != NULL) << "Method not found " << method_name;
+ CHECK(method != NULL) << "Virtual method not found: "
+ << class_name << "." << method_name << signature;
CompileMethod(method);
}
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index e9f8a3a..64d701e 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -699,40 +699,7 @@
*/
bool oatCompileMethod(Method* method, art::InstructionSet insnSet)
{
- bool compiling = true;
- if (!method->IsStatic()) {
- compiling = false; // assume skip
- if (PrettyMethod(method).find("virtualCall") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("tryThing") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("getFoo") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("setFoo") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("IntMath.<init>") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("IntMathBase.<init>") != std::string::npos) {
- compiling = true;
- }
- if (PrettyMethod(method).find("java.lang.Object.<init>") != std::string::npos) {
- compiling = true;
- }
- } else if (method->GetName()->ToModifiedUtf8().find("foo") != std::string::npos) {
- compiling = false;
- }
-
- if (compiling) {
- LOG(INFO) << "Compiling " << PrettyMethod(method);
- } else {
- LOG(INFO) << "not compiling " << PrettyMethod(method);
- return false;
- }
+ LOG(INFO) << "Compiling " << PrettyMethod(method) << "...";
CompilationUnit cUnit;
art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
@@ -930,6 +897,9 @@
method->SetFrameSizeInBytes(cUnit.frameSize);
method->SetCoreSpillMask(cUnit.coreSpillMask);
method->SetFpSpillMask(cUnit.fpSpillMask);
+ LOG(INFO) << "Compiled " << PrettyMethod(method)
+ << " code at " << reinterpret_cast<void*>(managed_code->GetData())
+ << " (" << managed_code->GetLength() << " bytes)";
// TODO: Transmit mapping table to caller
#if 0
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index d0b0683..9ea9e70 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -361,6 +361,9 @@
*/
static void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
{
+#if 1
+ UNIMPLEMENTED(WARNING);
+#else
int regCardBase = oatAllocTemp(cUnit);
int regCardNo = oatAllocTemp(cUnit);
ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondEq, valReg, 0);
@@ -374,6 +377,7 @@
branchOver->generic.target = (LIR*)target;
oatFreeTemp(cUnit, regCardBase);
oatFreeTemp(cUnit, regCardNo);
+#endif
}
static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size,
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 656c7d4..e3ff47f 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -26,7 +26,7 @@
jclass c = env->FindClass(klass);
CHECK(c != NULL) << "Class not found " << klass;
jmethodID m = env->GetStaticMethodID(c, method, signature);
- CHECK(m != NULL) << "Method not found " << method;
+ CHECK(m != NULL) << "Method not found: " << klass << "." << method << signature;
#if defined(__arm__)
va_list args;
va_start(args, expected);
@@ -44,7 +44,7 @@
jclass c = env->FindClass(klass);
CHECK(c != NULL) << "Class not found " << klass;
jmethodID m = env->GetStaticMethodID(c, method, signature);
- CHECK(m != NULL) << "Method not found " << method;
+ CHECK(m != NULL) << "Method not found: " << klass << "." << method << signature;
#if defined(__arm__)
va_list args;
va_start(args, expected);
@@ -263,5 +263,41 @@
111);
}
+TEST_F(CompilerTest, SystemMethodsTest) {
+ CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
+
+ CompileDirectMethod(NULL, "java.lang.String", "<clinit>", "()V");
+ CompileDirectMethod(NULL, "java.lang.String", "<init>", "(II[C)V");
+ CompileDirectMethod(NULL, "java.lang.String", "<init>", "([CII)V");
+ CompileVirtualMethod(NULL, "java.lang.String", "charAt", "(I)C");
+ CompileVirtualMethod(NULL, "java.lang.String", "length", "()I");
+ CompileVirtualMethod(NULL, "java.lang.String", "_getChars", "(II[CI)V");
+
+ CompileDirectMethod(NULL, "java.lang.AbstractStringBuilder", "<init>", "(I)V");
+ CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "(Ljava/lang/String;)V");
+ CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "(C)V");
+ CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "appendNull", "()V");
+ CompileDirectMethod(NULL, "java.lang.AbstractStringBuilder", "enlargeBuffer", "(I)V");
+ CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "toString", "()Ljava/lang/String;");
+
+ CompileDirectMethod(NULL, "java.lang.StringBuilder", "<init>", "(I)V");
+ CompileVirtualMethod(NULL, "java.lang.StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
+ CompileVirtualMethod(NULL, "java.lang.StringBuilder", "append", "(C)Ljava/lang/StringBuilder;");
+ CompileVirtualMethod(NULL, "java.lang.StringBuilder", "toString", "()Ljava/lang/String;");
+
+ // TODO: we can't compile these yet.
+ // CompileDirectMethod(NULL, "java.lang.Long", "toString", "(JI)Ljava/lang/String;");
+ // CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToString", "(JI)Ljava/lang/String;");
+
+ CompileDirectMethod(NULL, "java.lang.System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
+ CompileDirectMethod(NULL, "java.lang.System", "log", "(CLjava/lang/String;Ljava/lang/Throwable;)V");
+ CompileDirectMethod(NULL, "java.lang.System", "logI", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ CompileDirectMethod(NULL, "java.lang.System", "logI", "(Ljava/lang/String;)V");
+ CompileDirectMethod(NULL, "java.lang.System", "currentTimeMillis", "()J");
+
+ const ClassLoader* class_loader = LoadDex("SystemMethods");
+ AssertStaticIntMethod(class_loader, "SystemMethods", "test2", "()I", 123);
+}
+
} // namespace art
diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc
index e45519e..2bb767d 100644
--- a/src/java_lang_System.cc
+++ b/src/java_lang_System.cc
@@ -213,14 +213,14 @@
Class* initialElementClass = NULL;
if (length > 0 && srcObj[0] != NULL) {
initialElementClass = srcObj[0]->GetClass();
- if (!Class::CanPutArrayElementFromCode(initialElementClass, dstClass)) {
+ if (!Class::CanPutArrayElement(initialElementClass, dstClass)) {
initialElementClass = NULL;
}
}
int copyCount;
for (copyCount = 0; copyCount < length; copyCount++) {
- if (srcObj[copyCount] != NULL && srcObj[copyCount]->GetClass() != initialElementClass && !Class::CanPutArrayElementFromCode(srcObj[copyCount]->GetClass(), dstClass)) {
+ if (srcObj[copyCount] != NULL && srcObj[copyCount]->GetClass() != initialElementClass && !Class::CanPutArrayElement(srcObj[copyCount]->GetClass(), dstClass)) {
// Can't put this element into the array.
// We'll copy up to this point, then throw.
break;
diff --git a/src/object.cc b/src/object.cc
index d60b4c8..5d99cb6 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -595,9 +595,20 @@
return false;
}
-bool Class::CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass) {
- UNIMPLEMENTED(FATAL);
- return false;
+bool Class::CanPutArrayElement(const Class* object_class, const Class* array_class) {
+ if (object_class->IsArrayClass()) {
+ return array_class->IsArrayAssignableFromArray(object_class);
+ } else {
+ return array_class->GetComponentType()->IsAssignableFrom(object_class);
+ }
+}
+
+void Class::CanPutArrayElementFromCode(const Class* object_class, const Class* array_class) {
+ if (!CanPutArrayElement(object_class, array_class)) {
+ LOG(ERROR) << "Can't put a " << PrettyDescriptor(object_class->GetDescriptor())
+ << " into a " << PrettyDescriptor(array_class->GetDescriptor());
+ UNIMPLEMENTED(FATAL) << "need to throw ArrayStoreException and unwind stack";
+ }
}
// Determine whether "this" is assignable from "klazz", where both of these
@@ -617,7 +628,7 @@
// Serializable[][] = Y[][] --> false (unless Y is Serializable)
//
// Don't forget about primitive types.
-// int[] instanceof Object[] --> false
+// Object[] = int[] --> false
//
bool Class::IsArrayAssignableFromArray(const Class* klass) const {
DCHECK(IsArrayClass());
@@ -854,6 +865,7 @@
}
Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
+ DCHECK(array_class != NULL);
DCHECK_GE(component_count, 0);
DCHECK(array_class->IsArrayClass());
size_t size = SizeOf(component_count, component_size);
diff --git a/src/object.h b/src/object.h
index 4edae14..fa09782 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1092,7 +1092,7 @@
}
void SetLength(int32_t length) {
- CHECK_LE(0, length);
+ CHECK_GE(length, 0);
SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
}
@@ -1421,7 +1421,12 @@
return !IsPrimitive() && GetSuperClass() == NULL;
}
- static bool CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass);
+ // Tests whether an element of type 'object_class' can be
+ // assigned into an array of type 'array_class'.
+ static bool CanPutArrayElement(const Class* object_class, const Class* array_class);
+ // Like CanPutArrayElement, but throws an exception and
+ // unwinds the stack instead of returning false.
+ static void CanPutArrayElementFromCode(const Class* object_class, const Class* array_class);
// Given the context of a calling Method, use its DexCache to
// resolve a type to a Class. If it cannot be resolved, throw an
diff --git a/src/thread.cc b/src/thread.cc
index a617fb4..5da02ae 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -176,7 +176,7 @@
Mutex* Mutex::Create(const char* name) {
Mutex* mu = new Mutex(name);
int result = pthread_mutex_init(&mu->lock_impl_, NULL);
- CHECK_EQ(0, result);
+ CHECK_EQ(result, 0);
return mu;
}
diff --git a/src/thread.h b/src/thread.h
index 070933b..8749689 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -214,7 +214,7 @@
void (*pSet64Static)(uint32_t, const Method*, uint64_t);
Object* (*pGetObjStatic)(uint32_t, const Method*);
void (*pSetObjStatic)(uint32_t, const Method*, Object*);
- bool (*pCanPutArrayElementFromCode)(const Class*, const Class*);
+ void (*pCanPutArrayElementFromCode)(const Class*, const Class*);
int (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
bool (*pUnlockObjectFromCode)(Thread*, Object*);
diff --git a/test/SystemMethods/SystemMethods.java b/test/SystemMethods/SystemMethods.java
new file mode 100644
index 0000000..f14df18
--- /dev/null
+++ b/test/SystemMethods/SystemMethods.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class SystemMethods {
+ public static int test0() {
+ System.logI("hello world");
+ return 123;
+ }
+
+ public static int test1() {
+ String[] digits = new String[] {
+ "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f",
+ };
+ System.logI("hello world");
+ long t = System.currentTimeMillis();
+ for (int i = 7; i >= 0; --i) {
+ int b = ((int) (t >> (i * 8))) & 0xff;
+ System.logI(digits[(b >> 4) & 0xf]);
+ System.logI(digits[b & 0xf]);
+ }
+ return 123;
+ }
+
+ public static int test2() {
+ System.logI("creating char[]...");
+ char[] cs = new char[20];
+ System.logI("...created char[]");
+ String[] digits = new String[] {
+ "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f",
+ };
+ long t = System.currentTimeMillis();
+ System.logI("creating StringBuilder...");
+ StringBuilder sb = new StringBuilder(20);
+ System.logI("...created StringBuilder");
+ for (int i = 7; i >= 0; --i) {
+ int b = ((int) (t >> (i * 8))) & 0xff;
+ // TODO: StringBuilder.append(C) works, but StringBuilder.append(Ljava/lang/String;) doesn't.
+ System.logI("calling append...");
+ sb.append(digits[(b >> 4) & 0xf].charAt(0));
+ System.logI("...called append");
+ System.logI("calling append...");
+ sb.append(digits[b & 0xf].charAt(0));
+ System.logI("...called append");
+ }
+ System.logI("calling toString...");
+ String result = sb.toString();
+ System.logI("...called toString");
+ System.logI(result);
+ return 123;
+ }
+}