summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-10-17 02:29:32 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-10-17 02:29:32 +0000
commitb3f18cf7466f85e15c6b7f005f544867a4d6847a (patch)
tree62035f08dc38038b74c9796118ae0bab0e7608fb /compiler
parentcb142101f29a4f1e097f03a220db3da6d4bd679f (diff)
parent6f3dbbadf4ce66982eb3d400e0a74cb73eb034f3 (diff)
downloadart-b3f18cf7466f85e15c6b7f005f544867a4d6847a.zip
art-b3f18cf7466f85e15c6b7f005f544867a4d6847a.tar.gz
art-b3f18cf7466f85e15c6b7f005f544867a4d6847a.tar.bz2
Merge "Make ART compile with GCC -O0 again."
Diffstat (limited to 'compiler')
-rw-r--r--compiler/Android.mk1
-rw-r--r--compiler/common_compiler_test.cc170
-rw-r--r--compiler/common_compiler_test.h2
-rw-r--r--compiler/dex/compiler_ir.h2
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc12
-rw-r--r--compiler/dex/quick/gen_common.cc6
-rw-r--r--compiler/driver/compiler_driver.cc2
-rw-r--r--compiler/driver/compiler_driver.h6
-rw-r--r--compiler/jni/jni_compiler_test.cc6
-rw-r--r--compiler/oat_test.cc19
-rw-r--r--compiler/optimizing/gvn.h3
-rw-r--r--compiler/optimizing/register_allocator.h4
-rw-r--r--compiler/utils/arena_allocator.cc1
13 files changed, 43 insertions, 191 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk
index edc5bd0..f413576 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -223,6 +223,7 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : $(LOCAL_PAT
else # host
LOCAL_CLANG := $(ART_HOST_CLANG)
LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
+ LOCAL_LDLIBS := $(ART_HOST_LDLIBS)
ifeq ($$(art_ndebug_or_debug),debug)
LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
else
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index d1d47fb..9a5f74d 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -16,18 +16,12 @@
#include "common_compiler_test.h"
-#if defined(__arm__)
-#include <sys/ucontext.h>
-#endif
-#include <fstream>
-
#include "class_linker.h"
#include "compiled_method.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
-#include "entrypoints/entrypoint_utils.h"
#include "interpreter/interpreter.h"
#include "mirror/art_method.h"
#include "mirror/dex_cache.h"
@@ -38,128 +32,9 @@
namespace art {
-// Normally the ClassLinker supplies this.
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
-
-#if defined(__arm__)
-// A signal handler called when have an illegal instruction. We record the fact in
-// a global boolean and then increment the PC in the signal context to return to
-// the next instruction. We know the instruction is an sdiv (4 bytes long).
-static void baddivideinst(int signo, siginfo *si, void *data) {
- UNUSED(signo);
- UNUSED(si);
- struct ucontext *uc = (struct ucontext *)data;
- struct sigcontext *sc = &uc->uc_mcontext;
- sc->arm_r0 = 0; // set R0 to #0 to signal error
- sc->arm_pc += 4; // skip offending instruction
-}
-
-// This is in arch/arm/arm_sdiv.S. It does the following:
-// mov r1,#1
-// sdiv r0,r1,r1
-// bx lr
-//
-// the result will be the value 1 if sdiv is supported. If it is not supported
-// a SIGILL signal will be raised and the signal handler (baddivideinst) called.
-// The signal handler sets r0 to #0 and then increments pc beyond the failed instruction.
-// Thus if the instruction is not supported, the result of this function will be #0
-
-extern "C" bool CheckForARMSDIVInstruction();
-
-static InstructionSetFeatures GuessInstructionFeatures() {
- InstructionSetFeatures f;
-
- // Uncomment this for processing of /proc/cpuinfo.
- if (false) {
- // Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
- // the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
- std::ifstream in("/proc/cpuinfo");
- if (in) {
- while (!in.eof()) {
- std::string line;
- std::getline(in, line);
- if (!in.eof()) {
- if (line.find("Features") != std::string::npos) {
- if (line.find("idivt") != std::string::npos) {
- f.SetHasDivideInstruction(true);
- }
- }
- }
- in.close();
- }
- } else {
- LOG(INFO) << "Failed to open /proc/cpuinfo";
- }
- }
-
- // See if have a sdiv instruction. Register a signal handler and try to execute
- // an sdiv instruction. If we get a SIGILL then it's not supported. We can't use
- // the /proc/cpuinfo method for this because Krait devices don't always put the idivt
- // feature in the list.
- struct sigaction sa, osa;
- sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
- sa.sa_sigaction = baddivideinst;
- sigaction(SIGILL, &sa, &osa);
-
- if (CheckForARMSDIVInstruction()) {
- f.SetHasDivideInstruction(true);
- }
-
- // Restore the signal handler.
- sigaction(SIGILL, &osa, nullptr);
-
- // Other feature guesses in here.
- return f;
-}
-#endif
-
-// Given a set of instruction features from the build, parse it. The
-// input 'str' is a comma separated list of feature names. Parse it and
-// return the InstructionSetFeatures object.
-static InstructionSetFeatures ParseFeatureList(std::string str) {
- InstructionSetFeatures result;
- typedef std::vector<std::string> FeatureList;
- FeatureList features;
- Split(str, ',', features);
- for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
- std::string feature = Trim(*i);
- if (feature == "default") {
- // Nothing to do.
- } else if (feature == "div") {
- // Supports divide instruction.
- result.SetHasDivideInstruction(true);
- } else if (feature == "nodiv") {
- // Turn off support for divide instruction.
- result.SetHasDivideInstruction(false);
- } else {
- LOG(FATAL) << "Unknown instruction set feature: '" << feature << "'";
- }
- }
- // Others...
- return result;
-}
-
CommonCompilerTest::CommonCompilerTest() {}
CommonCompilerTest::~CommonCompilerTest() {}
-OatFile::OatMethod CommonCompilerTest::CreateOatMethod(const void* code, const uint8_t* gc_map) {
- CHECK(code != nullptr);
- const uint8_t* base;
- uint32_t code_offset, gc_map_offset;
- if (gc_map == nullptr) {
- base = reinterpret_cast<const uint8_t*>(code); // Base of data points at code.
- base -= sizeof(void*); // Move backward so that code_offset != 0.
- code_offset = sizeof(void*);
- gc_map_offset = 0;
- } else {
- // TODO: 64bit support.
- base = nullptr; // Base of data in oat file, ie 0.
- code_offset = PointerToLowMemUInt32(code);
- gc_map_offset = PointerToLowMemUInt32(gc_map);
- }
- return OatFile::OatMethod(base, code_offset, gc_map_offset);
-}
-
void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
CHECK(method != nullptr);
@@ -174,7 +49,8 @@ void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
if (compiled_method != nullptr) {
const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
const void* code_ptr;
- if (code != nullptr) {
+ bool is_portable = (code == nullptr);
+ if (!is_portable) {
uint32_t code_size = code->size();
CHECK_NE(0u, code_size);
const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
@@ -210,33 +86,11 @@ void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
const void* method_code = CompiledMethod::CodePointer(code_ptr,
compiled_method->GetInstructionSet());
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+ class_linker_->SetEntryPointsToCompiledCode(method, method_code, is_portable);
} else {
// No code? You must mean to go into the interpreter.
// Or the generic JNI...
- if (!method->IsNative()) {
- const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
- : GetQuickToInterpreterBridge();
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
- } else {
- const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
-
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
- }
- }
- // Create bridges to transition between different kinds of compiled bridge.
- if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
- method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
- } else {
- CHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
- method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
- method->SetIsPortableCompiled();
+ class_linker_->SetEntryPointsToInterpreter(method);
}
}
@@ -282,19 +136,9 @@ void CommonCompilerTest::SetUp() {
{
ScopedObjectAccess soa(Thread::Current());
- InstructionSet instruction_set = kRuntimeISA;
-
+ const InstructionSet instruction_set = kRuntimeISA;
// Take the default set of instruction features from the build.
- InstructionSetFeatures instruction_set_features =
- ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
-
-#if defined(__arm__)
- InstructionSetFeatures runtime_features = GuessInstructionFeatures();
-
- // for ARM, do a runtime check to make sure that the features we are passed from
- // the build match the features we actually determine at runtime.
- ASSERT_LE(instruction_set_features, runtime_features);
-#endif
+ instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
runtime_->SetInstructionSet(instruction_set);
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
@@ -313,7 +157,7 @@ void CommonCompilerTest::SetUp() {
verification_results_.get(),
method_inliner_map_.get(),
compiler_kind, instruction_set,
- instruction_set_features,
+ instruction_set_features_.get(),
true, new std::set<std::string>,
2, true, true, timer_.get()));
}
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index df06b71..20b750c 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -81,6 +81,8 @@ class CommonCompilerTest : public CommonRuntimeTest {
std::unique_ptr<CompilerCallbacks> callbacks_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<CumulativeLogger> timer_;
+ std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
+
private:
std::unique_ptr<MemMap> image_reservation_;
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index 37e3a7a..34585c1 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -68,7 +68,7 @@ struct CompilationUnit {
InstructionSet instruction_set;
bool target64;
- InstructionSetFeatures GetInstructionSetFeatures() {
+ const InstructionSetFeatures* GetInstructionSetFeatures() {
return compiler_driver->GetInstructionSetFeatures();
}
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index e833c9a..09acf4c 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -969,9 +969,9 @@ LIR* ArmMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_
size = k32;
}
LIR* load;
- if (UNLIKELY(is_volatile == kVolatile &&
- (size == k64 || size == kDouble) &&
- !cu_->compiler_driver->GetInstructionSetFeatures().HasLpae())) {
+ if (is_volatile == kVolatile && (size == k64 || size == kDouble) &&
+ !cu_->compiler_driver->GetInstructionSetFeatures()->
+ AsArmInstructionSetFeatures()->HasLpae()) {
// Only 64-bit load needs special handling.
// If the cpu supports LPAE, aligned LDRD is atomic - fall through to LoadBaseDisp().
DCHECK(!r_dest.IsFloat()); // See RegClassForFieldLoadSave().
@@ -1093,9 +1093,9 @@ LIR* ArmMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r
}
LIR* store;
- if (UNLIKELY(is_volatile == kVolatile &&
- (size == k64 || size == kDouble) &&
- !cu_->compiler_driver->GetInstructionSetFeatures().HasLpae())) {
+ if (is_volatile == kVolatile && (size == k64 || size == kDouble) &&
+ !cu_->compiler_driver->GetInstructionSetFeatures()->
+ AsArmInstructionSetFeatures()->HasLpae()) {
// Only 64-bit store needs special handling.
// If the cpu supports LPAE, aligned STRD is atomic - fall through to StoreBaseDisp().
// Use STREXD for the atomic store. (Expect displacement > 0, don't optimize for == 0.)
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 12ca065..a33d15f 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -1606,7 +1606,8 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
done = true;
} else if (cu_->instruction_set == kThumb2) {
- if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
+ if (cu_->GetInstructionSetFeatures()->AsArmInstructionSetFeatures()->
+ HasDivideInstruction()) {
// Use ARM SDIV instruction for division. For remainder we also need to
// calculate using a MUL and subtract.
rl_src1 = LoadValue(rl_src1, kCoreReg);
@@ -1875,7 +1876,8 @@ void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, Re
rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div);
done = true;
} else if (cu_->instruction_set == kThumb2) {
- if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
+ if (cu_->GetInstructionSetFeatures()->AsArmInstructionSetFeatures()->
+ HasDivideInstruction()) {
// Use ARM SDIV instruction for division. For remainder we also need to
// calculate using a MUL and subtract.
rl_src = LoadValue(rl_src, kCoreReg);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index fb648fc..aac33d2 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -329,7 +329,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
- InstructionSetFeatures instruction_set_features,
+ const InstructionSetFeatures* instruction_set_features,
bool image, std::set<std::string>* image_classes, size_t thread_count,
bool dump_stats, bool dump_passes, CumulativeLogger* timer,
std::string profile_file)
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index c445683..0425d27 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -88,7 +88,7 @@ class CompilerDriver {
DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
- InstructionSetFeatures instruction_set_features,
+ const InstructionSetFeatures* instruction_set_features,
bool image, std::set<std::string>* image_classes,
size_t thread_count, bool dump_stats, bool dump_passes,
CumulativeLogger* timer, std::string profile_file = "");
@@ -115,7 +115,7 @@ class CompilerDriver {
return instruction_set_;
}
- InstructionSetFeatures GetInstructionSetFeatures() const {
+ const InstructionSetFeatures* GetInstructionSetFeatures() const {
return instruction_set_features_;
}
@@ -475,7 +475,7 @@ class CompilerDriver {
std::unique_ptr<Compiler> compiler_;
const InstructionSet instruction_set_;
- const InstructionSetFeatures instruction_set_features_;
+ const InstructionSetFeatures* const instruction_set_features_;
// All class references that require
mutable ReaderWriterMutex freezing_constructor_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index fd7d350..0fea2a7 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -73,10 +73,10 @@ class JniCompilerTest : public CommonCompilerTest {
}
ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig;
if (check_generic_jni_) {
- method->SetEntryPointFromQuickCompiledCode(class_linker_->GetQuickGenericJniTrampoline());
+ method->SetEntryPointFromQuickCompiledCode(class_linker_->GetRuntimeQuickGenericJniStub());
} else {
- if (method->GetEntryPointFromQuickCompiledCode() == nullptr ||
- method->GetEntryPointFromQuickCompiledCode() == class_linker_->GetQuickGenericJniTrampoline()) {
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
+ if (code == nullptr || class_linker_->IsQuickGenericJniStub(code)) {
CompileMethod(method);
ASSERT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr)
<< method_name << " " << method_sig;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 3fcc369..a9d30b6 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -95,7 +95,10 @@ TEST_F(OatTest, WriteRead) {
: Compiler::kQuick;
InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
- InstructionSetFeatures insn_features;
+ std::string error_msg;
+ std::unique_ptr<const InstructionSetFeatures> insn_features(
+ InstructionSetFeatures::FromFeatureString(insn_set, "default", &error_msg));
+ ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
compiler_options_.reset(new CompilerOptions);
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
@@ -106,7 +109,7 @@ TEST_F(OatTest, WriteRead) {
verification_results_.get(),
method_inliner_map_.get(),
compiler_kind, insn_set,
- insn_features, false, NULL, 2, true, true,
+ insn_features.get(), false, NULL, 2, true, true,
timer_.get()));
jobject class_loader = NULL;
if (kCompile) {
@@ -135,7 +138,6 @@ TEST_F(OatTest, WriteRead) {
if (kCompile) { // OatWriter strips the code, regenerate to compare
compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
}
- std::string error_msg;
std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL, false,
&error_msg));
ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
@@ -193,13 +195,16 @@ TEST_F(OatTest, OatHeaderSizeCheck) {
}
TEST_F(OatTest, OatHeaderIsValid) {
- InstructionSet instruction_set = kX86;
- InstructionSetFeatures instruction_set_features;
+ InstructionSet insn_set = kX86;
+ std::string error_msg;
+ std::unique_ptr<const InstructionSetFeatures> insn_features(
+ InstructionSetFeatures::FromFeatureString(insn_set, "default", &error_msg));
+ ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
std::vector<const DexFile*> dex_files;
uint32_t image_file_location_oat_checksum = 0;
uint32_t image_file_location_oat_begin = 0;
- std::unique_ptr<OatHeader> oat_header(OatHeader::Create(instruction_set,
- instruction_set_features,
+ std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
+ insn_features.get(),
&dex_files,
image_file_location_oat_checksum,
image_file_location_oat_begin,
diff --git a/compiler/optimizing/gvn.h b/compiler/optimizing/gvn.h
index 41b3ceb..a98d714 100644
--- a/compiler/optimizing/gvn.h
+++ b/compiler/optimizing/gvn.h
@@ -17,7 +17,6 @@
#ifndef ART_COMPILER_OPTIMIZING_GVN_H_
#define ART_COMPILER_OPTIMIZING_GVN_H_
-#include <gtest/gtest.h>
#include "nodes.h"
namespace art {
@@ -221,7 +220,7 @@ class GlobalValueNumberer : public ValueObject {
// Mark visisted blocks. Only used for debugging.
GrowableArray<bool> visited_;
- FRIEND_TEST(GVNTest, LoopSideEffects);
+ ART_FRIEND_TEST(GVNTest, LoopSideEffects);
DISALLOW_COPY_AND_ASSIGN(GlobalValueNumberer);
};
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index d4c233a..0c3a9b3 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -21,8 +21,6 @@
#include "primitive.h"
#include "utils/growable_array.h"
-#include "gtest/gtest.h"
-
namespace art {
class CodeGenerator;
@@ -189,7 +187,7 @@ class RegisterAllocator {
// The maximum live registers at safepoints.
size_t maximum_number_of_live_registers_;
- FRIEND_TEST(RegisterAllocatorTest, FreeUntil);
+ ART_FRIEND_TEST(RegisterAllocatorTest, FreeUntil);
DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
};
diff --git a/compiler/utils/arena_allocator.cc b/compiler/utils/arena_allocator.cc
index 516ac2b..0c93f0a 100644
--- a/compiler/utils/arena_allocator.cc
+++ b/compiler/utils/arena_allocator.cc
@@ -15,6 +15,7 @@
*/
#include <algorithm>
+#include <iomanip>
#include <numeric>
#include "arena_allocator.h"