summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/code_generator.cc12
-rw-r--r--compiler/optimizing/code_generator.h12
-rw-r--r--compiler/optimizing/code_generator_arm.cc35
-rw-r--r--compiler/optimizing/code_generator_arm.h12
-rw-r--r--compiler/optimizing/code_generator_arm64.cc23
-rw-r--r--compiler/optimizing/code_generator_arm64.h5
-rw-r--r--compiler/optimizing/code_generator_x86.cc27
-rw-r--r--compiler/optimizing/code_generator_x86.h6
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc27
-rw-r--r--compiler/optimizing/code_generator_x86_64.h5
-rw-r--r--compiler/optimizing/codegen_test.cc21
-rw-r--r--compiler/optimizing/constant_folding_test.cc3
-rw-r--r--compiler/optimizing/dead_code_elimination_test.cc3
-rw-r--r--compiler/optimizing/linearize_test.cc3
-rw-r--r--compiler/optimizing/live_ranges_test.cc13
-rw-r--r--compiler/optimizing/liveness_test.cc3
-rw-r--r--compiler/optimizing/optimizing_compiler.cc13
-rw-r--r--compiler/optimizing/register_allocator_test.cc31
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc8
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h1
20 files changed, 192 insertions, 71 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 9e89070..08cbb20 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -330,23 +330,25 @@ bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) con
CodeGenerator* CodeGenerator::Create(HGraph* graph,
InstructionSet instruction_set,
- const InstructionSetFeatures& isa_features) {
+ const InstructionSetFeatures& isa_features,
+ const CompilerOptions& compiler_options) {
switch (instruction_set) {
case kArm:
case kThumb2: {
return new arm::CodeGeneratorARM(graph,
- isa_features.AsArmInstructionSetFeatures());
+ *isa_features.AsArmInstructionSetFeatures(),
+ compiler_options);
}
case kArm64: {
- return new arm64::CodeGeneratorARM64(graph);
+ return new arm64::CodeGeneratorARM64(graph, compiler_options);
}
case kMips:
return nullptr;
case kX86: {
- return new x86::CodeGeneratorX86(graph);
+ return new x86::CodeGeneratorX86(graph, compiler_options);
}
case kX86_64: {
- return new x86_64::CodeGeneratorX86_64(graph);
+ return new x86_64::CodeGeneratorX86_64(graph, compiler_options);
}
default:
return nullptr;
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 88e50b6..682c260 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -20,6 +20,7 @@
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
#include "base/bit_field.h"
+#include "driver/compiler_options.h"
#include "globals.h"
#include "locations.h"
#include "memory_region.h"
@@ -85,7 +86,8 @@ class CodeGenerator {
void CompileOptimized(CodeAllocator* allocator);
static CodeGenerator* Create(HGraph* graph,
InstructionSet instruction_set,
- const InstructionSetFeatures& isa_features);
+ const InstructionSetFeatures& isa_features,
+ const CompilerOptions& compiler_options);
virtual ~CodeGenerator() {}
HGraph* GetGraph() const { return graph_; }
@@ -130,6 +132,9 @@ class CodeGenerator {
virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
virtual InstructionSet GetInstructionSet() const = 0;
+
+ const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
+
// Saves the register in the stack. Returns the size taken on stack.
virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
// Restores the register from the stack. Returns the size taken on stack.
@@ -200,7 +205,8 @@ class CodeGenerator {
CodeGenerator(HGraph* graph,
size_t number_of_core_registers,
size_t number_of_fpu_registers,
- size_t number_of_register_pairs)
+ size_t number_of_register_pairs,
+ const CompilerOptions& compiler_options)
: frame_size_(kUninitializedFrameSize),
core_spill_mask_(0),
first_register_slot_in_slow_path_(0),
@@ -211,6 +217,7 @@ class CodeGenerator {
number_of_fpu_registers_(number_of_fpu_registers),
number_of_register_pairs_(number_of_register_pairs),
graph_(graph),
+ compiler_options_(compiler_options),
pc_infos_(graph->GetArena(), 32),
slow_paths_(graph->GetArena(), 8),
is_leaf_(true),
@@ -249,6 +256,7 @@ class CodeGenerator {
size_t GetStackOffsetOfSavedRegister(size_t index);
HGraph* const graph_;
+ const CompilerOptions& compiler_options_;
GrowableArray<PcInfo> pc_infos_;
GrowableArray<SlowPathCode*> slow_paths_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c4ba0fd..2d3fa5f 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -387,8 +387,10 @@ size_t CodeGeneratorARM::RestoreFloatingPointRegister(size_t stack_index, uint32
}
CodeGeneratorARM::CodeGeneratorARM(HGraph* graph,
- const ArmInstructionSetFeatures* isa_features)
- : CodeGenerator(graph, kNumberOfCoreRegisters, kNumberOfSRegisters, kNumberOfRegisterPairs),
+ const ArmInstructionSetFeatures& isa_features,
+ const CompilerOptions& compiler_options)
+ : CodeGenerator(graph, kNumberOfCoreRegisters, kNumberOfSRegisters,
+ kNumberOfRegisterPairs, compiler_options),
block_labels_(graph->GetArena(), 0),
location_builder_(graph, this),
instruction_visitor_(graph, this),
@@ -2616,7 +2618,7 @@ void LocationsBuilderARM::HandleFieldSet(HInstruction* instruction, const FieldI
bool is_wide = field_type == Primitive::kPrimLong || field_type == Primitive::kPrimDouble;
bool generate_volatile = field_info.IsVolatile()
&& is_wide
- && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
// Temporary registers for the write barrier.
// TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark.
if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
@@ -2649,7 +2651,7 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
Location value = locations->InAt(1);
bool is_volatile = field_info.IsVolatile();
- bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
@@ -2738,7 +2740,7 @@ void LocationsBuilderARM::HandleFieldGet(HInstruction* instruction, const FieldI
bool generate_volatile = field_info.IsVolatile()
&& (field_info.GetFieldType() == Primitive::kPrimDouble)
- && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
if (generate_volatile) {
// Arm encoding have some additional constraints for ldrexd/strexd:
// - registers need to be consecutive
@@ -2759,7 +2761,7 @@ void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction,
Register base = locations->InAt(0).AsRegister<Register>();
Location out = locations->Out();
bool is_volatile = field_info.IsVolatile();
- bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
@@ -2864,13 +2866,22 @@ void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instructi
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetInAt(0, Location::RequiresRegister());
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::RegisterOrConstant(instruction->InputAt(0));
+ locations->SetInAt(0, loc);
if (instruction->HasUses()) {
locations->SetOut(Location::SameAsFirstInput());
}
}
-void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
+void InstructionCodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ Location obj = instruction->GetLocations()->InAt(0);
+ __ LoadFromOffset(kLoadWord, IP, obj.AsRegister<Register>(), 0);
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+}
+
+void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
@@ -2887,6 +2898,14 @@ void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
}
}
+void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
+ if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void LocationsBuilderARM::VisitArrayGet(HArrayGet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 267d9a2..fe373d5 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -19,6 +19,7 @@
#include "code_generator.h"
#include "dex/compiler_enums.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
#include "utils/arm/assembler_thumb2.h"
@@ -143,7 +144,8 @@ class InstructionCodeGeneratorARM : public HGraphVisitor {
Register out_lo, Register out_hi);
void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
-
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
ArmAssembler* const assembler_;
CodeGeneratorARM* const codegen_;
@@ -153,7 +155,9 @@ class InstructionCodeGeneratorARM : public HGraphVisitor {
class CodeGeneratorARM : public CodeGenerator {
public:
- CodeGeneratorARM(HGraph* graph, const ArmInstructionSetFeatures* isa_features);
+ CodeGeneratorARM(HGraph* graph,
+ const ArmInstructionSetFeatures& isa_features,
+ const CompilerOptions& compiler_options);
virtual ~CodeGeneratorARM() {}
void GenerateFrameEntry() OVERRIDE;
@@ -234,7 +238,7 @@ class CodeGeneratorARM : public CodeGenerator {
block_labels_.SetSize(GetGraph()->GetBlocks().Size());
}
- const ArmInstructionSetFeatures* GetInstructionSetFeatures() const {
+ const ArmInstructionSetFeatures& GetInstructionSetFeatures() const {
return isa_features_;
}
@@ -249,7 +253,7 @@ class CodeGeneratorARM : public CodeGenerator {
InstructionCodeGeneratorARM instruction_visitor_;
ParallelMoveResolverARM move_resolver_;
Thumb2Assembler assembler_;
- const ArmInstructionSetFeatures* isa_features_;
+ const ArmInstructionSetFeatures& isa_features_;
DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM);
};
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 6d2c3de..c1bce2a 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -22,6 +22,7 @@
#include "mirror/array-inl.h"
#include "mirror/art_method.h"
#include "mirror/class.h"
+#include "offsets.h"
#include "thread.h"
#include "utils/arm64/assembler_arm64.h"
#include "utils/assembler.h"
@@ -562,11 +563,12 @@ Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type
return next_location;
}
-CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph)
+CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph, const CompilerOptions& compiler_options)
: CodeGenerator(graph,
kNumberOfAllocatableRegisters,
kNumberOfAllocatableFPRegisters,
- kNumberOfAllocatableRegisterPairs),
+ kNumberOfAllocatableRegisterPairs,
+ compiler_options),
block_labels_(nullptr),
location_builder_(graph, this),
instruction_visitor_(graph, this),
@@ -2291,7 +2293,14 @@ void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
}
}
-void InstructionCodeGeneratorARM64::VisitNullCheck(HNullCheck* instruction) {
+void InstructionCodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ Location obj = instruction->GetLocations()->InAt(0);
+
+ __ Ldr(wzr, HeapOperandFrom(obj, Offset(0)));
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+}
+
+void InstructionCodeGeneratorARM64::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeARM64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM64(instruction);
codegen_->AddSlowPath(slow_path);
@@ -2306,6 +2315,14 @@ void InstructionCodeGeneratorARM64::VisitNullCheck(HNullCheck* instruction) {
}
}
+void InstructionCodeGeneratorARM64::VisitNullCheck(HNullCheck* instruction) {
+ if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void LocationsBuilderARM64::VisitOr(HOr* instruction) {
HandleBinaryOp(instruction);
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 590bc1d..e20d02e 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -19,6 +19,7 @@
#include "code_generator.h"
#include "dex/compiler_enums.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
#include "utils/arm64/assembler_arm64.h"
@@ -113,6 +114,8 @@ class InstructionCodeGeneratorARM64 : public HGraphVisitor {
void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
void HandleBinaryOp(HBinaryOperation* instr);
void HandleShift(HBinaryOperation* instr);
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
Arm64Assembler* const assembler_;
CodeGeneratorARM64* const codegen_;
@@ -164,7 +167,7 @@ class ParallelMoveResolverARM64 : public ParallelMoveResolver {
class CodeGeneratorARM64 : public CodeGenerator {
public:
- explicit CodeGeneratorARM64(HGraph* graph);
+ CodeGeneratorARM64(HGraph* graph, const CompilerOptions& compiler_options);
virtual ~CodeGeneratorARM64() {}
void GenerateFrameEntry() OVERRIDE;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 1a0df44..22b2aa0 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -373,8 +373,9 @@ size_t CodeGeneratorX86::RestoreCoreRegister(size_t stack_index, uint32_t reg_id
return kX86WordSize;
}
-CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
- : CodeGenerator(graph, kNumberOfCpuRegisters, kNumberOfXmmRegisters, kNumberOfRegisterPairs),
+CodeGeneratorX86::CodeGeneratorX86(HGraph* graph, const CompilerOptions& compiler_options)
+ : CodeGenerator(graph, kNumberOfCpuRegisters, kNumberOfXmmRegisters,
+ kNumberOfRegisterPairs, compiler_options),
block_labels_(graph->GetArena(), 0),
location_builder_(graph, this),
instruction_visitor_(graph, this),
@@ -2924,13 +2925,23 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instr
void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetInAt(0, Location::Any());
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::Any();
+ locations->SetInAt(0, loc);
if (instruction->HasUses()) {
locations->SetOut(Location::SameAsFirstInput());
}
}
-void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
+void InstructionCodeGeneratorX86::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ Location obj = locations->InAt(0);
+ __ testl(EAX, Address(obj.AsRegister<Register>(), 0));
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+}
+
+void InstructionCodeGeneratorX86::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeX86* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction);
codegen_->AddSlowPath(slow_path);
@@ -2950,6 +2961,14 @@ void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
__ j(kEqual, slow_path->GetEntryLabel());
}
+void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
+ if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 2d8adb2..b77a1aa 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -19,6 +19,7 @@
#include "code_generator.h"
#include "dex/compiler_enums.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
#include "utils/x86/assembler_x86.h"
@@ -144,6 +145,9 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor {
void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
+
X86Assembler* const assembler_;
CodeGeneratorX86* const codegen_;
@@ -152,7 +156,7 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor {
class CodeGeneratorX86 : public CodeGenerator {
public:
- explicit CodeGeneratorX86(HGraph* graph);
+ CodeGeneratorX86(HGraph* graph, const CompilerOptions& compiler_options);
virtual ~CodeGeneratorX86() {}
void GenerateFrameEntry() OVERRIDE;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 3d7f122..723573a 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -416,8 +416,8 @@ size_t CodeGeneratorX86_64::RestoreFloatingPointRegister(size_t stack_index, uin
return kX86_64WordSize;
}
-CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph)
- : CodeGenerator(graph, kNumberOfCpuRegisters, kNumberOfFloatRegisters, 0),
+CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph, const CompilerOptions& compiler_options)
+ : CodeGenerator(graph, kNumberOfCpuRegisters, kNumberOfFloatRegisters, 0, compiler_options),
block_labels_(graph->GetArena(), 0),
location_builder_(graph, this),
instruction_visitor_(graph, this),
@@ -2623,13 +2623,24 @@ void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instru
void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetInAt(0, Location::Any());
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::Any();
+ locations->SetInAt(0, loc);
if (instruction->HasUses()) {
locations->SetOut(Location::SameAsFirstInput());
}
}
-void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
+void InstructionCodeGeneratorX86_64::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ Location obj = locations->InAt(0);
+
+ __ testl(CpuRegister(RAX), Address(obj.AsRegister<CpuRegister>(), 0));
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+}
+
+void InstructionCodeGeneratorX86_64::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction);
codegen_->AddSlowPath(slow_path);
@@ -2649,6 +2660,14 @@ void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
__ j(kEqual, slow_path->GetEntryLabel());
}
+void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
+ if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index c501568..befe994 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -19,6 +19,7 @@
#include "code_generator.h"
#include "dex/compiler_enums.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
#include "utils/x86_64/assembler_x86_64.h"
@@ -159,6 +160,8 @@ class InstructionCodeGeneratorX86_64 : public HGraphVisitor {
void GenerateMemoryBarrier(MemBarrierKind kind);
void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
+ void GenerateImplicitNullCheck(HNullCheck* instruction);
+ void GenerateExplicitNullCheck(HNullCheck* instruction);
X86_64Assembler* const assembler_;
CodeGeneratorX86_64* const codegen_;
@@ -168,7 +171,7 @@ class InstructionCodeGeneratorX86_64 : public HGraphVisitor {
class CodeGeneratorX86_64 : public CodeGenerator {
public:
- explicit CodeGeneratorX86_64(HGraph* graph);
+ CodeGeneratorX86_64(HGraph* graph, const CompilerOptions& compiler_options);
virtual ~CodeGeneratorX86_64() {}
void GenerateFrameEntry() OVERRIDE;
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 18722f7..aa4fc8f 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -27,6 +27,7 @@
#include "common_compiler_test.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "prepare_for_register_allocation.h"
@@ -80,7 +81,8 @@ template <typename Expected>
static void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) {
InternalCodeAllocator allocator;
- x86::CodeGeneratorX86 codegenX86(graph);
+ CompilerOptions compiler_options;
+ x86::CodeGeneratorX86 codegenX86(graph, compiler_options);
// We avoid doing a stack overflow check that requires the runtime being setup,
// by making sure the compiler knows the methods we are running are leaf methods.
codegenX86.CompileBaseline(&allocator, true);
@@ -90,19 +92,19 @@ static void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) {
std::unique_ptr<const ArmInstructionSetFeatures> features(
ArmInstructionSetFeatures::FromCppDefines());
- arm::CodeGeneratorARM codegenARM(graph, features.get());
+ arm::CodeGeneratorARM codegenARM(graph, *features.get(), compiler_options);
codegenARM.CompileBaseline(&allocator, true);
if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
Run(allocator, codegenARM, has_result, expected);
}
- x86_64::CodeGeneratorX86_64 codegenX86_64(graph);
+ x86_64::CodeGeneratorX86_64 codegenX86_64(graph, compiler_options);
codegenX86_64.CompileBaseline(&allocator, true);
if (kRuntimeISA == kX86_64) {
Run(allocator, codegenX86_64, has_result, expected);
}
- arm64::CodeGeneratorARM64 codegenARM64(graph);
+ arm64::CodeGeneratorARM64 codegenARM64(graph, compiler_options);
codegenARM64.CompileBaseline(&allocator, true);
if (kRuntimeISA == kArm64) {
Run(allocator, codegenARM64, has_result, expected);
@@ -132,17 +134,20 @@ static void RunCodeOptimized(HGraph* graph,
std::function<void(HGraph*)> hook_before_codegen,
bool has_result,
Expected expected) {
+ CompilerOptions compiler_options;
if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
- arm::CodeGeneratorARM codegenARM(graph, ArmInstructionSetFeatures::FromCppDefines());
+ arm::CodeGeneratorARM codegenARM(graph,
+ *ArmInstructionSetFeatures::FromCppDefines(),
+ compiler_options);
RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected);
} else if (kRuntimeISA == kArm64) {
- arm64::CodeGeneratorARM64 codegenARM64(graph);
+ arm64::CodeGeneratorARM64 codegenARM64(graph, compiler_options);
RunCodeOptimized(&codegenARM64, graph, hook_before_codegen, has_result, expected);
} else if (kRuntimeISA == kX86) {
- x86::CodeGeneratorX86 codegenX86(graph);
+ x86::CodeGeneratorX86 codegenX86(graph, compiler_options);
RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected);
} else if (kRuntimeISA == kX86_64) {
- x86_64::CodeGeneratorX86_64 codegenX86_64(graph);
+ x86_64::CodeGeneratorX86_64 codegenX86_64(graph, compiler_options);
RunCodeOptimized(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
}
}
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index ed7e57b..6ceccfb 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -19,6 +19,7 @@
#include "code_generator_x86.h"
#include "constant_folding.h"
#include "dead_code_elimination.h"
+#include "driver/compiler_options.h"
#include "graph_checker.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"
@@ -45,7 +46,7 @@ static void TestCode(const uint16_t* data,
std::string actual_before = printer_before.str();
ASSERT_EQ(expected_before, actual_before);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
HConstantFolding(graph).Run();
SSAChecker ssa_checker_cf(&allocator, graph);
ssa_checker_cf.Run();
diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc
index 3dbd04e..a644719 100644
--- a/compiler/optimizing/dead_code_elimination_test.cc
+++ b/compiler/optimizing/dead_code_elimination_test.cc
@@ -16,6 +16,7 @@
#include "code_generator_x86.h"
#include "dead_code_elimination.h"
+#include "driver/compiler_options.h"
#include "graph_checker.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"
@@ -39,7 +40,7 @@ static void TestCode(const uint16_t* data,
std::string actual_before = printer_before.str();
ASSERT_EQ(actual_before, expected_before);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
HDeadCodeElimination(graph).Run();
SSAChecker ssa_checker(&allocator, graph);
ssa_checker.Run();
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index 59404dc..2ab9b57 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -22,6 +22,7 @@
#include "code_generator_x86.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "driver/compiler_options.h"
#include "graph_visualizer.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
@@ -44,7 +45,7 @@ static void TestCode(const uint16_t* data, const int* expected_order, size_t num
graph->TryBuildingSsa();
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index 007c43e..ff23eda 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -19,6 +19,7 @@
#include "code_generator_x86.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "prepare_for_register_allocation.h"
@@ -63,7 +64,7 @@ TEST(LiveRangesTest, CFG1) {
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -109,7 +110,7 @@ TEST(LiveRangesTest, CFG2) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -158,7 +159,7 @@ TEST(LiveRangesTest, CFG3) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -235,7 +236,7 @@ TEST(LiveRangesTest, Loop1) {
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
RemoveSuspendChecks(graph);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -313,7 +314,7 @@ TEST(LiveRangesTest, Loop2) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -389,7 +390,7 @@ TEST(LiveRangesTest, CFG4) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index 6f706c3..f2d49ac 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -19,6 +19,7 @@
#include "code_generator_x86.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "prepare_for_register_allocation.h"
@@ -51,7 +52,7 @@ static void TestCode(const uint16_t* data, const char* expected) {
graph->TryBuildingSsa();
// `Inline` conditions into ifs.
PrepareForRegisterAllocation(graph).Run();
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 6056373..daec0f0 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -328,7 +328,8 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
const DexFile& dex_file) const {
UNUSED(invoke_type);
compilation_stats_.RecordStat(MethodCompilationStat::kAttemptCompilation);
- InstructionSet instruction_set = GetCompilerDriver()->GetInstructionSet();
+ CompilerDriver* compiler_driver = GetCompilerDriver();
+ InstructionSet instruction_set = compiler_driver->GetInstructionSet();
// Always use the thumb2 assembler: some runtime functionality (like implicit stack
// overflow checks) assume thumb2.
if (instruction_set == kArm) {
@@ -349,7 +350,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
DexCompilationUnit dex_compilation_unit(
nullptr, class_loader, art::Runtime::Current()->GetClassLinker(), dex_file, code_item,
class_def_idx, method_idx, access_flags,
- GetCompilerDriver()->GetVerifiedMethod(&dex_file, method_idx));
+ compiler_driver->GetVerifiedMethod(&dex_file, method_idx));
std::string method_name = PrettyMethod(method_idx, dex_file);
@@ -364,7 +365,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
&dex_compilation_unit,
&dex_compilation_unit,
&dex_file,
- GetCompilerDriver(),
+ compiler_driver,
&compilation_stats_);
VLOG(compiler) << "Building " << PrettyMethod(method_idx, dex_file);
@@ -374,9 +375,11 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
return nullptr;
}
- CompilerDriver* compiler_driver = GetCompilerDriver();
std::unique_ptr<CodeGenerator> codegen(
- CodeGenerator::Create(graph, instruction_set, *compiler_driver->GetInstructionSetFeatures()));
+ CodeGenerator::Create(graph,
+ instruction_set,
+ *compiler_driver->GetInstructionSetFeatures(),
+ compiler_driver->GetCompilerOptions()));
if (codegen.get() == nullptr) {
CHECK(!shouldCompile) << "Could not find code generator for optimizing compiler";
compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledNoCodegen);
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 0948643..fa1e01f 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -19,6 +19,7 @@
#include "code_generator_x86.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "register_allocator.h"
@@ -40,7 +41,7 @@ static bool Check(const uint16_t* data) {
const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
HGraph* graph = builder.BuildGraph(*item);
graph->TryBuildingSsa();
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
RegisterAllocator register_allocator(&allocator, &codegen, liveness);
@@ -56,7 +57,7 @@ TEST(RegisterAllocatorTest, ValidateIntervals) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = new (&allocator) HGraph(&allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
GrowableArray<LiveInterval*> intervals(&allocator, 0);
// Test with two intervals of the same range.
@@ -295,7 +296,7 @@ TEST(RegisterAllocatorTest, Loop3) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildSSAGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
RegisterAllocator register_allocator(&allocator, &codegen, liveness);
@@ -327,7 +328,7 @@ TEST(RegisterAllocatorTest, FirstRegisterUse) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
HGraph* graph = BuildSSAGraph(data, &allocator);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -380,7 +381,7 @@ TEST(RegisterAllocatorTest, DeadPhi) {
ArenaAllocator allocator(&pool);
HGraph* graph = BuildSSAGraph(data, &allocator);
SsaDeadPhiElimination(graph).Run();
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
RegisterAllocator register_allocator(&allocator, &codegen, liveness);
@@ -402,7 +403,7 @@ TEST(RegisterAllocatorTest, FreeUntil) {
ArenaAllocator allocator(&pool);
HGraph* graph = BuildSSAGraph(data, &allocator);
SsaDeadPhiElimination(graph).Run();
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
RegisterAllocator register_allocator(&allocator, &codegen, liveness);
@@ -504,7 +505,7 @@ TEST(RegisterAllocatorTest, PhiHint) {
{
HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -519,7 +520,7 @@ TEST(RegisterAllocatorTest, PhiHint) {
{
HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -536,7 +537,7 @@ TEST(RegisterAllocatorTest, PhiHint) {
{
HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -553,7 +554,7 @@ TEST(RegisterAllocatorTest, PhiHint) {
{
HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -603,7 +604,7 @@ TEST(RegisterAllocatorTest, ExpectedInRegisterHint) {
{
HGraph* graph = BuildFieldReturn(&allocator, &field, &ret);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -616,7 +617,7 @@ TEST(RegisterAllocatorTest, ExpectedInRegisterHint) {
{
HGraph* graph = BuildFieldReturn(&allocator, &field, &ret);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -665,7 +666,7 @@ TEST(RegisterAllocatorTest, SameAsFirstInputHint) {
{
HGraph* graph = BuildTwoAdds(&allocator, &first_add, &second_add);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -679,7 +680,7 @@ TEST(RegisterAllocatorTest, SameAsFirstInputHint) {
{
HGraph* graph = BuildTwoAdds(&allocator, &first_add, &second_add);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
@@ -726,7 +727,7 @@ TEST(RegisterAllocatorTest, ExpectedExactInRegisterAndSameOutputHint) {
{
HGraph* graph = BuildDiv(&allocator, &div);
- x86::CodeGeneratorX86 codegen(graph);
+ x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
SsaLivenessAnalysis liveness(*graph, &codegen);
liveness.Analyze();
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index c7414a1..906eabf 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -1121,6 +1121,14 @@ void X86_64Assembler::testl(CpuRegister reg1, CpuRegister reg2) {
}
+void X86_64Assembler::testl(CpuRegister reg, const Address& address) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOptionalRex32(reg, address);
+ EmitUint8(0x85);
+ EmitOperand(reg.LowBits(), address);
+}
+
+
void X86_64Assembler::testl(CpuRegister reg, const Immediate& immediate) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
// For registers that have a byte variant (RAX, RBX, RCX, and RDX)
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 5c8d608..4a509fa 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -409,6 +409,7 @@ class X86_64Assembler FINAL : public Assembler {
void cmpq(const Address& address, const Immediate& imm);
void testl(CpuRegister reg1, CpuRegister reg2);
+ void testl(CpuRegister reg, const Address& address);
void testl(CpuRegister reg, const Immediate& imm);
void testq(CpuRegister reg1, CpuRegister reg2);