Merge "Restrict Mac OS 10.5 devices to 1 dex2oat thread." into ics-mr1-plus-art
diff --git a/src/compiler_llvm/compiler_runtime_func_list.h b/src/compiler_llvm/compiler_runtime_func_list.h
new file mode 100644
index 0000000..5cf5bb5
--- /dev/null
+++ b/src/compiler_llvm/compiler_runtime_func_list.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// NOTE: COMPILER_RUNTIME_FUNC_LIST should be sorted!
+
+#if defined(__i386__) || defined(__mips__)
+
+#define COMPILER_RUNTIME_FUNC_LIST(V) \
+  V(__ashldi3) \
+  V(__ashrdi3) \
+  V(__divdi3) \
+  V(__fixdfdi) \
+  V(__fixsfdi) \
+  V(__fixtfdi) \
+  V(__fixtfsi) \
+  V(__fixunsdfdi) \
+  V(__fixunsdfsi) \
+  V(__fixunssfdi) \
+  V(__fixunssfsi) \
+  V(__fixunstfdi) \
+  V(__fixunstfsi) \
+  V(__fixunsxfdi) \
+  V(__fixunsxfsi) \
+  V(__fixxfdi) \
+  V(__floatdidf) \
+  V(__floatdisf) \
+  V(__floatditf) \
+  V(__floatdixf) \
+  V(__floatsitf) \
+  V(__floatundidf) \
+  V(__floatundisf) \
+  V(__floatunditf) \
+  V(__floatundixf) \
+  V(__floatunsitf) \
+  V(__lshrdi3) \
+  V(__moddi3) \
+  V(__muldi3) \
+  V(__negdi2) \
+  V(__powidf2) \
+  V(__powisf2) \
+  V(__powitf2) \
+  V(__powixf2) \
+  V(__trunctfdf2) \
+  V(__trunctfsf2) \
+  V(__udivdi3) \
+  V(__umoddi3) \
+  V(ceil) \
+  V(ceilf) \
+  V(ceill) \
+  V(copysign) \
+  V(copysignf) \
+  V(copysignl) \
+  V(cos) \
+  V(cosf) \
+  V(cosl) \
+  V(exp) \
+  V(exp2) \
+  V(exp2f) \
+  V(exp2l) \
+  V(expf) \
+  V(expl) \
+  V(floor) \
+  V(floorf) \
+  V(floorl) \
+  V(fma) \
+  V(fmaf) \
+  V(fmal) \
+  V(fmod) \
+  V(fmodf) \
+  V(fmodl) \
+  V(log) \
+  V(log10) \
+  V(log10f) \
+  V(log10l) \
+  V(log2) \
+  V(log2f) \
+  V(log2l) \
+  V(logf) \
+  V(logl) \
+  V(memcpy) \
+  V(memmove) \
+  V(memset) \
+  V(nearbyint) \
+  V(nearbyintf) \
+  V(nearbyintl) \
+  V(pow) \
+  V(powf) \
+  V(powl) \
+  V(rint) \
+  V(rintf) \
+  V(rintl) \
+  V(sin) \
+  V(sinf) \
+  V(sinl) \
+  V(sqrt) \
+  V(sqrtf) \
+  V(sqrtl) \
+  V(trunc) \
+  V(truncf) \
+  V(truncl)
+
+#elif defined(__arm__)
+
+#define COMPILER_RUNTIME_FUNC_LIST(V) \
+  V(__aeabi_d2f) \
+  V(__aeabi_d2iz) \
+  V(__aeabi_d2lz) \
+  V(__aeabi_d2uiz) \
+  V(__aeabi_d2ulz) \
+  V(__aeabi_dadd) \
+  V(__aeabi_dcmpeq) \
+  V(__aeabi_dcmpeq) \
+  V(__aeabi_dcmpge) \
+  V(__aeabi_dcmpgt) \
+  V(__aeabi_dcmple) \
+  V(__aeabi_dcmplt) \
+  V(__aeabi_dcmpun) \
+  V(__aeabi_dcmpun) \
+  V(__aeabi_ddiv) \
+  V(__aeabi_dmul) \
+  V(__aeabi_dsub) \
+  V(__aeabi_f2d) \
+  V(__aeabi_f2iz) \
+  V(__aeabi_f2lz) \
+  V(__aeabi_f2uiz) \
+  V(__aeabi_f2ulz) \
+  V(__aeabi_fadd) \
+  V(__aeabi_fcmpeq) \
+  V(__aeabi_fcmpeq) \
+  V(__aeabi_fcmpge) \
+  V(__aeabi_fcmpgt) \
+  V(__aeabi_fcmple) \
+  V(__aeabi_fcmplt) \
+  V(__aeabi_fcmpun) \
+  V(__aeabi_fcmpun) \
+  V(__aeabi_fdiv) \
+  V(__aeabi_fmul) \
+  V(__aeabi_fsub) \
+  V(__aeabi_i2d) \
+  V(__aeabi_i2f) \
+  V(__aeabi_idiv) \
+  V(__aeabi_idiv) \
+  V(__aeabi_idiv) \
+  V(__aeabi_l2d) \
+  V(__aeabi_l2f) \
+  V(__aeabi_lasr) \
+  V(__aeabi_ldivmod) \
+  V(__aeabi_llsl) \
+  V(__aeabi_llsr) \
+  V(__aeabi_lmul) \
+  V(__aeabi_memcpy) \
+  V(__aeabi_memmove) \
+  V(__aeabi_memset) \
+  V(__aeabi_ui2d) \
+  V(__aeabi_ui2f) \
+  V(__aeabi_uidiv) \
+  V(__aeabi_uidiv) \
+  V(__aeabi_uidiv) \
+  V(__aeabi_ul2d) \
+  V(__aeabi_ul2f) \
+  V(__aeabi_uldivmod)
+
+#else
+
+#error "Unknown target platform"
+
+#endif
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 890eeab..09b84ad 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -804,15 +804,15 @@
     break;
 
   case Instruction::SHL_INT:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shl, kInt, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
     break;
 
   case Instruction::SHR_INT:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shr, kInt, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
     break;
 
   case Instruction::USHR_INT:
