diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2014-06-03 01:23:27 +0100 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2014-06-03 01:23:27 +0100 |
commit | 6ae6d126ba3b50d16b6ba61f39c3982a34a49eec (patch) | |
tree | f588c43e574217cd38777f8282314d250d9dbc6a | |
parent | 1ca6a11a61b57edea370adf4454876ccf869d92e (diff) | |
parent | d5e4ac0abdeeb4dc13bd05a40bf496299a787536 (diff) | |
download | art-cm-11.0.tar.gz art-cm-11.0.tar.bz2 art-cm-11.0.zip |
Merge tag 'android-4.4.3_r1' into HEADcm-11.0-XNPH44S-bacon-5fa8c79c0bcm-11.0-XNPH33R-bacon-3628510d76cm-11.0-XNPH30O-bacon-4f280f505acm-11.0-XNPH05Q-tomato-9828f8e9cccm-11.0-XNPH05Q-bacon-5229c4ef56stable/cm-11.0-XNG3Cstable/cm-11.0-XNG2Sstable/cm-11.0-XNF9Xstable/cm-11.0-XNF8Ystable/cm-11.0shipping/cm-11.0cm-11.0
Android 4.4.3 release 1
-rw-r--r-- | compiler/dex/quick/arm/utility_arm.cc | 3 | ||||
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 34 | ||||
-rw-r--r-- | compiler/dex/quick/gen_invoke.cc | 9 | ||||
-rw-r--r-- | compiler/dex/quick/mips/mips_lir.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 11 | ||||
-rw-r--r-- | compiler/dex/quick/x86/call_x86.cc | 6 | ||||
-rw-r--r-- | compiler/dex/quick/x86/utility_x86.cc | 1 | ||||
-rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 1 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 4 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 2 | ||||
-rw-r--r-- | runtime/oat.cc | 2 | ||||
-rw-r--r-- | runtime/thread.cc | 52 | ||||
-rw-r--r-- | test/018-stack-overflow/expected.txt | 3 | ||||
-rw-r--r-- | test/018-stack-overflow/src/Main.java | 37 | ||||
-rw-r--r-- | test/040-miranda/expected.txt | 2 | ||||
-rw-r--r-- | test/040-miranda/src/Main.java | 13 | ||||
-rw-r--r-- | test/044-proxy/expected.txt | 5 | ||||
-rw-r--r-- | test/044-proxy/src/BasicTest.java | 22 | ||||
-rw-r--r-- | test/JniTest/JniTest.java | 34 | ||||
-rw-r--r-- | test/JniTest/jni_test.cc | 44 |
21 files changed, 239 insertions, 50 deletions
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index c63de69284..f29e04b0fa 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -223,6 +223,9 @@ LIR* ArmMir2Lir::OpReg(OpKind op, int r_dest_src) { case kOpBlx: opcode = kThumbBlxR; break; + case kOpBx: + opcode = kThumbBx; + break; default: LOG(FATAL) << "Bad opcode " << op; } diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index f018c61819..8e31a25d92 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -16,6 +16,7 @@ #include "dex/compiler_ir.h" #include "dex/compiler_internals.h" +#include "dex/quick/arm/arm_lir.h" #include "dex/quick/mir_to_lir-inl.h" #include "entrypoints/quick/quick_entrypoints.h" #include "mirror/array.h" @@ -544,7 +545,9 @@ void Mir2Lir::HandleThrowLaunchPads() { ThreadOffset func_offset(-1); int v1 = lab->operands[2]; int v2 = lab->operands[3]; - bool target_x86 = (cu_->instruction_set == kX86); + const bool target_x86 = cu_->instruction_set == kX86; + const bool target_arm = cu_->instruction_set == kArm || cu_->instruction_set == kThumb2; + const bool target_mips = cu_->instruction_set == kMips; switch (lab->operands[0]) { case kThrowNullPointer: func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowNullPointer); @@ -602,21 +605,40 @@ void Mir2Lir::HandleThrowLaunchPads() { func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowNoSuchMethod); break; - case kThrowStackOverflow: + case kThrowStackOverflow: { func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow); // Restore stack alignment + int r_tgt = 0; + const int spill_size = (num_core_spills_ + num_fp_spills_) * 4; if (target_x86) { - OpRegImm(kOpAdd, TargetReg(kSp), frame_size_); + // - 4 to leave link register on stack. + OpRegImm(kOpAdd, TargetReg(kSp), frame_size_ - 4); + ClobberCalleeSave(); + } else if (target_arm) { + r_tgt = r12; + LoadWordDisp(TargetReg(kSp), spill_size - 4, TargetReg(kLr)); + OpRegImm(kOpAdd, TargetReg(kSp), spill_size); + ClobberCalleeSave(); + LoadWordDisp(rARM_SELF, func_offset.Int32Value(), r_tgt); } else { - OpRegImm(kOpAdd, TargetReg(kSp), (num_core_spills_ + num_fp_spills_) * 4); + DCHECK(target_mips); + DCHECK_EQ(num_fp_spills_, 0); // FP spills currently don't happen on mips. + // LR is offset 0 since we push in reverse order. + LoadWordDisp(TargetReg(kSp), 0, TargetReg(kLr)); + OpRegImm(kOpAdd, TargetReg(kSp), spill_size); + ClobberCalleeSave(); + r_tgt = CallHelperSetup(func_offset); // Doesn't clobber LR. + DCHECK_NE(r_tgt, TargetReg(kLr)); } - break; + CallHelper(r_tgt, func_offset, false /* MarkSafepointPC */, false /* UseLink */); + continue; + } default: LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0]; } ClobberCalleeSave(); int r_tgt = CallHelperSetup(func_offset); - CallHelper(r_tgt, func_offset, true /* MarkSafepointPC */); + CallHelper(r_tgt, func_offset, true /* MarkSafepointPC */, true /* UseLink */); } } diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 2a0a23c7cd..3a39669103 100644 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -33,7 +33,7 @@ namespace art { /* * To save scheduling time, helper calls are broken into two parts: generation of - * the helper target address, and the actuall call to the helper. Because x86 + * the helper target address, and the actual call to the helper. Because x86 * has a memory call operation, part 1 is a NOP for x86. For other targets, * load arguments between the two parts. */ @@ -42,12 +42,13 @@ int Mir2Lir::CallHelperSetup(ThreadOffset helper_offset) { } /* NOTE: if r_tgt is a temp, it will be freed following use */ -LIR* Mir2Lir::CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc) { +LIR* Mir2Lir::CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc, bool use_link) { LIR* call_inst; + OpKind op = use_link ? kOpBlx : kOpBx; if (cu_->instruction_set == kX86) { - call_inst = OpThreadMem(kOpBlx, helper_offset); + call_inst = OpThreadMem(op, helper_offset); } else { - call_inst = OpReg(kOpBlx, r_tgt); + call_inst = OpReg(op, r_tgt); FreeTemp(r_tgt); } if (safepoint_pc) { diff --git a/compiler/dex/quick/mips/mips_lir.h b/compiler/dex/quick/mips/mips_lir.h index 278fcefcbf..dfa837cfbb 100644 --- a/compiler/dex/quick/mips/mips_lir.h +++ b/compiler/dex/quick/mips/mips_lir.h @@ -138,7 +138,6 @@ namespace art { #define r_FRESULT1 r_F1 // Regs not used for Mips. -#define rMIPS_LR INVALID_REG #define rMIPS_PC INVALID_REG // RegisterLocation templates return values (r_V0, or r_V0/r_V1). @@ -278,6 +277,7 @@ enum MipsNativeRegisterPool { #define rMIPS_RET1 r_RESULT1 #define rMIPS_INVOKE_TGT r_T9 #define rMIPS_COUNT INVALID_REG +#define rMIPS_LR r_RA enum MipsShiftEncodings { kMipsLsl = 0x0, diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index a37ebd173f..d41204fc46 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -432,7 +432,7 @@ class Mir2Lir : public Backend { // Shared by all targets - implemented in gen_invoke.cc. int CallHelperSetup(ThreadOffset helper_offset); - LIR* CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc); + LIR* CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc, bool use_link = true); void CallRuntimeHelperImm(ThreadOffset helper_offset, int arg0, bool safepoint_pc); void CallRuntimeHelperReg(ThreadOffset helper_offset, int arg0, bool safepoint_pc); void CallRuntimeHelperRegLocation(ThreadOffset helper_offset, RegLocation arg0, diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index e8834320a9..93612dcf50 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -319,6 +319,7 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, { kX86Jmp8, kJmp, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP, { 0, 0, 0xEB, 0, 0, 0, 0, 0 }, "Jmp8", "!0t" }, { kX86Jmp32, kJmp, IS_UNARY_OP | IS_BRANCH | NEEDS_FIXUP, { 0, 0, 0xE9, 0, 0, 0, 0, 0 }, "Jmp32", "!0t" }, { kX86JmpR, kJmp, IS_UNARY_OP | IS_BRANCH | REG_USE0, { 0, 0, 0xFF, 0, 0, 4, 0, 0 }, "JmpR", "!0r" }, + { kX86JmpT, kJmp, IS_UNARY_OP | IS_BRANCH | IS_LOAD, { THREAD_PREFIX, 0, 0xFF, 0, 0, 4, 0, 0 }, "JmpT", "fs:[!0d]" }, { kX86CallR, kCall, IS_UNARY_OP | IS_BRANCH | REG_USE0, { 0, 0, 0xE8, 0, 0, 0, 0, 0 }, "CallR", "!0r" }, { kX86CallM, kCall, IS_BINARY_OP | IS_BRANCH | IS_LOAD | REG_USE0, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallM", "[!0r+!1d]" }, { kX86CallA, kCall, IS_QUAD_OP | IS_BRANCH | IS_LOAD | REG_USE01, { 0, 0, 0xFF, 0, 0, 2, 0, 0 }, "CallA", "[!0r+!1r<<!2d+!3d]" }, @@ -451,6 +452,8 @@ int X86Mir2Lir::GetInsnSize(LIR* lir) { return 2; // opcode + rel8 } else if (lir->opcode == kX86Jmp32) { return 5; // opcode + rel32 + } else if (lir->opcode == kX86JmpT) { + return ComputeSize(entry, 0, 0x12345678, false); // displacement size is always 32bit } else { DCHECK(lir->opcode == kX86JmpR); return 2; // opcode + modrm @@ -1349,7 +1352,13 @@ AssemblerStatus X86Mir2Lir::AssembleInstructions(uintptr_t start_addr) { EmitRegCond(entry, lir->operands[0], lir->operands[1]); break; case kJmp: // lir operands - 0: rel - EmitJmp(entry, lir->operands[0]); + if (entry->opcode == kX86JmpT) { + // This works since the instruction format for jmp and call is basically the same and + // EmitCallThread loads opcode info. + EmitCallThread(entry, lir->operands[0]); + } else { + EmitJmp(entry, lir->operands[0]); + } break; case kJcc: // lir operands - 0: rel, 1: CC, target assigned EmitJcc(entry, lir->operands[0], lir->operands[1]); diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc index 2be2aa9a0e..67388666b4 100644 --- a/compiler/dex/quick/x86/call_x86.cc +++ b/compiler/dex/quick/x86/call_x86.cc @@ -224,15 +224,15 @@ void X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { LockTemp(rX86_ARG2); /* Build frame, return address already on stack */ + // TODO: 64 bit. OpRegImm(kOpSub, rX86_SP, frame_size_ - 4); /* * We can safely skip the stack overflow check if we're * a leaf *and* our frame size < fudge factor. */ - bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && - (static_cast<size_t>(frame_size_) < - Thread::kStackOverflowReservedBytes)); + const bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && + (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes)); NewLIR0(kPseudoMethodEntry); /* Spill core callee saves */ SpillCoreRegs(); diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index c519bfec44..d03d4f8577 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -296,6 +296,7 @@ LIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) { X86OpCode opcode = kX86Bkpt; switch (op) { case kOpBlx: opcode = kX86CallT; break; + case kOpBx: opcode = kX86JmpT; break; default: LOG(FATAL) << "Bad opcode: " << op; break; diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 643a3d5b8f..8a813e88ea 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -362,6 +362,7 @@ enum X86OpCode { kX86Jcc8, kX86Jcc32, // jCC rel8/32; lir operands - 0: rel, 1: CC, target assigned kX86Jmp8, kX86Jmp32, // jmp rel8/32; lir operands - 0: rel, target assigned kX86JmpR, // jmp reg; lir operands - 0: reg + kX86JmpT, // jmp fs:[disp]; fs: is equal to Thread::Current(); lir operands - 0: disp kX86CallR, // call reg; lir operands - 0: reg kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp kX86CallA, // call [base + index * scale + disp] diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 412f96e4af..df863f07b7 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -291,8 +291,8 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con Class* field_type; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (sig[1] != '\0') { - ClassLoader* cl = GetClassLoader(soa); - field_type = class_linker->FindClass(sig, cl); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), c->GetClassLoader()); + field_type = class_linker->FindClass(sig, class_loader.get()); } else { field_type = class_linker->FindPrimitiveClass(*sig); } diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 1e1138745d..998ebe1a8f 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -241,7 +241,7 @@ inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* metho if (method->IsDirect()) { return method; } - if (method->GetDeclaringClass()->IsInterface()) { + if (method->GetDeclaringClass()->IsInterface() && !method->IsMiranda()) { return FindVirtualMethodForInterface(method); } return FindVirtualMethodForVirtual(method); diff --git a/runtime/oat.cc b/runtime/oat.cc index c01f77c364..6fe5d1097b 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -22,7 +22,7 @@ namespace art { const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '0', '7', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '0', '8', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); diff --git a/runtime/thread.cc b/runtime/thread.cc index 60a3bf8196..25418a9758 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1332,7 +1332,7 @@ class BuildInternalStackTraceVisitor : public StackVisitor { return true; // Ignore runtime frames (in particular callee save). } method_trace_->Set(count_, m); - dex_pc_trace_->Set(count_, GetDexPc()); + dex_pc_trace_->Set(count_, m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc()); ++count_; return true; } @@ -1384,7 +1384,6 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job mirror::ObjectArray<mirror::Object>* method_trace = soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal); int32_t depth = method_trace->GetLength() - 1; - mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth)); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); @@ -1413,19 +1412,34 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job for (int32_t i = 0; i < depth; ++i) { // Prepare parameters for StackTraceElement(String cls, String method, String file, int line) mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(method_trace->Get(i)); - mh.ChangeMethod(method); - uint32_t dex_pc = pc_trace->Get(i); - int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); - // Allocate element, potentially triggering GC - // TODO: reuse class_name_object via Class::name_? - const char* descriptor = mh.GetDeclaringClassDescriptor(); - CHECK(descriptor != NULL); - std::string class_name(PrettyDescriptor(descriptor)); - SirtRef<mirror::String> class_name_object(soa.Self(), - mirror::String::AllocFromModifiedUtf8(soa.Self(), - class_name.c_str())); - if (class_name_object.get() == NULL) { - return NULL; + MethodHelper mh(method); + int32_t line_number; + SirtRef<mirror::String> class_name_object(soa.Self(), nullptr); + SirtRef<mirror::String> source_name_object(soa.Self(), nullptr); + if (method->IsProxyMethod()) { + line_number = -1; + class_name_object.reset(method->GetDeclaringClass()->GetName()); + // source_name_object intentionally left null for proxy methods + } else { + mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth)); + uint32_t dex_pc = pc_trace->Get(i); + line_number = mh.GetLineNumFromDexPC(dex_pc); + // Allocate element, potentially triggering GC + // TODO: reuse class_name_object via Class::name_? + const char* descriptor = mh.GetDeclaringClassDescriptor(); + CHECK(descriptor != nullptr); + std::string class_name(PrettyDescriptor(descriptor)); + class_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str())); + if (class_name_object.get() == nullptr) { + return nullptr; + } + const char* source_file = mh.GetDeclaringClassSourceFile(); + if (source_file != nullptr) { + source_name_object.reset(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file)); + if (source_name_object.get() == nullptr) { + return nullptr; + } + } } const char* method_name = mh.GetName(); CHECK(method_name != NULL); @@ -1435,14 +1449,8 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job if (method_name_object.get() == NULL) { return NULL; } - const char* source_file = mh.GetDeclaringClassSourceFile(); - SirtRef<mirror::String> source_name_object(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), - source_file)); mirror::StackTraceElement* obj = mirror::StackTraceElement::Alloc(soa.Self(), - class_name_object.get(), - method_name_object.get(), - source_name_object.get(), - line_number); + class_name_object.get(), method_name_object.get(), source_name_object.get(), line_number); if (obj == NULL) { return NULL; } diff --git a/test/018-stack-overflow/expected.txt b/test/018-stack-overflow/expected.txt index 7797816785..98b45b7b21 100644 --- a/test/018-stack-overflow/expected.txt +++ b/test/018-stack-overflow/expected.txt @@ -1,2 +1,3 @@ -caught SOE +caught SOE in testSelfRecursion +caught SOE in testMutualRecursion SOE test done diff --git a/test/018-stack-overflow/src/Main.java b/test/018-stack-overflow/src/Main.java index f79c269c85..41adabc9ff 100644 --- a/test/018-stack-overflow/src/Main.java +++ b/test/018-stack-overflow/src/Main.java @@ -19,17 +19,46 @@ */ public class Main { public static void main(String args[]) { + testSelfRecursion(); + testMutualRecursion(); + System.out.println("SOE test done"); + } + + private static void testSelfRecursion() { try { stackOverflowTestSub(0.0, 0.0, 0.0); } catch (StackOverflowError soe) { - System.out.println("caught SOE"); + System.out.println("caught SOE in testSelfRecursion"); } - System.out.println("SOE test done"); } - private static void stackOverflowTestSub(double pad1, double pad2, - double pad3) { + private static void stackOverflowTestSub(double pad1, double pad2, double pad3) { stackOverflowTestSub(pad1, pad2, pad3); } + + private static void testMutualRecursion() { + try { + foo(0.0, 0.0, 0.0); + } + catch (StackOverflowError soe) { + System.out.println("caught SOE in testMutualRecursion"); + } + } + + private static void foo(double pad1, double pad2, double pad3) { + bar(pad1, pad2, pad3); + } + + private static void bar(double pad1, double pad2, double pad3) { + baz(pad1, pad2, pad3); + } + + private static void baz(double pad1, double pad2, double pad3) { + qux(pad1, pad2, pad3); + } + + private static void qux(double pad1, double pad2, double pad3) { + foo(pad1, pad2, pad3); + } } diff --git a/test/040-miranda/expected.txt b/test/040-miranda/expected.txt index e22bbd974c..011be2af86 100644 --- a/test/040-miranda/expected.txt +++ b/test/040-miranda/expected.txt @@ -10,3 +10,5 @@ MirandaAbstract / MirandaClass2: inInterface: true inInterface2: 28 inAbstract: true +Test getting miranda method via reflection: + caught expected NoSuchMethodException diff --git a/test/040-miranda/src/Main.java b/test/040-miranda/src/Main.java index 1fd8287ba0..ff5eba0a17 100644 --- a/test/040-miranda/src/Main.java +++ b/test/040-miranda/src/Main.java @@ -14,6 +14,8 @@ * limitations under the License. */ +import java.lang.reflect.Method; + /** * Miranda testing. */ @@ -37,5 +39,16 @@ public class Main { System.out.println(" inInterface: " + mira2.inInterface()); System.out.println(" inInterface2: " + mira2.inInterface2()); System.out.println(" inAbstract: " + mira2.inAbstract()); + + System.out.println("Test getting miranda method via reflection:"); + try { + Class mirandaClass = Class.forName("MirandaAbstract"); + Method mirandaMethod = mirandaClass.getDeclaredMethod("inInterface", (Class[]) null); + System.out.println(" did not expect to find miranda method"); + } catch (NoSuchMethodException nsme) { + System.out.println(" caught expected NoSuchMethodException"); + } catch (Exception e) { + System.out.println(" caught unexpected exception " + e); + } } } diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt index eafaf1d188..400a1619cd 100644 --- a/test/044-proxy/expected.txt +++ b/test/044-proxy/expected.txt @@ -42,6 +42,7 @@ Invoke public abstract java.lang.String Shapes.blob() (no args) --- blob Success: method blob res=mix +$Proxy1.getTrace null:-1 Invoke public abstract void Shapes.upChuck() (no args) Got expected ioobe @@ -49,8 +50,8 @@ Invoke public abstract void Shapes.upCheck() throws java.lang.InterruptedExcepti (no args) Got expected ie -Proxy interfaces: [interface Quads, interface Colors] -Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()] +Proxy interfaces: [interface Quads, interface Colors, interface Trace] +Proxy methods: [public final java.lang.String $Proxy1.blob(), public final double $Proxy1.blue(int), public final R0a $Proxy1.checkMe(), public final R0aa $Proxy1.checkMe(), public final R0base $Proxy1.checkMe(), public final void $Proxy1.circle(int), public final boolean $Proxy1.equals(java.lang.Object), public final void $Proxy1.getTrace(), public final int $Proxy1.green(double), public final int $Proxy1.hashCode(), public final int $Proxy1.mauve(java.lang.String), public final int $Proxy1.rectangle(int,int), public final int $Proxy1.red(float), public final int $Proxy1.square(int,int), public final java.lang.String $Proxy1.toString(), public final int $Proxy1.trapezoid(int,double,int), public final void $Proxy1.upCheck() throws java.lang.InterruptedException, public final void $Proxy1.upChuck()] Decl annos: [] Param annos (0) : [] Dupe threw expected exception diff --git a/test/044-proxy/src/BasicTest.java b/test/044-proxy/src/BasicTest.java index 46aa3feea2..ea46f49f2b 100644 --- a/test/044-proxy/src/BasicTest.java +++ b/test/044-proxy/src/BasicTest.java @@ -51,6 +51,8 @@ public class BasicTest { colors.blue(777); colors.mauve("sorry"); colors.blob(); + Trace trace = (Trace) proxy; + trace.getTrace(); try { shapes.upChuck(); @@ -96,7 +98,7 @@ public class BasicTest { /* create the proxy class */ Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(), - new Class[] { Quads.class, Colors.class }); + new Class[] { Quads.class, Colors.class, Trace.class }); /* create a proxy object, passing the handler object in */ Object proxy = null; @@ -156,6 +158,10 @@ interface Colors { public R0aa checkMe(); } +interface Trace { + public void getTrace(); +} + /* * Some return types. */ @@ -248,6 +254,20 @@ class MyInvocationHandler implements InvocationHandler { throw new RuntimeException("huh?"); } + if (method.getDeclaringClass() == Trace.class) { + if (method.getName().equals("getTrace")) { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + for (int i = 0; i < stackTrace.length; i++) { + StackTraceElement ste = stackTrace[i]; + if (ste.getMethodName().equals("getTrace")) { + System.out.println(ste.getClassName() + "." + ste.getMethodName() + " " + + ste.getFileName() + ":" + ste.getLineNumber()); + } + } + return null; + } + } + System.out.println("Invoke " + method); if (args == null || args.length == 0) { System.out.println(" (no args)"); diff --git a/test/JniTest/JniTest.java b/test/JniTest/JniTest.java index 7014ef9334..9194da581f 100644 --- a/test/JniTest/JniTest.java +++ b/test/JniTest/JniTest.java @@ -14,15 +14,30 @@ * limitations under the License. */ +import java.lang.reflect.Method; + class JniTest { public static void main(String[] args) { System.loadLibrary("arttest"); testFindClassOnAttachedNativeThread(); + testFindFieldOnAttachedNativeThread(); testCallStaticVoidMethodOnSubClass(); + testGetMirandaMethod(); } private static native void testFindClassOnAttachedNativeThread(); + private static boolean testFindFieldOnAttachedNativeThreadField; + + private static void testFindFieldOnAttachedNativeThread() { + testFindFieldOnAttachedNativeThreadNative(); + if (!testFindFieldOnAttachedNativeThreadField) { + throw new AssertionError(); + } + } + + private static native void testFindFieldOnAttachedNativeThreadNative(); + private static void testCallStaticVoidMethodOnSubClass() { testCallStaticVoidMethodOnSubClassNative(); if (!testCallStaticVoidMethodOnSubClass_SuperClass.executed) { @@ -42,4 +57,23 @@ class JniTest { private static class testCallStaticVoidMethodOnSubClass_SubClass extends testCallStaticVoidMethodOnSubClass_SuperClass { } + + private static native Method testGetMirandaMethodNative(); + + private static void testGetMirandaMethod() { + Method m = testGetMirandaMethodNative(); + if (m.getDeclaringClass() != testGetMirandaMethod_MirandaInterface.class) { + throw new AssertionError(); + } + } + + private static abstract class testGetMirandaMethod_MirandaAbstract implements testGetMirandaMethod_MirandaInterface { + public boolean inAbstract() { + return true; + } + } + + private static interface testGetMirandaMethod_MirandaInterface { + public boolean inInterface(); + } } diff --git a/test/JniTest/jni_test.cc b/test/JniTest/jni_test.cc index 72a3309d9d..d15e180c02 100644 --- a/test/JniTest/jni_test.cc +++ b/test/JniTest/jni_test.cc @@ -67,6 +67,42 @@ extern "C" JNIEXPORT void JNICALL Java_JniTest_testFindClassOnAttachedNativeThre assert(pthread_join_result == 0); } +static void* testFindFieldOnAttachedNativeThread(void*) { + assert(jvm != NULL); + + JNIEnv* env = NULL; + JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL }; + int attach_result = jvm->AttachCurrentThread(&env, &args); + assert(attach_result == 0); + + jclass clazz = env->FindClass("JniTest"); + assert(clazz != NULL); + assert(!env->ExceptionCheck()); + + jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z"); + assert(field != NULL); + assert(!env->ExceptionCheck()); + + env->SetStaticBooleanField(clazz, field, JNI_TRUE); + + int detach_result = jvm->DetachCurrentThread(); + assert(detach_result == 0); + return NULL; +} + +extern "C" JNIEXPORT void JNICALL Java_JniTest_testFindFieldOnAttachedNativeThreadNative(JNIEnv*, + jclass) { + pthread_t pthread; + int pthread_create_result = pthread_create(&pthread, + NULL, + testFindFieldOnAttachedNativeThread, + NULL); + assert(pthread_create_result == 0); + int pthread_join_result = pthread_join(pthread, NULL); + assert(pthread_join_result == 0); +} + + // http://b/11243757 extern "C" JNIEXPORT void JNICALL Java_JniTest_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, jclass) { @@ -81,3 +117,11 @@ extern "C" JNIEXPORT void JNICALL Java_JniTest_testCallStaticVoidMethodOnSubClas env->CallStaticVoidMethod(sub_class, execute); } + +extern "C" JNIEXPORT jobject JNICALL Java_JniTest_testGetMirandaMethodNative(JNIEnv* env, jclass) { + jclass abstract_class = env->FindClass("JniTest$testGetMirandaMethod_MirandaAbstract"); + assert(abstract_class != NULL); + jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z"); + assert(miranda_method != NULL); + return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE); +} |