Merge "Implement sun.misc.Unsafe and fix the jfieldID/jmethodID leak." into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a2e05c5..5b4c08c 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1612,9 +1612,6 @@
// Link interface method tables
LinkInterfaceMethods(klass);
-
- // Insert stubs.
- LinkAbstractMethods(klass);
}
return true;
}
@@ -1797,16 +1794,6 @@
return true;
}
-void ClassLinker::LinkAbstractMethods(Class* klass) {
- for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
- Method* method = klass->GetVirtualMethodDuringLinking(i);
- if (method->IsAbstract()) {
- LG << "AbstractMethodError";
- // TODO: throw AbstractMethodError
- }
- }
-}
-
bool ClassLinker::LinkInstanceFields(Class* klass) {
CHECK(klass != NULL);
return LinkFields(klass, true);
diff --git a/src/class_linker.h b/src/class_linker.h
index b250593..88871f4 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -242,8 +242,6 @@
bool LinkInterfaceMethods(Class* klass);
- void LinkAbstractMethods(Class* klass);
-
bool LinkStaticFields(Class* klass);
bool LinkInstanceFields(Class* klass);
bool LinkFields(Class *klass, bool instance);
diff --git a/src/compiler.cc b/src/compiler.cc
index e2768bf..fb510bb 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -14,6 +14,30 @@
namespace art {
+typedef void (*ThrowAme)(Method*, Thread*);
+
+void ThrowAbstractMethodError(Method* method, Thread* thread) {
+ thread->ThrowNewException("Ljava/lang/AbstractMethodError",
+ "abstract method \"%s\"",
+ PrettyMethod(method).c_str());
+}
+
+namespace arm {
+ ByteArray* CreateAbstractMethodErrorStub(ThrowAme);
+}
+
+namespace x86 {
+ ByteArray* CreateAbstractMethodErrorStub(ThrowAme);
+}
+
+Compiler::Compiler(InstructionSet insns) : instruction_set_(insns), jni_compiler_(insns) {
+ if (insns == kArm || insns == kThumb2) {
+ abstract_method_error_stub_ = arm::CreateAbstractMethodErrorStub(&ThrowAbstractMethodError);
+ } else if (insns == kX86) {
+ abstract_method_error_stub_ = x86::CreateAbstractMethodErrorStub(&ThrowAbstractMethodError);
+ }
+}
+
void Compiler::CompileAll(const ClassLoader* class_loader) {
Resolve(class_loader);
// TODO add verification step
@@ -107,13 +131,17 @@
if (method->IsNative()) {
jni_compiler_.Compile(method);
} else if (method->IsAbstract()) {
- // TODO: This might be also noted in the ClassLinker.
- // Probably makes more sense to do here?
- UNIMPLEMENTED(WARNING) << "compile stub to throw AbstractMethodError";
+ DCHECK(abstract_method_error_stub_ != NULL);
+ if (instruction_set_ == kX86) {
+ method->SetCode(abstract_method_error_stub_, kX86);
+ } else {
+ CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
+ method->SetCode(abstract_method_error_stub_, kArm);
+ }
} else {
oatCompileMethod(method, kThumb2);
}
- // CHECK(method->GetCode() != NULL); // TODO: enable this check ASAP
+ CHECK(method->GetCode() != NULL);
if (instruction_set_ == kX86) {
art::x86::X86CreateInvokeStub(method);
diff --git a/src/compiler.h b/src/compiler.h
index e818a1c..24889e8 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,8 +12,7 @@
class Compiler {
public:
- explicit Compiler(InstructionSet insns) : instruction_set_(insns),
- jni_compiler_(insns) {}
+ explicit Compiler(InstructionSet insns);
// Compile all Methods of all the Classes of all the DexFiles that are part of a ClassLoader.
void CompileAll(const ClassLoader* class_loader);
@@ -40,6 +39,7 @@
InstructionSet instruction_set_;
JniCompiler jni_compiler_;
+ ByteArray* abstract_method_error_stub_;
DISALLOW_COPY_AND_ASSIGN(Compiler);
};
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 6784981..884f7a7 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -128,6 +128,10 @@
EXPECT_TRUE(method != NULL) << "method_idx=" << i
<< " " << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
<< " " << dex->GetMethodName(dex->GetMethodId(i));
+ EXPECT_TRUE(method->GetCode() != NULL) << "method_idx=" << i
+ << " "
+ << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+ << " " << dex->GetMethodName(dex->GetMethodId(i));
}
EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index 2e2f6a6..7939780 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -9,6 +9,34 @@
namespace art {
namespace arm {
+typedef void (*ThrowAme)(Method*, Thread*);
+
+ByteArray* CreateAbstractMethodErrorStub(ThrowAme throw_ame) {
+ UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
+
+ // R0 is the Method* already.
+
+ // Pass Thread::Current() in R1
+ __ mov(R1, ShifterOperand(R9));
+
+ // Call throw_ame to throw AbstractMethodError
+ __ LoadImmediate(R12, reinterpret_cast<int32_t>(throw_ame));
+ // Leaf call to routine that never returns
+ __ mov(PC, ShifterOperand(R12));
+
+ __ bkpt(0);
+
+ assembler->EmitSlowPaths();
+
+ size_t cs = assembler->CodeSize();
+ ByteArray* abstract_stub = ByteArray::Alloc(cs);
+ CHECK(abstract_stub != NULL);
+ MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
+ assembler->FinalizeInstructions(code);
+
+ return abstract_stub;
+}
+
ByteArray* CreateJniStub() {
UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
diff --git a/src/stub_x86.cc b/src/stub_x86.cc
index bddfc6c..ce9a875 100644
--- a/src/stub_x86.cc
+++ b/src/stub_x86.cc
@@ -9,6 +9,35 @@
namespace art {
namespace x86 {
+typedef void (*ThrowAme)(Method*, Thread*);
+
+ByteArray* CreateAbstractMethodErrorStub(ThrowAme throw_ame) {
+ UniquePtr<X86Assembler> assembler( static_cast<X86Assembler*>(Assembler::Create(kX86)) );
+
+ // Pad stack to ensure 16-byte alignment
+ __ pushl(Immediate(0));
+ __ pushl(Immediate(0));
+ __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // Thread*
+ __ pushl(EDI); // Method*
+
+ // Call throw_ame to throw AbstractMethodError
+ __ Call(reinterpret_cast<int32_t>(throw_ame), X86ManagedRegister::FromCpuRegister(ECX));
+
+ // Because the call above never returns, we do not need to do ESP+=16 here.
+
+ __ int3();
+
+ assembler->EmitSlowPaths();
+
+ size_t cs = assembler->CodeSize();
+ ByteArray* abstract_stub = ByteArray::Alloc(cs);
+ CHECK(abstract_stub != NULL);
+ MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
+ assembler->FinalizeInstructions(code);
+
+ return abstract_stub;
+}
+
ByteArray* CreateJniStub() {
UniquePtr<X86Assembler> assembler( static_cast<X86Assembler*>(Assembler::Create(kX86)) );