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;