diff options
-rw-r--r-- | src/class_linker.cc | 6 | ||||
-rw-r--r-- | src/compiler/RuntimeUtilities.cc | 4 | ||||
-rw-r--r-- | src/compiler_test.cc | 40 | ||||
-rw-r--r-- | src/jni_internal.cc | 22 | ||||
-rw-r--r-- | src/mark_sweep.cc | 8 | ||||
-rw-r--r-- | src/object.cc | 73 | ||||
-rw-r--r-- | src/object.h | 4 | ||||
-rw-r--r-- | test/SystemMethods/SystemMethods.java | 65 |
8 files changed, 138 insertions, 84 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 211b87d..b8cd891 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -1177,7 +1177,7 @@ Class* ClassLinker::LookupClass(const StringPiece& descriptor, const ClassLoader bool ClassLinker::InitializeClass(Class* klass) { CHECK(klass->GetStatus() == Class::kStatusResolved || - klass->GetStatus() == Class::kStatusError); + klass->GetStatus() == Class::kStatusError) << klass->GetStatus(); Thread* self = Thread::Current(); @@ -1270,9 +1270,7 @@ bool ClassLinker::InitializeClass(Class* klass) { Method* clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V"); if (clinit != NULL) { - // JValue unused; - // TODO: dvmCallMethod(self, method, NULL, &unused); - // UNIMPLEMENTED(FATAL); + clinit->Invoke(self, NULL, NULL, NULL); } { diff --git a/src/compiler/RuntimeUtilities.cc b/src/compiler/RuntimeUtilities.cc index 298cef1..8c94d62 100644 --- a/src/compiler/RuntimeUtilities.cc +++ b/src/compiler/RuntimeUtilities.cc @@ -73,7 +73,9 @@ void HandleFillArrayDataFromCode(Array* array, const uint16_t* table) { uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16); uint32_t size_in_bytes = size * table[1]; - UNIMPLEMENTED(WARNING) << "Need to check if array.length() <= size"; + if (static_cast<int32_t>(size) > array->GetLength()) { + UNIMPLEMENTED(FATAL) << "need to throw AIOOBE and unwind"; + } memcpy((char*)array + art::Array::DataOffset().Int32Value(), (char*)&table[4], size_in_bytes); } diff --git a/src/compiler_test.cc b/src/compiler_test.cc index a1aadc8..b11dff6 100644 --- a/src/compiler_test.cc +++ b/src/compiler_test.cc @@ -296,35 +296,63 @@ TEST_F(CompilerTest, SystemMethodsTest) { 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", "_getChars", "(II[CI)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>", "()V"); CompileDirectMethod(NULL, "java.lang.AbstractStringBuilder", "<init>", "(I)V"); - CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "(Ljava/lang/String;)V"); + CompileDirectMethod(NULL, "java.lang.AbstractStringBuilder", "enlargeBuffer", "(I)V"); CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "(C)V"); + CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "(Ljava/lang/String;)V"); + CompileVirtualMethod(NULL, "java.lang.AbstractStringBuilder", "append0", "([CII)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>", "()V"); 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", "append", "(I)Ljava/lang/StringBuilder;"); + CompileVirtualMethod(NULL, "java.lang.StringBuilder", "append", "(J)Ljava/lang/StringBuilder;"); + CompileVirtualMethod(NULL, "java.lang.StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;"); CompileVirtualMethod(NULL, "java.lang.StringBuilder", "toString", "()Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.ThreadLocal", "<init>", "()V"); + CompileVirtualMethod(NULL, "java.lang.ThreadLocal", "get", "()Ljava/lang/Object;"); + + CompileDirectMethod(NULL, "java.lang.Long", "toHexString", "(J)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.Long", "toString", "(J)Ljava/lang/String;"); CompileDirectMethod(NULL, "java.lang.Long", "toString", "(JI)Ljava/lang/String;"); + + CompileDirectMethod(NULL, "java.lang.IntegralToString", "<clinit>", "()V"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "appendInt", "(Ljava/lang/AbstractStringBuilder;I)V"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "appendLong", "(Ljava/lang/AbstractStringBuilder;J)V"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "convertInt", "(Ljava/lang/AbstractStringBuilder;I)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "convertLong", "(Ljava/lang/AbstractStringBuilder;J)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "intIntoCharArray", "([CII)I"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "intToHexString", "(IZI)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToHexString", "(J)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToString", "(J)Ljava/lang/String;"); CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToString", "(JI)Ljava/lang/String;"); + CompileDirectMethod(NULL, "java.lang.IntegralToString", "stringOf", "([C)Ljava/lang/String;"); CompileDirectMethod(NULL, "java.lang.System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"); + CompileDirectMethod(NULL, "java.lang.System", "currentTimeMillis", "()J"); 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"); + CompileDirectMethod(NULL, "java.lang.System", "logI", "(Ljava/lang/String;Ljava/lang/Throwable;)V"); + + CompileDirectMethod(NULL, "java.util.Arrays", "checkOffsetAndCount", "(III)V"); const ClassLoader* class_loader = LoadDex("SystemMethods"); + + CompileDirectMethod(class_loader, "SystemMethods", "<clinit>", "()V"); + AssertStaticIntMethod(class_loader, "SystemMethods", "test0", "()I", 123); AssertStaticIntMethod(class_loader, "SystemMethods", "test1", "()I", 123); AssertStaticIntMethod(class_loader, "SystemMethods", "test2", "()I", 123); + AssertStaticIntMethod(class_loader, "SystemMethods", "test3", "()I", 123); + AssertStaticIntMethod(class_loader, "SystemMethods", "test4", "()I", 123); } diff --git a/src/jni_internal.cc b/src/jni_internal.cc index bd1ccec..ef15e8e 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -196,28 +196,8 @@ byte* CreateArgArray(ScopedJniThreadState& ts, Method* method, jvalue* args) { JValue InvokeWithArgArray(ScopedJniThreadState& ts, Object* receiver, Method* method, byte* args) { - Thread* self = ts.Self(); - - // Push a transition back into managed code onto the linked list in thread - CHECK_EQ(Thread::kRunnable, self->GetState()); - NativeToManagedRecord record; - self->PushNativeToManagedRecord(&record); - - // Call the invoke stub associated with the method - // Pass everything as arguments - const Method::InvokeStub* stub = method->GetInvokeStub(); JValue result; - - if (method->HasCode() && stub != NULL) { - (*stub)(method, receiver, self, args, &result); - } else { - LOG(WARNING) << "Not invoking method with no associated code: " - << PrettyMethod(method); - result.j = 0; - } - - // Pop transition - self->PopNativeToManagedRecord(record); + method->Invoke(ts.Self(), receiver, args, &result); return result; } diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc index ac9a7cd..a2f1a56 100644 --- a/src/mark_sweep.cc +++ b/src/mark_sweep.cc @@ -511,11 +511,11 @@ void MarkSweep::EnqueueClearedReferences(Object** cleared) { if (*cleared != NULL) { Thread* self = Thread::Current(); DCHECK(self != NULL); - // TODO: Method *meth = gDvm.methJavaLangRefReferenceQueueAdd; - // DCHECK(meth != NULL); - // JValue unused; + // TODO: Method* m = gDvm.methJavaLangRefReferenceQueueAdd; + // DCHECK(m != NULL); // Object* reference = *cleared; - // TODO: dvmCallMethod(self, meth, NULL, &unused, reference); + // args = {reference} + // TODO: m->Invoke(self, NULL, args, NULL); UNIMPLEMENTED(FATAL); *cleared = NULL; } diff --git a/src/object.cc b/src/object.cc index f92f746..8b0c976 100644 --- a/src/object.cc +++ b/src/object.cc @@ -56,57 +56,48 @@ Class* Field::GetType() const { return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this); } -uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return 0; +Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer) { + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Field* f = class_linker->ResolveField(field_idx, referrer); + if (f != NULL) { + Class* c = f->GetDeclaringClass(); + // If the class is already initializing, we must be inside <clinit>, or + // we'd still be waiting for the lock. + if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c)) { + return f; + } } + UNIMPLEMENTED(FATAL) << "throw an error and unwind"; + return NULL; +} + +uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) { + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t)); return field->Get32(NULL); } void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return; - } + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t)); field->Set32(NULL, new_value); } uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return 0; - } + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t)); return field->Get64(NULL); } void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return; - } + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t)); field->Set64(NULL, new_value); } Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return 0; - } + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(!field->GetType()->IsPrimitive()); return field->GetObj(NULL); } void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) { - Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer); - if (field == NULL) { - UNIMPLEMENTED(FATAL) << "throw an error"; - return; - } + Field* field = FindFieldFromCode(field_idx, referrer); DCHECK(!field->GetType()->IsPrimitive()); field->SetObj(NULL, new_value); } @@ -483,6 +474,28 @@ void Method::SetInvokeStub(const ByteArray* invoke_stub_array) { OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), invoke_stub, false); } +void Method::Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const { + // Push a transition back into managed code onto the linked list in thread. + CHECK_EQ(Thread::kRunnable, self->GetState()); + NativeToManagedRecord record; + self->PushNativeToManagedRecord(&record); + + // Call the invoke stub associated with the method. + // Pass everything as arguments. + const Method::InvokeStub* stub = GetInvokeStub(); + if (HasCode() && stub != NULL) { + (*stub)(this, receiver, self, args, result); + } else { + LOG(WARNING) << "Not invoking method with no associated code: " << PrettyMethod(this); + if (result != NULL) { + result->j = 0; + } + } + + // Pop transition. + self->PopNativeToManagedRecord(record); +} + void Class::SetStatus(Status new_status) { CHECK(new_status > GetStatus() || new_status == kStatusError || Runtime::Current() == NULL); // no runtime implies we're not initialized diff --git a/src/object.h b/src/object.h index 9b3bf88..8504612 100644 --- a/src/object.h +++ b/src/object.h @@ -602,7 +602,7 @@ class Field : public AccessibleObject { class Method : public AccessibleObject { public: // An function that invokes a method with an array of its arguments. - typedef void InvokeStub(Method* method, + typedef void InvokeStub(const Method* method, Object* obj, Thread* thread, byte* args, @@ -833,6 +833,8 @@ class Method : public AccessibleObject { // Size in bytes of the return value size_t ReturnSize() const; + void Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const; + const ByteArray* GetCodeArray() const { return GetFieldPtr<const ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), false); } diff --git a/test/SystemMethods/SystemMethods.java b/test/SystemMethods/SystemMethods.java index f14df18..3d76548 100644 --- a/test/SystemMethods/SystemMethods.java +++ b/test/SystemMethods/SystemMethods.java @@ -24,7 +24,6 @@ class SystemMethods { 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; @@ -34,31 +33,63 @@ class SystemMethods { return 123; } + private static String[] STRING_DIGITS = new String[] { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f", + }; + 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"); + sb.append(STRING_DIGITS[(b >> 4) & 0xf]); + sb.append(STRING_DIGITS[b & 0xf]); } - System.logI("calling toString..."); String result = sb.toString(); - System.logI("...called toString"); System.logI(result); return 123; } + + private static char[] DIGITS = new char[] { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z' + }; + + public static int test3() { + long t = System.currentTimeMillis(); + + long v = t; + // int i = (int) v; + // if (v >= 0 && i == v) { + // return intToHexString(i, false, 0); + // } + + int bufLen = 16; // Max number of hex digits in a long + char[] buf = new char[bufLen]; + int cursor = bufLen; + + do { + buf[--cursor] = DIGITS[((int) v) & 0xF]; + } while ((v >>>= 4) != 0); + + String s = new String(buf, cursor, bufLen - cursor); + System.logI(s); + + System.logI(IntegralToString.longToHexString(t)); + System.logI(Long.toHexString(t)); + System.logI(Long.toString(t)); + return 123; + } + + private static int i = 4; + private static long j = 0x0123456789abcdefL; + + public static int test4() { + String s = "int=" + i + " long=" + j; + System.logI(s); + return 123; + } } |