-    EmitInsn_IntArithm(ARGS, kIntArithm_UShr, kInt, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
     break;
 
   case Instruction::ADD_LONG:
@@ -848,15 +848,15 @@
     break;
 
   case Instruction::SHL_LONG:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shl, kLong, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
     break;
 
   case Instruction::SHR_LONG:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shr, kLong, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
     break;
 
   case Instruction::USHR_LONG:
-    EmitInsn_IntArithm(ARGS, kIntArithm_UShr, kLong, false);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
     break;
 
   case Instruction::ADD_FLOAT:
@@ -932,15 +932,15 @@
     break;
 
   case Instruction::SHL_INT_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shl, kInt, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
     break;
 
   case Instruction::SHR_INT_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shr, kInt, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
     break;
 
   case Instruction::USHR_INT_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_UShr, kInt, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
     break;
 
   case Instruction::ADD_LONG_2ADDR:
@@ -976,15 +976,15 @@
     break;
 
   case Instruction::SHL_LONG_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shl, kLong, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
     break;
 
   case Instruction::SHR_LONG_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_Shr, kLong, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
     break;
 
   case Instruction::USHR_LONG_2ADDR:
-    EmitInsn_IntArithm(ARGS, kIntArithm_UShr, kLong, true);
+    EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
     break;
 
   case Instruction::ADD_FLOAT_2ADDR:
@@ -1068,15 +1068,15 @@
     break;
 
   case Instruction::SHL_INT_LIT8:
-    EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Shl);
+    EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
     break;
 
   case Instruction::SHR_INT_LIT8:
-    EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Shr);
+    EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
     break;
 
   case Instruction::USHR_INT_LIT8:
-    EmitInsn_IntArithmImmediate(ARGS, kIntArithm_UShr);
+    EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
     break;
 
   case Instruction::UNUSED_3E:
@@ -3300,27 +3300,6 @@
   case kIntArithm_Xor:
     return irb_.CreateXor(lhs, rhs);
 
-  case kIntArithm_Shl:
-    if (op_jty == kLong) {
-      return irb_.CreateShl(lhs, irb_.CreateAnd(rhs, 0x3f));
-    } else {
-      return irb_.CreateShl(lhs, irb_.CreateAnd(rhs, 0x1f));
-    }
-
-  case kIntArithm_Shr:
-    if (op_jty == kLong) {
-      return irb_.CreateAShr(lhs, irb_.CreateAnd(rhs, 0x3f));
-    } else {
-      return irb_.CreateAShr(lhs, irb_.CreateAnd(rhs, 0x1f));
-    }
-
-  case kIntArithm_UShr:
-    if (op_jty == kLong) {
-      return irb_.CreateLShr(lhs, irb_.CreateAnd(rhs, 0x3f));
-    } else {
-      return irb_.CreateLShr(lhs, irb_.CreateAnd(rhs, 0x1f));
-    }
-
   default:
     LOG(FATAL) << "Unknown integer arithmetic kind: " << arithm;
     return NULL;
@@ -3328,6 +3307,92 @@
 }
 
 
