Merge "Fix output of 107 art/test"
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 547c0f6..d544397 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -157,6 +157,8 @@
Instruction::GOTO,
Instruction::GOTO_16,
Instruction::GOTO_32,
+ Instruction::PACKED_SWITCH,
+ Instruction::SPARSE_SWITCH,
Instruction::IF_EQ,
Instruction::IF_NE,
Instruction::IF_LT,
@@ -248,8 +250,6 @@
Instruction::MOVE_OBJECT,
Instruction::MOVE_OBJECT_FROM16,
Instruction::MOVE_OBJECT_16,
- // Instruction::PACKED_SWITCH,
- // Instruction::SPARSE_SWITCH,
// Instruction::MOVE_RESULT,
// Instruction::MOVE_RESULT_WIDE,
// Instruction::MOVE_RESULT_OBJECT,
@@ -889,7 +889,9 @@
// TODO(Arm64): enable optimizations once backend is mature enough.
// TODO(X86_64): enable optimizations once backend is mature enough.
cu.disable_opt = ~(uint32_t)0;
- cu.enable_debug |= (1 << kDebugCodegenDump);
+ if (cu.instruction_set == kArm64) {
+ cu.enable_debug |= (1 << kDebugCodegenDump);
+ }
}
cu.StartTimingSplit("BuildMIRGraph");
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index b80938a..b85f569 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -68,7 +68,7 @@
// Get the switch value
rl_src = LoadValue(rl_src, kCoreReg);
- RegStorage r_base = AllocTemp();
+ RegStorage r_base = AllocTempWide();
// Allocate key and disp temps.
RegStorage r_key = AllocTemp();
RegStorage r_disp = AllocTemp();
@@ -95,7 +95,8 @@
tab_rec->anchor = switch_label;
// Add displacement to base branch address and go!
- OpRegRegRegShift(kOpAdd, r_base, r_base, r_disp, ENCODE_NO_SHIFT);
+ // TODO(Arm64): generate "add x1, x1, w3, sxtw" rather than "add x1, x1, x3"?
+ OpRegRegRegShift(kOpAdd, r_base, r_base, As64BitReg(r_disp), ENCODE_NO_SHIFT);
NewLIR1(kA64Br1x, r_base.GetReg());
// Loop exit label.
@@ -105,7 +106,7 @@
void Arm64Mir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset,
- RegLocation rl_src) {
+ RegLocation rl_src) {
const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
if (cu_->verbose) {
DumpPackedSwitchTable(table);
@@ -122,7 +123,7 @@
// Get the switch value
rl_src = LoadValue(rl_src, kCoreReg);
- RegStorage table_base = AllocTemp();
+ RegStorage table_base = AllocTempWide();
// Materialize a pointer to the switch table
NewLIR3(kA64Adr2xd, table_base.GetReg(), 0, WrapPointer(tab_rec));
int low_key = s4FromSwitchData(&table[2]);
@@ -140,15 +141,17 @@
// Load the displacement from the switch table
RegStorage disp_reg = AllocTemp();
- LoadBaseIndexed(table_base, key_reg, disp_reg, 2, k32);
+ // TODO(Arm64): generate "ldr w3, [x1,w2,sxtw #2]" rather than "ldr w3, [x1,x2,lsl #2]"?
+ LoadBaseIndexed(table_base, key_reg, As64BitReg(disp_reg), 2, k32);
// Get base branch address.
- RegStorage branch_reg = AllocTemp();
+ RegStorage branch_reg = AllocTempWide();
LIR* switch_label = NewLIR3(kA64Adr2xd, branch_reg.GetReg(), 0, -1);
tab_rec->anchor = switch_label;
// Add displacement to base branch address and go!
- OpRegRegRegShift(kOpAdd, branch_reg, branch_reg, disp_reg, ENCODE_NO_SHIFT);
+ // TODO(Arm64): generate "add x4, x4, w3, sxtw" rather than "add x4, x4, x3"?
+ OpRegRegRegShift(kOpAdd, branch_reg, branch_reg, As64BitReg(disp_reg), ENCODE_NO_SHIFT);
NewLIR1(kA64Br1x, branch_reg.GetReg());
// branch_over target here
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index 6251f4f..21db771 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -223,6 +223,40 @@
bool skip_this);
private:
+ /**
+ * @brief Given register xNN (dNN), returns register wNN (sNN).
+ * @param reg #RegStorage containing a Solo64 input register (e.g. @c x1 or @c d2).
+ * @return A Solo32 with the same register number as the @p reg (e.g. @c w1 or @c s2).
+ * @see As64BitReg
+ */
+ RegStorage As32BitReg(RegStorage reg) {
+ DCHECK(reg.Is64Bit());
+ DCHECK(!reg.IsPair());
+ RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
+ reg.GetRawBits() & RegStorage::kRegTypeMask);
+ DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
+ ->GetReg().GetReg(),
+ ret_val.GetReg());
+ return ret_val;
+ }
+
+ /**
+ * @brief Given register wNN (sNN), returns register xNN (dNN).
+ * @param reg #RegStorage containing a Solo32 input register (e.g. @c w1 or @c s2).
+ * @return A Solo64 with the same register number as the @p reg (e.g. @c x1 or @c d2).
+ * @see As32BitReg
+ */
+ RegStorage As64BitReg(RegStorage reg) {
+ DCHECK(reg.Is32Bit());
+ DCHECK(!reg.IsPair());
+ RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
+ reg.GetRawBits() & RegStorage::kRegTypeMask);
+ DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
+ ->GetReg().GetReg(),
+ ret_val.GetReg());
+ return ret_val;
+ }
+
LIR* LoadFPConstantValue(int r_dest, int32_t value);
LIR* LoadFPConstantValueWide(int r_dest, int64_t value);
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
diff --git a/compiler/dex/quick/arm64/fp_arm64.cc b/compiler/dex/quick/arm64/fp_arm64.cc
index acc7d17..265e8d2 100644
--- a/compiler/dex/quick/arm64/fp_arm64.cc
+++ b/compiler/dex/quick/arm64/fp_arm64.cc
@@ -45,6 +45,7 @@
case Instruction::REM_FLOAT_2ADDR:
case Instruction::REM_FLOAT:
FlushAllRegs(); // Send everything to home location
+ // TODO: Fix xSELF.
CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmodf), rl_src1, rl_src2,
false);
rl_result = GetReturn(kFPReg);
@@ -88,8 +89,15 @@
case Instruction::REM_DOUBLE_2ADDR:
case Instruction::REM_DOUBLE:
FlushAllRegs(); // Send everything to home location
- CallRuntimeHelperRegLocationRegLocation(QUICK_ENTRYPOINT_OFFSET(8, pFmod), rl_src1, rl_src2,
- false);
+ // TODO: Fix xSELF.
+ {
+ ThreadOffset<8> helper_offset = QUICK_ENTRYPOINT_OFFSET(8, pFmod);
+ RegStorage r_tgt = CallHelperSetup(helper_offset);
+ LoadValueDirectWideFixed(rl_src1, rs_d0);
+ LoadValueDirectWideFixed(rl_src2, rs_d1);
+ ClobberCallerSave();
+ CallHelper(r_tgt, helper_offset, false);
+ }
rl_result = GetReturnWide(kFPReg);
StoreValueWide(rl_dest, rl_result);
return;
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index d0ab4f6..4f0d7bc 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -532,11 +532,11 @@
switch (op) {
case kOpLsl: {
// "lsl w1, w2, #imm" is an alias of "ubfm w1, w2, #(-imm MOD 32), #(31-imm)"
- // and "lsl x1, x2, #imm" of "ubfm x1, x2, #(-imm MOD 32), #(31-imm)".
+ // and "lsl x1, x2, #imm" of "ubfm x1, x2, #(-imm MOD 64), #(63-imm)".
// For now, we just use ubfm directly.
- int max_value = (is_wide) ? 64 : 32;
+ int max_value = (is_wide) ? 63 : 31;
return NewLIR4(kA64Ubfm4rrdd | wide, r_dest.GetReg(), r_src1.GetReg(),
- (-value) & (max_value - 1), max_value - value);
+ (-value) & max_value, max_value - value);
}
case kOpLsr:
return NewLIR3(kA64Lsr3rrd | wide, r_dest.GetReg(), r_src1.GetReg(), value);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index ee68fe2..7a415a2 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -277,6 +277,8 @@
if (arg1.wide == 0) {
if (cu_->instruction_set == kMips) {
LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1));
+ } else if (cu_->instruction_set == kArm64) {
+ LoadValueDirectFixed(arg1, arg1.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
} else {
LoadValueDirectFixed(arg1, TargetReg(kArg1));
}
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index c383296..b52a4b7 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -896,7 +896,7 @@
}
void X86Mir2Lir::EmitOpRegOpcode(const X86EncodingMap* entry, uint8_t reg) {
- EmitPrefixAndOpcode(entry, reg, NO_REG, NO_REG);
+ EmitPrefixAndOpcode(entry, NO_REG, NO_REG, reg);
reg = LowRegisterBits(reg);
// There's no 3-byte instruction with +rd
DCHECK(entry->skeleton.opcode != 0x0F ||
@@ -909,7 +909,7 @@
}
void X86Mir2Lir::EmitOpReg(const X86EncodingMap* entry, uint8_t reg) {
- EmitPrefixAndOpcode(entry, reg, NO_REG, NO_REG);
+ EmitPrefixAndOpcode(entry, NO_REG, NO_REG, reg);
reg = LowRegisterBits(reg);
if (RegStorage::RegNum(reg) >= 4) {
DCHECK(strchr(entry->name, '8') == NULL) << entry->name << " "
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index d214b8d..b110793 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -2154,7 +2154,12 @@
LoadConstant(result_reg, 0);
LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg, 0, NULL);
- RegStorage check_class = AllocTypedTemp(false, kRefReg);
+ // We will use this register to compare to memory below.
+ // References are 32 bit in memory, and 64 bit in registers (in 64 bit mode).
+ // For this reason, force allocation of a 32 bit register to use, so that the
+ // compare to memory will be done using a 32 bit comparision.
+ // The LoadRefDisp(s) below will work normally, even in 64 bit mode.
+ RegStorage check_class = AllocTemp();
// If Method* is already in a register, we can save a copy.
RegLocation rl_method = mir_graph_->GetMethodLoc();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d7b673e..f5f7a86 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2464,7 +2464,7 @@
}
size_t Heap::GetPercentFree() {
- return static_cast<size_t>(100.0f * static_cast<float>(GetFreeMemory()) / GetMaxMemory());
+ return static_cast<size_t>(100.0f * static_cast<float>(GetFreeMemory()) / max_allowed_footprint_);
}
void Heap::SetIdealFootprint(size_t max_allowed_footprint) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index e568b36..9b49373 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -408,7 +408,7 @@
// Implements java.lang.Runtime.freeMemory.
size_t GetFreeMemory() const {
- return GetMaxMemory() - num_bytes_allocated_.LoadSequentiallyConsistent();
+ return max_allowed_footprint_ - num_bytes_allocated_.LoadSequentiallyConsistent();
}
// get the space that corresponds to an object's address. Current implementation searches all
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 74dfe91..6c44aa9 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -292,11 +292,14 @@
return false;
}
- oat_dex_files_.Put(dex_file_location, new OatDexFile(this,
- dex_file_location,
- dex_file_checksum,
- dex_file_pointer,
- methods_offsets_pointer));
+ OatDexFile* oat_dex_file = new OatDexFile(this,
+ dex_file_location,
+ dex_file_checksum,
+ dex_file_pointer,
+ methods_offsets_pointer);
+ // Use a StringPiece backed by the oat_dex_file's internal std::string as the key.
+ StringPiece key(oat_dex_file->GetDexFileLocation());
+ oat_dex_files_.Put(key, oat_dex_file);
}
return true;
}
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index d703731..eae0418 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -20,6 +20,7 @@
#include <string>
#include <vector>
+#include "base/stringpiece.h"
#include "dex_file.h"
#include "invoke_type.h"
#include "mem_map.h"
@@ -206,11 +207,11 @@
const byte* dex_file_pointer,
const uint32_t* oat_class_offsets_pointer);
- const OatFile* oat_file_;
- std::string dex_file_location_;
- uint32_t dex_file_location_checksum_;
- const byte* dex_file_pointer_;
- const uint32_t* oat_class_offsets_pointer_;
+ const OatFile* const oat_file_;
+ const std::string dex_file_location_;
+ const uint32_t dex_file_location_checksum_;
+ const byte* const dex_file_pointer_;
+ const uint32_t* const oat_class_offsets_pointer_;
friend class OatFile;
DISALLOW_COPY_AND_ASSIGN(OatDexFile);
@@ -270,7 +271,9 @@
// dlopen handle during runtime.
void* dlopen_handle_;
- typedef SafeMap<std::string, const OatDexFile*> Table;
+ // NOTE: We use a StringPiece as the key type to avoid a memory allocation on every lookup
+ // with a const char* key.
+ typedef SafeMap<StringPiece, const OatDexFile*> Table;
Table oat_dex_files_;
friend class OatClass;