Skip to content

Commit

Permalink
Merge tag 'android-4.4.3_r1' into HEAD
Browse files Browse the repository at this point in the history
Android 4.4.3 release 1
  • Loading branch information
rmcc committed Jun 3, 2014
2 parents 1ca6a11 + d5e4ac0 commit 6ae6d12
Show file tree
Hide file tree
Showing 21 changed files with 239 additions and 50 deletions.
3 changes: 3 additions & 0 deletions compiler/dex/quick/arm/utility_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
34 changes: 28 additions & 6 deletions compiler/dex/quick/gen_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */);
}
}

Expand Down
9 changes: 5 additions & 4 deletions compiler/dex/quick/gen_invoke.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/dex/quick/mips/mips_lir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/dex/quick/mir_to_lir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 10 additions & 1 deletion compiler/dex/quick/x86/assemble_x86.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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]" },
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]);
Expand Down
6 changes: 3 additions & 3 deletions compiler/dex/quick/x86/call_x86.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions compiler/dex/quick/x86/utility_x86.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions compiler/dex/quick/x86/x86_lir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions runtime/jni_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/mirror/class-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion runtime/oat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
52 changes: 30 additions & 22 deletions runtime/thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion test/018-stack-overflow/expected.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
caught SOE
caught SOE in testSelfRecursion
caught SOE in testMutualRecursion
SOE test done
37 changes: 33 additions & 4 deletions test/018-stack-overflow/src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
2 changes: 2 additions & 0 deletions test/040-miranda/expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ MirandaAbstract / MirandaClass2:
inInterface: true
inInterface2: 28
inAbstract: true
Test getting miranda method via reflection:
caught expected NoSuchMethodException
13 changes: 13 additions & 0 deletions test/040-miranda/src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

import java.lang.reflect.Method;

/**
* Miranda testing.
*/
Expand All @@ -37,5 +39,16 @@ public static void main(String[] args) {
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);
}
}
}
Loading

0 comments on commit 6ae6d12

Please sign in to comment.