+void MethodCompiler::EmitInsn_IntShiftArithm(uint32_t dex_pc,
+                                             Instruction const* insn,
+                                             IntShiftArithmKind arithm,
+                                             JType op_jty,
+                                             bool is_2addr) {
+
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Value* src1_value;
+  llvm::Value* src2_value;
+
+  // NOTE: The 2nd operand of the shift arithmetic instruction is
+  // 32-bit integer regardless of the 1st operand.
+  if (is_2addr) {
+    src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
+    src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+  } else {
+    src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
+    src2_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
+  }
+
+  llvm::Value* result_value =
+    EmitIntShiftArithmResultComputation(dex_pc, src1_value, src2_value,
+                                        arithm, op_jty);
+
+  EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+}
+
+
+void MethodCompiler::
+EmitInsn_IntShiftArithmImmediate(uint32_t dex_pc,
+                                 Instruction const* insn,
+                                 IntShiftArithmKind arithm) {
+
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+
+  llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
+
+  llvm::Value* result_value =
+    EmitIntShiftArithmResultComputation(dex_pc, src_value, imm_value,
+                                        arithm, kInt);
+
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+}
+
+
+llvm::Value*
+MethodCompiler::EmitIntShiftArithmResultComputation(uint32_t dex_pc,
+                                                    llvm::Value* lhs,
+                                                    llvm::Value* rhs,
+                                                    IntShiftArithmKind arithm,
+                                                    JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  if (op_jty == kInt) {
+    rhs = irb_.CreateAnd(rhs, 0x1f);
+  } else {
+    llvm::Value* masked_rhs = irb_.CreateAnd(rhs, 0x3f);
+    rhs = irb_.CreateZExt(masked_rhs, irb_.getJLongTy());
+  }
+
+  switch (arithm) {
+  case kIntArithm_Shl:
+    return irb_.CreateShl(lhs, rhs);
+
+  case kIntArithm_Shr:
+    return irb_.CreateAShr(lhs, rhs);
+
+  case kIntArithm_UShr:
+    return irb_.CreateLShr(lhs, rhs);
+
+  default:
+    LOG(FATAL) << "Unknown integer shift arithmetic kind: " << arithm;
+    return NULL;
+  }
+}
+
+
 void MethodCompiler::EmitInsn_RSubImmediate(uint32_t dex_pc,
                                             Instruction const* insn) {
 
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 3127447..7e56046 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -112,6 +112,9 @@
     kIntArithm_And,
     kIntArithm_Or,
     kIntArithm_Xor,
+  };
+
+  enum IntShiftArithmKind {
     kIntArithm_Shl,
     kIntArithm_Shr,
     kIntArithm_UShr,
@@ -222,6 +225,12 @@
 
   void EmitInsn_IntArithmImmediate(GEN_INSN_ARGS, IntArithmKind arithm);
 
+  void EmitInsn_IntShiftArithm(GEN_INSN_ARGS, IntShiftArithmKind arithm,
+                               JType op_jty, bool is_2addr);
+
+  void EmitInsn_IntShiftArithmImmediate(GEN_INSN_ARGS,
+                                        IntShiftArithmKind arithm);
+
   void EmitInsn_RSubImmediate(GEN_INSN_ARGS);
 
 
@@ -275,6 +284,12 @@
                                               IntArithmKind arithm,
                                               JType op_jty);
 
+  llvm::Value* EmitIntShiftArithmResultComputation(uint32_t dex_pc,
+                                                   llvm::Value* lhs,
+                                                   llvm::Value* rhs,
+                                                   IntShiftArithmKind arithm,
+                                                   JType op_jty);
+
   llvm::Value* EmitFPArithmResultComputation(uint32_t dex_pc,
                                              llvm::Value* lhs,
                                              llvm::Value* rhs,
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 3d2b84a..0bf2699 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -24,6 +24,7 @@
 #include "thread.h"
 #include "thread_list.h"
 
+#include <algorithm>
 #include <stdint.h>
 
 namespace art {
@@ -432,6 +433,50 @@
 // Runtime Support Function Lookup Callback
 //----------------------------------------------------------------------------
 
+class CStringComparator {
+ public:
+  bool operator()(const char* lhs, const char* rhs) const {
+    return (strcmp(lhs, rhs) <= 0);
+  }
+};
+
+#define EXTERNAL_LINKAGE(NAME) \
+extern "C" void NAME(...);
+
+#include "compiler_runtime_func_list.h"
+COMPILER_RUNTIME_FUNC_LIST(EXTERNAL_LINKAGE)
+#undef COMPILER_RUNTIME_FUNC_LIST
+#undef EXTERNAL_LINKAGE
+
+static void* art_find_compiler_runtime_func(char const* name) {
+  static const char* const names[] = {
+#define DEFINE_ENTRY(NAME) #NAME ,
+#include "compiler_runtime_func_list.h"
+    COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
+#undef COMPILER_RUNTIME_FUNC_LIST
+#undef DEFINE_ENTRY
+  };
+
+  static void* const funcs[] = {
+#define DEFINE_ENTRY(NAME) reinterpret_cast<void*>(NAME) ,
+#include "compiler_runtime_func_list.h"
+    COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
+#undef COMPILER_RUNTIME_FUNC_LIST
+#undef DEFINE_ENTRY
+  };
+
+  static const size_t num_entries = sizeof(names) / sizeof(const char* const);
+
+  const char* const* matched_name_ptr =
+      std::lower_bound(names, names + num_entries, name, CStringComparator());
+
+  if (matched_name_ptr == names + num_entries) {
+    return NULL;
+  } else {
+    return funcs[matched_name_ptr - names];
+  }
+}
+
 void* art_find_runtime_support_func(void* context, char const* name) {
   struct func_entry_t {
     char const* name;
@@ -451,6 +496,12 @@
 
   static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
 
+  // Search the compiler runtime (such as __divdi3)
+  void* result = art_find_compiler_runtime_func(name);
+  if (result != NULL) {
+    return result;
+  }
+
   // Note: Since our table is small, we are using trivial O(n) searching
   // function.  For bigger table, it will be better to use binary
   // search or hash function.