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.