diff options
author | 2017-10-05 14:35:55 +0100 | |
---|---|---|
committer | 2017-10-09 10:39:22 +0100 | |
commit | e764d2e50c544c2cb98ee61a15d613161ac6bd17 (patch) | |
tree | 112aa7ca459d2edb4f800897060a2407fcc622c7 /compiler/optimizing | |
parent | ca6fff898afcb62491458ae8bcd428bfb3043da1 (diff) |
Use ScopedArenaAllocator for register allocation.
Memory needed to compile the two most expensive methods for
aosp_angler-userdebug boot image:
BatteryStats.dumpCheckinLocked() : 25.1MiB -> 21.1MiB
BatteryStats.dumpLocked(): 49.6MiB -> 42.0MiB
This is because all the memory previously used by Scheduler
is reused by the register allocator; the register allocator
has a higher peak usage of the ArenaStack.
And continue the "arena"->"allocator" renaming.
Test: m test-art-host-gtest
Test: testrunner.py --host
Bug: 64312607
Change-Id: Idfd79a9901552b5147ec0bf591cb38120de86b01
Diffstat (limited to 'compiler/optimizing')
37 files changed, 737 insertions, 686 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index ba26cfc70f..dd8e3d240f 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -617,61 +617,49 @@ std::unique_ptr<CodeGenerator> CodeGenerator::Create(HGraph* graph, const InstructionSetFeatures& isa_features, const CompilerOptions& compiler_options, OptimizingCompilerStats* stats) { - ArenaAllocator* arena = graph->GetAllocator(); + ArenaAllocator* allocator = graph->GetAllocator(); switch (instruction_set) { #ifdef ART_ENABLE_CODEGEN_arm case kArm: case kThumb2: { return std::unique_ptr<CodeGenerator>( - new (arena) arm::CodeGeneratorARMVIXL(graph, - *isa_features.AsArmInstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) arm::CodeGeneratorARMVIXL( + graph, *isa_features.AsArmInstructionSetFeatures(), compiler_options, stats)); } #endif #ifdef ART_ENABLE_CODEGEN_arm64 case kArm64: { return std::unique_ptr<CodeGenerator>( - new (arena) arm64::CodeGeneratorARM64(graph, - *isa_features.AsArm64InstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) arm64::CodeGeneratorARM64( + graph, *isa_features.AsArm64InstructionSetFeatures(), compiler_options, stats)); } #endif #ifdef ART_ENABLE_CODEGEN_mips case kMips: { return std::unique_ptr<CodeGenerator>( - new (arena) mips::CodeGeneratorMIPS(graph, - *isa_features.AsMipsInstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) mips::CodeGeneratorMIPS( + graph, *isa_features.AsMipsInstructionSetFeatures(), compiler_options, stats)); } #endif #ifdef ART_ENABLE_CODEGEN_mips64 case kMips64: { return std::unique_ptr<CodeGenerator>( - new (arena) mips64::CodeGeneratorMIPS64(graph, - *isa_features.AsMips64InstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) mips64::CodeGeneratorMIPS64( + graph, *isa_features.AsMips64InstructionSetFeatures(), compiler_options, stats)); } #endif #ifdef ART_ENABLE_CODEGEN_x86 case kX86: { return std::unique_ptr<CodeGenerator>( - new (arena) x86::CodeGeneratorX86(graph, - *isa_features.AsX86InstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) x86::CodeGeneratorX86( + graph, *isa_features.AsX86InstructionSetFeatures(), compiler_options, stats)); } #endif #ifdef ART_ENABLE_CODEGEN_x86_64 case kX86_64: { return std::unique_ptr<CodeGenerator>( - new (arena) x86_64::CodeGeneratorX86_64(graph, - *isa_features.AsX86_64InstructionSetFeatures(), - compiler_options, - stats)); + new (allocator) x86_64::CodeGeneratorX86_64( + graph, *isa_features.AsX86_64InstructionSetFeatures(), compiler_options, stats)); } #endif default: @@ -910,7 +898,7 @@ void CodeGenerator::MaybeRecordNativeDebugInfo(HInstruction* instruction, } void CodeGenerator::RecordCatchBlockInfo() { - ArenaAllocator* arena = graph_->GetAllocator(); + ArenaAllocator* allocator = graph_->GetAllocator(); for (HBasicBlock* block : *block_order_) { if (!block->IsCatchBlock()) { @@ -925,7 +913,7 @@ void CodeGenerator::RecordCatchBlockInfo() { // The stack mask is not used, so we leave it empty. ArenaBitVector* stack_mask = - ArenaBitVector::Create(arena, 0, /* expandable */ true, kArenaAllocCodeGenerator); + ArenaBitVector::Create(allocator, 0, /* expandable */ true, kArenaAllocCodeGenerator); stack_map_stream_.BeginStackMapEntry(dex_pc, native_pc, diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc index bcf35d9030..10aced02c3 100644 --- a/compiler/optimizing/code_generator_vector_arm64.cc +++ b/compiler/optimizing/code_generator_vector_arm64.cc @@ -179,8 +179,8 @@ void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* ins } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); @@ -372,8 +372,8 @@ void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -772,8 +772,8 @@ void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -967,8 +967,8 @@ void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instructi } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -1216,10 +1216,10 @@ void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* ins } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc index 605c936f52..f84408da49 100644 --- a/compiler/optimizing/code_generator_vector_arm_vixl.cc +++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc @@ -84,8 +84,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecExtractScalar(HVecExtractScalar* i } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); @@ -207,8 +207,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -526,8 +526,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -643,8 +643,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecSetScalars(HVecSetScalars* instruc } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -686,10 +686,10 @@ static bool IsWordAligned(HVecMemoryOperation* instruction) { } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc index 82d90e0367..c5a39ff882 100644 --- a/compiler/optimizing/code_generator_vector_mips.cc +++ b/compiler/optimizing/code_generator_vector_mips.cc @@ -99,8 +99,8 @@ void InstructionCodeGeneratorMIPS::VisitVecExtractScalar(HVecExtractScalar* inst } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); @@ -281,8 +281,8 @@ void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -709,8 +709,8 @@ void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -839,8 +839,8 @@ void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instructio } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -919,10 +919,10 @@ void InstructionCodeGeneratorMIPS::VisitVecSADAccumulate(HVecSADAccumulate* inst } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc index 6b0162a375..e606df2158 100644 --- a/compiler/optimizing/code_generator_vector_mips64.cc +++ b/compiler/optimizing/code_generator_vector_mips64.cc @@ -102,8 +102,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecExtractScalar(HVecExtractScalar* in } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); @@ -285,8 +285,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -713,8 +713,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -843,8 +843,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruct } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -923,10 +923,10 @@ void InstructionCodeGeneratorMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* in } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc index 699c02fb1e..ad8128a5b1 100644 --- a/compiler/optimizing/code_generator_vector_x86.cc +++ b/compiler/optimizing/code_generator_vector_x86.cc @@ -180,8 +180,8 @@ void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instr } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -424,8 +424,8 @@ void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -857,8 +857,8 @@ void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint16: case DataType::Type::kInt16: @@ -1045,8 +1045,8 @@ void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -1084,10 +1084,10 @@ void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instr } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc index d0c4320411..107030e6c2 100644 --- a/compiler/optimizing/code_generator_vector_x86_64.cc +++ b/compiler/optimizing/code_generator_vector_x86_64.cc @@ -163,8 +163,8 @@ void InstructionCodeGeneratorX86_64::VisitVecExtractScalar(HVecExtractScalar* in } // Helper to set up locations for vector unary operations. -static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -407,8 +407,8 @@ void InstructionCodeGeneratorX86_64::VisitVecNot(HVecNot* instruction) { } // Helper to set up locations for vector binary operations. -static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: @@ -840,8 +840,8 @@ void InstructionCodeGeneratorX86_64::VisitVecXor(HVecXor* instruction) { } // Helper to set up locations for vector shift operations. -static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint16: case DataType::Type::kInt16: @@ -1018,8 +1018,8 @@ void InstructionCodeGeneratorX86_64::VisitVecSetScalars(HVecSetScalars* instruct } // Helper to set up locations for vector accumulations. -static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { - LocationSummary* locations = new (arena) LocationSummary(instruction); +static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) { + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kUint8: case DataType::Type::kInt8: @@ -1057,10 +1057,10 @@ void InstructionCodeGeneratorX86_64::VisitVecSADAccumulate(HVecSADAccumulate* in } // Helper to set up locations for vector memory operations. -static void CreateVecMemLocations(ArenaAllocator* arena, +static void CreateVecMemLocations(ArenaAllocator* allocator, HVecMemoryOperation* instruction, bool is_load) { - LocationSummary* locations = new (arena) LocationSummary(instruction); + LocationSummary* locations = new (allocator) LocationSummary(instruction); switch (instruction->GetPackedType()) { case DataType::Type::kBool: case DataType::Type::kUint8: diff --git a/compiler/optimizing/codegen_test_utils.h b/compiler/optimizing/codegen_test_utils.h index 5f4593ff0e..bcbcc12349 100644 --- a/compiler/optimizing/codegen_test_utils.h +++ b/compiler/optimizing/codegen_test_utils.h @@ -295,10 +295,15 @@ static void RunCodeNoCheck(CodeGenerator* codegen, const std::function<void(HGraph*)>& hook_before_codegen, bool has_result, Expected expected) { - SsaLivenessAnalysis liveness(graph, codegen); - PrepareForRegisterAllocation(graph).Run(); - liveness.Analyze(); - RegisterAllocator::Create(graph->GetAllocator(), codegen, liveness)->AllocateRegisters(); + { + ScopedArenaAllocator local_allocator(graph->GetArenaStack()); + SsaLivenessAnalysis liveness(graph, codegen, &local_allocator); + PrepareForRegisterAllocation(graph).Run(); + liveness.Analyze(); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(&local_allocator, codegen, liveness); + register_allocator->AllocateRegisters(); + } hook_before_codegen(graph); InternalCodeAllocator allocator; codegen->Compile(&allocator); diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 1cebeb5bd7..f39acab3d7 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -274,7 +274,7 @@ bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) return false; } - ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetAllocator(); + ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator(); if (mul->HasOnlyOneNonEnvironmentUse()) { HInstruction* use = mul->GetUses().front().GetUser(); @@ -307,14 +307,14 @@ bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) use->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub; if (accumulator != nullptr) { HVecMultiplyAccumulate* mulacc = - new (arena) HVecMultiplyAccumulate(arena, - kind, - accumulator, - mul->GetLeft(), - mul->GetRight(), - binop->GetPackedType(), - binop->GetVectorLength(), - binop->GetDexPc()); + new (allocator) HVecMultiplyAccumulate(allocator, + kind, + accumulator, + mul->GetLeft(), + mul->GetRight(), + binop->GetPackedType(), + binop->GetVectorLength(), + binop->GetDexPc()); binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc); DCHECK(!mul->HasUses()); @@ -700,30 +700,30 @@ void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruct } } -static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) { +static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* allocator, HInstruction* cond) { HInstruction *lhs = cond->InputAt(0); HInstruction *rhs = cond->InputAt(1); switch (cond->GetKind()) { case HInstruction::kEqual: - return new (arena) HEqual(rhs, lhs); + return new (allocator) HEqual(rhs, lhs); case HInstruction::kNotEqual: - return new (arena) HNotEqual(rhs, lhs); + return new (allocator) HNotEqual(rhs, lhs); case HInstruction::kLessThan: - return new (arena) HGreaterThan(rhs, lhs); + return new (allocator) HGreaterThan(rhs, lhs); case HInstruction::kLessThanOrEqual: - return new (arena) HGreaterThanOrEqual(rhs, lhs); + return new (allocator) HGreaterThanOrEqual(rhs, lhs); case HInstruction::kGreaterThan: - return new (arena) HLessThan(rhs, lhs); + return new (allocator) HLessThan(rhs, lhs); case HInstruction::kGreaterThanOrEqual: - return new (arena) HLessThanOrEqual(rhs, lhs); + return new (allocator) HLessThanOrEqual(rhs, lhs); case HInstruction::kBelow: - return new (arena) HAbove(rhs, lhs); + return new (allocator) HAbove(rhs, lhs); case HInstruction::kBelowOrEqual: - return new (arena) HAboveOrEqual(rhs, lhs); + return new (allocator) HAboveOrEqual(rhs, lhs); case HInstruction::kAbove: - return new (arena) HBelow(rhs, lhs); + return new (allocator) HBelow(rhs, lhs); case HInstruction::kAboveOrEqual: - return new (arena) HBelowOrEqual(rhs, lhs); + return new (allocator) HBelowOrEqual(rhs, lhs); default: LOG(FATAL) << "Unknown ConditionType " << cond->GetKind(); } @@ -837,7 +837,9 @@ void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) { } // Constructs a new ABS(x) node in the HIR. -static HInstruction* NewIntegralAbs(ArenaAllocator* arena, HInstruction* x, HInstruction* cursor) { +static HInstruction* NewIntegralAbs(ArenaAllocator* allocator, + HInstruction* x, + HInstruction* cursor) { DataType::Type type = x->GetType(); DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); // Construct a fake intrinsic with as much context as is needed to allocate one. @@ -848,8 +850,8 @@ static HInstruction* NewIntegralAbs(ArenaAllocator* arena, HInstruction* x, HIns HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod, 0u }; - HInvokeStaticOrDirect* invoke = new (arena) HInvokeStaticOrDirect( - arena, + HInvokeStaticOrDirect* invoke = new (allocator) HInvokeStaticOrDirect( + allocator, 1, type, x->GetDexPc(), @@ -2180,20 +2182,20 @@ void InstructionSimplifierVisitor::SimplifyStringCharAt(HInvoke* invoke) { HInstruction* str = invoke->InputAt(0); HInstruction* index = invoke->InputAt(1); uint32_t dex_pc = invoke->GetDexPc(); - ArenaAllocator* arena = GetGraph()->GetAllocator(); + ArenaAllocator* allocator = GetGraph()->GetAllocator(); // We treat String as an array to allow DCE and BCE to seamlessly work on strings, // so create the HArrayLength, HBoundsCheck and HArrayGet. - HArrayLength* length = new (arena) HArrayLength(str, dex_pc, /* is_string_length */ true); + HArrayLength* length = new (allocator) HArrayLength(str, dex_pc, /* is_string_length */ true); invoke->GetBlock()->InsertInstructionBefore(length, invoke); - HBoundsCheck* bounds_check = new (arena) HBoundsCheck( + HBoundsCheck* bounds_check = new (allocator) HBoundsCheck( index, length, dex_pc, invoke->GetDexMethodIndex()); invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke); - HArrayGet* array_get = new (arena) HArrayGet(str, - bounds_check, - DataType::Type::kUint16, - SideEffects::None(), // Strings are immutable. - dex_pc, - /* is_string_char_at */ true); + HArrayGet* array_get = new (allocator) HArrayGet(str, + bounds_check, + DataType::Type::kUint16, + SideEffects::None(), // Strings are immutable. + dex_pc, + /* is_string_char_at */ true); invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get); bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment()); GetGraph()->SetHasBoundsChecks(true); @@ -2524,13 +2526,13 @@ bool InstructionSimplifierVisitor::TrySubtractionChainSimplification( int64_t const3_val = ComputeAddition(type, const1_val, const2_val); HBasicBlock* block = instruction->GetBlock(); HConstant* const3 = block->GetGraph()->GetConstant(type, const3_val); - ArenaAllocator* arena = instruction->GetAllocator(); + ArenaAllocator* allocator = instruction->GetAllocator(); HInstruction* z; if (is_x_negated) { - z = new (arena) HSub(type, const3, x, instruction->GetDexPc()); + z = new (allocator) HSub(type, const3, x, instruction->GetDexPc()); } else { - z = new (arena) HAdd(type, x, const3, instruction->GetDexPc()); + z = new (allocator) HAdd(type, x, const3, instruction->GetDexPc()); } block->ReplaceAndRemoveInstructionWith(instruction, z); diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc index 037e98c3bf..1c13084a48 100644 --- a/compiler/optimizing/instruction_simplifier_shared.cc +++ b/compiler/optimizing/instruction_simplifier_shared.cc @@ -75,8 +75,8 @@ bool TrySimpleMultiplyAccumulatePatterns(HMul* mul, return false; } - ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetAllocator(); - HMultiplyAccumulate* mulacc = new(arena) HMultiplyAccumulate( + ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator(); + HMultiplyAccumulate* mulacc = new (allocator) HMultiplyAccumulate( mul->GetType(), op_kind, input_a, input_a, input_b, mul->GetDexPc()); mul->GetBlock()->ReplaceAndRemoveInstructionWith(mul, mulacc); @@ -105,7 +105,7 @@ bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) { return false; } - ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetAllocator(); + ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator(); if (mul->HasOnlyOneNonEnvironmentUse()) { HInstruction* use = mul->GetUses().front().GetUser(); @@ -137,11 +137,11 @@ bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) { if (accumulator != nullptr) { HMultiplyAccumulate* mulacc = - new (arena) HMultiplyAccumulate(type, - binop->GetKind(), - accumulator, - mul->GetLeft(), - mul->GetRight()); + new (allocator) HMultiplyAccumulate(type, + binop->GetKind(), + accumulator, + mul->GetLeft(), + mul->GetRight()); binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc); DCHECK(!mul->HasUses()); @@ -150,11 +150,11 @@ bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) { } } else if (use->IsNeg() && isa != kArm) { HMultiplyAccumulate* mulacc = - new (arena) HMultiplyAccumulate(type, - HInstruction::kSub, - mul->GetBlock()->GetGraph()->GetConstant(type, 0), - mul->GetLeft(), - mul->GetRight()); + new (allocator) HMultiplyAccumulate(type, + HInstruction::kSub, + mul->GetBlock()->GetGraph()->GetConstant(type, 0), + mul->GetLeft(), + mul->GetRight()); use->GetBlock()->ReplaceAndRemoveInstructionWith(use, mulacc); DCHECK(!mul->HasUses()); @@ -255,10 +255,10 @@ bool TryExtractArrayAccessAddress(HInstruction* access, // Proceed to extract the base address computation. HGraph* graph = access->GetBlock()->GetGraph(); - ArenaAllocator* arena = graph->GetAllocator(); + ArenaAllocator* allocator = graph->GetAllocator(); HIntConstant* offset = graph->GetIntConstant(data_offset); - HIntermediateAddress* address = new (arena) HIntermediateAddress(array, offset, kNoDexPc); + HIntermediateAddress* address = new (allocator) HIntermediateAddress(array, offset, kNoDexPc); // TODO: Is it ok to not have this on the intermediate address? // address->SetReferenceTypeInfo(array->GetReferenceTypeInfo()); access->GetBlock()->InsertInstructionBefore(address, access); @@ -289,7 +289,7 @@ bool TryExtractVecArrayAccessAddress(HVecMemoryOperation* access, HInstruction* } HGraph* graph = access->GetBlock()->GetGraph(); - ArenaAllocator* arena = graph->GetAllocator(); + ArenaAllocator* allocator = graph->GetAllocator(); DataType::Type packed_type = access->GetPackedType(); uint32_t data_offset = mirror::Array::DataOffset( DataType::Size(packed_type)).Uint32Value(); @@ -328,7 +328,7 @@ bool TryExtractVecArrayAccessAddress(HVecMemoryOperation* access, HInstruction* HIntConstant* offset = graph->GetIntConstant(data_offset); HIntConstant* shift = graph->GetIntConstant(component_shift); HIntermediateAddressIndex* address = - new (arena) HIntermediateAddressIndex(index, offset, shift, kNoDexPc); + new (allocator) HIntermediateAddressIndex(index, offset, shift, kNoDexPc); access->GetBlock()->InsertInstructionBefore(address, access); access->ReplaceInput(address, 1); diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc index e82fab9b46..b2a9c0a8e7 100644 --- a/compiler/optimizing/linearize_test.cc +++ b/compiler/optimizing/linearize_test.cc @@ -45,7 +45,7 @@ void LinearizeTest::TestCode(const uint16_t* data, std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); ASSERT_EQ(graph->GetLinearOrder().size(), number_of_blocks); diff --git a/compiler/optimizing/live_interval_test.cc b/compiler/optimizing/live_interval_test.cc index 405f261986..c60386d7b7 100644 --- a/compiler/optimizing/live_interval_test.cc +++ b/compiler/optimizing/live_interval_test.cc @@ -23,29 +23,29 @@ namespace art { TEST(LiveInterval, GetStart) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { static constexpr size_t ranges[][2] = {{0, 42}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_EQ(0u, interval->GetStart()); } { static constexpr size_t ranges[][2] = {{4, 12}, {14, 16}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_EQ(4u, interval->GetStart()); } } TEST(LiveInterval, IsDeadAt) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { static constexpr size_t ranges[][2] = {{0, 42}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_TRUE(interval->IsDeadAt(42)); ASSERT_TRUE(interval->IsDeadAt(43)); ASSERT_FALSE(interval->IsDeadAt(41)); @@ -55,7 +55,7 @@ TEST(LiveInterval, IsDeadAt) { { static constexpr size_t ranges[][2] = {{4, 12}, {14, 16}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_TRUE(interval->IsDeadAt(16)); ASSERT_TRUE(interval->IsDeadAt(32)); ASSERT_FALSE(interval->IsDeadAt(0)); @@ -68,12 +68,12 @@ TEST(LiveInterval, IsDeadAt) { } TEST(LiveInterval, Covers) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { static constexpr size_t ranges[][2] = {{0, 42}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_TRUE(interval->Covers(0)); ASSERT_TRUE(interval->Covers(4)); ASSERT_TRUE(interval->Covers(41)); @@ -83,7 +83,7 @@ TEST(LiveInterval, Covers) { { static constexpr size_t ranges[][2] = {{4, 12}, {14, 16}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); ASSERT_FALSE(interval->Covers(0)); ASSERT_TRUE(interval->Covers(4)); ASSERT_TRUE(interval->Covers(11)); @@ -96,68 +96,68 @@ TEST(LiveInterval, Covers) { } TEST(LiveInterval, FirstIntersectionWith) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { static constexpr size_t ranges1[][2] = {{0, 4}, {8, 10}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{5, 6}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(kNoLifetime, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 4}, {8, 10}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{5, 42}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(8u, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 4}, {8, 10}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{5, 6}, {7, 8}, {11, 12}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(kNoLifetime, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 4}, {8, 10}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{5, 6}, {7, 8}, {9, 10}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(9u, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 1}, {2, 7}, {8, 10}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{1, 2}, {6, 7}, {9, 10}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(6u, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 1}, {2, 8}, {55, 58}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{1, 2}, {11, 42}, {43, 48}, {54, 56}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(55u, interval1->FirstIntersectionWith(interval2)); } { static constexpr size_t ranges1[][2] = {{0, 1}, {2, 8}, {15, 18}, {27, 32}, {41, 53}, {54, 60}}; - LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), &allocator); + LiveInterval* interval1 = BuildInterval(ranges1, arraysize(ranges1), allocator); static constexpr size_t ranges2[][2] = {{1, 2}, {11, 12}, {19, 25}, {34, 42}, {52, 60}}; - LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), &allocator); + LiveInterval* interval2 = BuildInterval(ranges2, arraysize(ranges2), allocator); ASSERT_EQ(41u, interval1->FirstIntersectionWith(interval2)); } @@ -188,13 +188,13 @@ static bool RangesEquals(LiveInterval* interval, } TEST(LiveInterval, SplitAt) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { // Test within one range. static constexpr size_t ranges[][2] = {{0, 4}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(1); static constexpr size_t expected[][2] = {{0, 1}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -205,7 +205,7 @@ TEST(LiveInterval, SplitAt) { { // Test just before the end of one range. static constexpr size_t ranges[][2] = {{0, 4}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(3); static constexpr size_t expected[][2] = {{0, 3}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -216,7 +216,7 @@ TEST(LiveInterval, SplitAt) { { // Test withing the first range. static constexpr size_t ranges[][2] = {{0, 4}, {8, 12}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(1); static constexpr size_t expected[][2] = {{0, 1}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -227,7 +227,7 @@ TEST(LiveInterval, SplitAt) { { // Test in a hole. static constexpr size_t ranges[][2] = {{0, 4}, {8, 12}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(5); static constexpr size_t expected[][2] = {{0, 4}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -238,7 +238,7 @@ TEST(LiveInterval, SplitAt) { { // Test withing the second range. static constexpr size_t ranges[][2] = {{0, 4}, {8, 12}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(9); static constexpr size_t expected[][2] = {{0, 4}, {8, 9}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -249,7 +249,7 @@ TEST(LiveInterval, SplitAt) { { // Test at the beginning of the second range. static constexpr size_t ranges[][2] = {{0, 4}, {6, 10}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(6); static constexpr size_t expected[][2] = {{0, 4}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -260,7 +260,7 @@ TEST(LiveInterval, SplitAt) { { // Test at the end of the first range. static constexpr size_t ranges[][2] = {{0, 4}, {6, 10}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(4); static constexpr size_t expected[][2] = {{0, 4}}; ASSERT_TRUE(RangesEquals(interval, expected, arraysize(expected))); @@ -271,7 +271,7 @@ TEST(LiveInterval, SplitAt) { { // Test that we get null if we split at a position where the interval is dead. static constexpr size_t ranges[][2] = {{0, 4}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); LiveInterval* split = interval->SplitAt(5); ASSERT_TRUE(split == nullptr); ASSERT_TRUE(RangesEquals(interval, ranges, arraysize(ranges))); @@ -279,13 +279,13 @@ TEST(LiveInterval, SplitAt) { } TEST(LiveInterval, AddLoopRange) { - ArenaPool pool; - ArenaAllocator allocator(&pool); + ArenaPoolAndAllocator pool; + ScopedArenaAllocator* allocator = pool.GetScopedAllocator(); { // Test when only used in a loop. static constexpr size_t ranges[][2] = {{0, 4}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); interval->AddLoopRange(0, 8); LiveRange* range = interval->GetFirstRange(); ASSERT_TRUE(range->GetNext() == nullptr); @@ -296,7 +296,7 @@ TEST(LiveInterval, AddLoopRange) { { // Test when only used in a loop. static constexpr size_t ranges[][2] = {{2, 4}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); interval->AddLoopRange(0, 8); LiveRange* range = interval->GetFirstRange(); ASSERT_TRUE(range->GetNext() == nullptr); @@ -307,7 +307,7 @@ TEST(LiveInterval, AddLoopRange) { { // Test when used just after the loop. static constexpr size_t ranges[][2] = {{2, 4}, {8, 10}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); interval->AddLoopRange(0, 8); LiveRange* range = interval->GetFirstRange(); ASSERT_TRUE(range->GetNext() == nullptr); @@ -318,7 +318,7 @@ TEST(LiveInterval, AddLoopRange) { { // Test when use after the loop is after a lifetime hole. static constexpr size_t ranges[][2] = {{2, 4}, {10, 12}}; - LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), &allocator); + LiveInterval* interval = BuildInterval(ranges, arraysize(ranges), allocator); interval->AddLoopRange(0, 8); LiveRange* range = interval->GetFirstRange(); ASSERT_EQ(range->GetStart(), 0u); diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc index 8087fe0988..ddcad5aed8 100644 --- a/compiler/optimizing/live_ranges_test.cc +++ b/compiler/optimizing/live_ranges_test.cc @@ -66,7 +66,7 @@ TEST_F(LiveRangesTest, CFG1) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval(); @@ -112,7 +112,7 @@ TEST_F(LiveRangesTest, CFG2) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval(); @@ -161,7 +161,7 @@ TEST_F(LiveRangesTest, CFG3) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Test for the 4 constant. @@ -238,7 +238,7 @@ TEST_F(LiveRangesTest, Loop1) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Test for the 0 constant. @@ -315,7 +315,7 @@ TEST_F(LiveRangesTest, Loop2) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Test for the 0 constant. @@ -391,7 +391,7 @@ TEST_F(LiveRangesTest, CFG4) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Test for the 0 constant. diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc index 7793965148..3eadc8f8fc 100644 --- a/compiler/optimizing/liveness_test.cc +++ b/compiler/optimizing/liveness_test.cc @@ -53,7 +53,7 @@ void LivenessTest::TestCode(const uint16_t* data, const char* expected) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); std::ostringstream buffer; diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc index 29dfddf4d6..5879c6fa07 100644 --- a/compiler/optimizing/locations.cc +++ b/compiler/optimizing/locations.cc @@ -43,8 +43,7 @@ LocationSummary::LocationSummary(HInstruction* instruction, instruction->SetLocations(this); if (NeedsSafepoint()) { - ArenaAllocator* arena = instruction->GetBlock()->GetGraph()->GetAllocator(); - stack_mask_ = ArenaBitVector::Create(arena, 0, true, kArenaAllocLocationSummary); + stack_mask_ = ArenaBitVector::Create(allocator, 0, true, kArenaAllocLocationSummary); } } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 3c584bd67d..99fde755da 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1800,21 +1800,23 @@ class SideEffects : public ValueObject { // A HEnvironment object contains the values of virtual registers at a given location. class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { public: - ALWAYS_INLINE HEnvironment(ArenaAllocator* arena, + ALWAYS_INLINE HEnvironment(ArenaAllocator* allocator, size_t number_of_vregs, ArtMethod* method, uint32_t dex_pc, HInstruction* holder) - : vregs_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentVRegs)), - locations_(arena->Adapter(kArenaAllocEnvironmentLocations)), + : vregs_(number_of_vregs, allocator->Adapter(kArenaAllocEnvironmentVRegs)), + locations_(allocator->Adapter(kArenaAllocEnvironmentLocations)), parent_(nullptr), method_(method), dex_pc_(dex_pc), holder_(holder) { } - ALWAYS_INLINE HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder) - : HEnvironment(arena, + ALWAYS_INLINE HEnvironment(ArenaAllocator* allocator, + const HEnvironment& to_copy, + HInstruction* holder) + : HEnvironment(allocator, to_copy.Size(), to_copy.GetMethod(), to_copy.GetDexPc(), @@ -2475,11 +2477,11 @@ class HVariableInputSizeInstruction : public HInstruction { protected: HVariableInputSizeInstruction(SideEffects side_effects, uint32_t dex_pc, - ArenaAllocator* arena, + ArenaAllocator* allocator, size_t number_of_inputs, ArenaAllocKind kind) : HInstruction(side_effects, dex_pc), - inputs_(number_of_inputs, arena->Adapter(kind)) {} + inputs_(number_of_inputs, allocator->Adapter(kind)) {} ArenaVector<HUserRecord<HInstruction*>> inputs_; @@ -2580,7 +2582,7 @@ class HReturn FINAL : public HTemplateInstruction<1> { class HPhi FINAL : public HVariableInputSizeInstruction { public: - HPhi(ArenaAllocator* arena, + HPhi(ArenaAllocator* allocator, uint32_t reg_number, size_t number_of_inputs, DataType::Type type, @@ -2588,7 +2590,7 @@ class HPhi FINAL : public HVariableInputSizeInstruction { : HVariableInputSizeInstruction( SideEffects::None(), dex_pc, - arena, + allocator, number_of_inputs, kArenaAllocPhiInputs), reg_number_(reg_number) { @@ -3027,11 +3029,14 @@ class HDeoptimize FINAL : public HVariableInputSizeInstruction { public: // Use this constructor when the `HDeoptimize` acts as a barrier, where no code can move // across. - HDeoptimize(ArenaAllocator* arena, HInstruction* cond, DeoptimizationKind kind, uint32_t dex_pc) + HDeoptimize(ArenaAllocator* allocator, + HInstruction* cond, + DeoptimizationKind kind, + uint32_t dex_pc) : HVariableInputSizeInstruction( SideEffects::All(), dex_pc, - arena, + allocator, /* number_of_inputs */ 1, kArenaAllocMisc) { SetPackedFlag<kFieldCanBeMoved>(false); @@ -3044,7 +3049,7 @@ class HDeoptimize FINAL : public HVariableInputSizeInstruction { // instead of `guard`. // We set CanTriggerGC to prevent any intermediate address to be live // at the point of the `HDeoptimize`. - HDeoptimize(ArenaAllocator* arena, + HDeoptimize(ArenaAllocator* allocator, HInstruction* cond, HInstruction* guard, DeoptimizationKind kind, @@ -3052,7 +3057,7 @@ class HDeoptimize FINAL : public HVariableInputSizeInstruction { : HVariableInputSizeInstruction( SideEffects::CanTriggerGC(), dex_pc, - arena, + allocator, /* number_of_inputs */ 2, kArenaAllocMisc) { SetPackedFlag<kFieldCanBeMoved>(true); @@ -3116,8 +3121,8 @@ class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction { public: // CHA guards are only optimized in a separate pass and it has no side effects // with regard to other passes. - HShouldDeoptimizeFlag(ArenaAllocator* arena, uint32_t dex_pc) - : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, arena, 0, kArenaAllocCHA) { + HShouldDeoptimizeFlag(ArenaAllocator* allocator, uint32_t dex_pc) + : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, allocator, 0, kArenaAllocCHA) { } DataType::Type GetType() const OVERRIDE { return DataType::Type::kInt32; } @@ -4084,7 +4089,7 @@ class HInvoke : public HVariableInputSizeInstruction { using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>; using ReturnTypeField = BitField<DataType::Type, kFieldReturnType, kFieldReturnTypeSize>; - HInvoke(ArenaAllocator* arena, + HInvoke(ArenaAllocator* allocator, uint32_t number_of_arguments, uint32_t number_of_other_inputs, DataType::Type return_type, @@ -4095,7 +4100,7 @@ class HInvoke : public HVariableInputSizeInstruction { : HVariableInputSizeInstruction( SideEffects::AllExceptGCDependency(), // Assume write/read on all fields/arrays. dex_pc, - arena, + allocator, number_of_arguments + number_of_other_inputs, kArenaAllocInvokeInputs), number_of_arguments_(number_of_arguments), @@ -4122,13 +4127,13 @@ class HInvoke : public HVariableInputSizeInstruction { class HInvokeUnresolved FINAL : public HInvoke { public: - HInvokeUnresolved(ArenaAllocator* arena, + HInvokeUnresolved(ArenaAllocator* allocator, uint32_t number_of_arguments, DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, InvokeType invoke_type) - : HInvoke(arena, + : HInvoke(allocator, number_of_arguments, 0u /* number_of_other_inputs */, return_type, @@ -4146,12 +4151,12 @@ class HInvokeUnresolved FINAL : public HInvoke { class HInvokePolymorphic FINAL : public HInvoke { public: - HInvokePolymorphic(ArenaAllocator* arena, + HInvokePolymorphic(ArenaAllocator* allocator, uint32_t number_of_arguments, DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index) - : HInvoke(arena, + : HInvoke(allocator, number_of_arguments, 0u /* number_of_other_inputs */, return_type, @@ -4223,7 +4228,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { uint64_t method_load_data; }; - HInvokeStaticOrDirect(ArenaAllocator* arena, + HInvokeStaticOrDirect(ArenaAllocator* allocator, uint32_t number_of_arguments, DataType::Type return_type, uint32_t dex_pc, @@ -4233,7 +4238,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { InvokeType invoke_type, MethodReference target_method, ClinitCheckRequirement clinit_check_requirement) - : HInvoke(arena, + : HInvoke(allocator, number_of_arguments, // There is potentially one extra argument for the HCurrentMethod node, and // potentially one other if the clinit check is explicit, and potentially @@ -4418,14 +4423,14 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckReq class HInvokeVirtual FINAL : public HInvoke { public: - HInvokeVirtual(ArenaAllocator* arena, + HInvokeVirtual(ArenaAllocator* allocator, uint32_t number_of_arguments, DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, ArtMethod* resolved_method, uint32_t vtable_index) - : HInvoke(arena, + : HInvoke(allocator, number_of_arguments, 0u, return_type, @@ -4466,14 +4471,14 @@ class HInvokeVirtual FINAL : public HInvoke { class HInvokeInterface FINAL : public HInvoke { public: - HInvokeInterface(ArenaAllocator* arena, + HInvokeInterface(ArenaAllocator* allocator, uint32_t number_of_arguments, DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, ArtMethod* resolved_method, uint32_t imt_index) - : HInvoke(arena, + : HInvoke(allocator, number_of_arguments, 0u, return_type, @@ -6645,7 +6650,7 @@ class HConstructorFence FINAL : public HVariableInputSizeInstruction { // about the associated object. HConstructorFence(HInstruction* fence_object, uint32_t dex_pc, - ArenaAllocator* arena) + ArenaAllocator* allocator) // We strongly suspect there is not a more accurate way to describe the fine-grained reordering // constraints described in the class header. We claim that these SideEffects constraints // enforce a superset of the real constraints. @@ -6669,7 +6674,7 @@ class HConstructorFence FINAL : public HVariableInputSizeInstruction { // we can refine the side effect to a smaller set of type reads (see above constraints). : HVariableInputSizeInstruction(SideEffects::AllReads(), dex_pc, - arena, + allocator, /* number_of_inputs */ 1, kArenaAllocConstructorFenceInputs) { DCHECK(fence_object != nullptr); @@ -6886,9 +6891,9 @@ static constexpr size_t kDefaultNumberOfMoves = 4; class HParallelMove FINAL : public HTemplateInstruction<0> { public: - explicit HParallelMove(ArenaAllocator* arena, uint32_t dex_pc = kNoDexPc) + explicit HParallelMove(ArenaAllocator* allocator, uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc), - moves_(arena->Adapter(kArenaAllocMoveOperands)) { + moves_(allocator->Adapter(kArenaAllocMoveOperands)) { moves_.reserve(kDefaultNumberOfMoves); } diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h index 8f3ab11d00..781a59f661 100644 --- a/compiler/optimizing/nodes_vector.h +++ b/compiler/optimizing/nodes_vector.h @@ -71,7 +71,7 @@ class HVecOperation : public HVariableInputSizeInstruction { // TODO: we could introduce SIMD types in HIR. static constexpr DataType::Type kSIMDType = DataType::Type::kFloat64; - HVecOperation(ArenaAllocator* arena, + HVecOperation(ArenaAllocator* allocator, DataType::Type packed_type, SideEffects side_effects, size_t number_of_inputs, @@ -79,7 +79,7 @@ class HVecOperation : public HVariableInputSizeInstruction { uint32_t dex_pc) : HVariableInputSizeInstruction(side_effects, dex_pc, - arena, + allocator, number_of_inputs, kArenaAllocVectorNode), vector_length_(vector_length) { @@ -156,12 +156,12 @@ class HVecOperation : public HVariableInputSizeInstruction { // Abstraction of a unary vector operation. class HVecUnaryOperation : public HVecOperation { public: - HVecUnaryOperation(ArenaAllocator* arena, + HVecUnaryOperation(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecOperation(arena, + : HVecOperation(allocator, packed_type, SideEffects::None(), /* number_of_inputs */ 1, @@ -181,13 +181,13 @@ class HVecUnaryOperation : public HVecOperation { // Abstraction of a binary vector operation. class HVecBinaryOperation : public HVecOperation { public: - HVecBinaryOperation(ArenaAllocator* arena, + HVecBinaryOperation(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecOperation(arena, + : HVecOperation(allocator, packed_type, SideEffects::None(), /* number_of_inputs */ 2, @@ -210,13 +210,18 @@ class HVecBinaryOperation : public HVecOperation { // The Android runtime guarantees elements have at least natural alignment. class HVecMemoryOperation : public HVecOperation { public: - HVecMemoryOperation(ArenaAllocator* arena, + HVecMemoryOperation(ArenaAllocator* allocator, DataType::Type packed_type, SideEffects side_effects, size_t number_of_inputs, size_t vector_length, uint32_t dex_pc) - : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc), + : HVecOperation(allocator, + packed_type, + side_effects, + number_of_inputs, + vector_length, + dex_pc), alignment_(DataType::Size(packed_type), 0) { DCHECK_GE(number_of_inputs, 2u); } @@ -260,12 +265,12 @@ inline static bool HasConsistentPackedTypes(HInstruction* input, DataType::Type // viz. replicate(x) = [ x, .. , x ]. class HVecReplicateScalar FINAL : public HVecUnaryOperation { public: - HVecReplicateScalar(ArenaAllocator* arena, + HVecReplicateScalar(ArenaAllocator* allocator, HInstruction* scalar, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, scalar, packed_type, vector_length, dex_pc) { DCHECK(!scalar->IsVecOperation()); } @@ -285,13 +290,13 @@ class HVecReplicateScalar FINAL : public HVecUnaryOperation { // TODO: for now only i == 1 case supported. class HVecExtractScalar FINAL : public HVecUnaryOperation { public: - HVecExtractScalar(ArenaAllocator* arena, + HVecExtractScalar(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, size_t index, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(input, packed_type)); DCHECK_LT(index, vector_length); DCHECK_EQ(index, 0u); @@ -323,13 +328,13 @@ class HVecReduce FINAL : public HVecUnaryOperation { kMax = 3 }; - HVecReduce(ArenaAllocator* arena, + HVecReduce(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, ReductionKind kind, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc), + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc), kind_(kind) { DCHECK(HasConsistentPackedTypes(input, packed_type)); } @@ -356,12 +361,12 @@ class HVecReduce FINAL : public HVecUnaryOperation { // viz. cnv[ x1, .. , xn ] = [ cnv(x1), .. , cnv(xn) ]. class HVecCnv FINAL : public HVecUnaryOperation { public: - HVecCnv(ArenaAllocator* arena, + HVecCnv(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); DCHECK_NE(GetInputType(), GetResultType()); // actual convert } @@ -381,12 +386,12 @@ class HVecCnv FINAL : public HVecUnaryOperation { // viz. neg[ x1, .. , xn ] = [ -x1, .. , -xn ]. class HVecNeg FINAL : public HVecUnaryOperation { public: - HVecNeg(ArenaAllocator* arena, + HVecNeg(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(input, packed_type)); } @@ -403,12 +408,12 @@ class HVecNeg FINAL : public HVecUnaryOperation { // for signed operand x. class HVecAbs FINAL : public HVecUnaryOperation { public: - HVecAbs(ArenaAllocator* arena, + HVecAbs(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(input, packed_type)); } @@ -425,12 +430,12 @@ class HVecAbs FINAL : public HVecUnaryOperation { // not[ x1, .. , xn ] = [ !x1, .. , !xn ] for boolean. class HVecNot FINAL : public HVecUnaryOperation { public: - HVecNot(ArenaAllocator* arena, + HVecNot(ArenaAllocator* allocator, HInstruction* input, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(allocator, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); } @@ -450,13 +455,13 @@ class HVecNot FINAL : public HVecUnaryOperation { // viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ]. class HVecAdd FINAL : public HVecBinaryOperation { public: - HVecAdd(ArenaAllocator* arena, + HVecAdd(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); DCHECK(HasConsistentPackedTypes(right, packed_type)); } @@ -475,7 +480,7 @@ class HVecAdd FINAL : public HVecBinaryOperation { // for either both signed or both unsigned operands x, y. class HVecHalvingAdd FINAL : public HVecBinaryOperation { public: - HVecHalvingAdd(ArenaAllocator* arena, + HVecHalvingAdd(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, @@ -483,7 +488,7 @@ class HVecHalvingAdd FINAL : public HVecBinaryOperation { bool is_rounded, bool is_unsigned, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { // The `is_unsigned` flag should be used exclusively with the Int32 or Int64. // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types. DCHECK(!is_unsigned || @@ -524,13 +529,13 @@ class HVecHalvingAdd FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] - [ y1, .. , yn ] = [ x1 - y1, .. , xn - yn ]. class HVecSub FINAL : public HVecBinaryOperation { public: - HVecSub(ArenaAllocator* arena, + HVecSub(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); DCHECK(HasConsistentPackedTypes(right, packed_type)); } @@ -547,13 +552,13 @@ class HVecSub FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] * [ y1, .. , yn ] = [ x1 * y1, .. , xn * yn ]. class HVecMul FINAL : public HVecBinaryOperation { public: - HVecMul(ArenaAllocator* arena, + HVecMul(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); DCHECK(HasConsistentPackedTypes(right, packed_type)); } @@ -570,13 +575,13 @@ class HVecMul FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] / [ y1, .. , yn ] = [ x1 / y1, .. , xn / yn ]. class HVecDiv FINAL : public HVecBinaryOperation { public: - HVecDiv(ArenaAllocator* arena, + HVecDiv(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); DCHECK(HasConsistentPackedTypes(right, packed_type)); } @@ -594,14 +599,14 @@ class HVecDiv FINAL : public HVecBinaryOperation { // for either both signed or both unsigned operands x, y. class HVecMin FINAL : public HVecBinaryOperation { public: - HVecMin(ArenaAllocator* arena, + HVecMin(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, bool is_unsigned, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { // The `is_unsigned` flag should be used exclusively with the Int32 or Int64. // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types. DCHECK(!is_unsigned || @@ -638,14 +643,14 @@ class HVecMin FINAL : public HVecBinaryOperation { // for either both signed or both unsigned operands x, y. class HVecMax FINAL : public HVecBinaryOperation { public: - HVecMax(ArenaAllocator* arena, + HVecMax(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, bool is_unsigned, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { // The `is_unsigned` flag should be used exclusively with the Int32 or Int64. // This flag is a temporary measure while we do not have the Uint32 and Uint64 data types. DCHECK(!is_unsigned || @@ -681,13 +686,13 @@ class HVecMax FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] & [ y1, .. , yn ] = [ x1 & y1, .. , xn & yn ]. class HVecAnd FINAL : public HVecBinaryOperation { public: - HVecAnd(ArenaAllocator* arena, + HVecAnd(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); } @@ -703,13 +708,13 @@ class HVecAnd FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] and-not [ y1, .. , yn ] = [ ~x1 & y1, .. , ~xn & yn ]. class HVecAndNot FINAL : public HVecBinaryOperation { public: - HVecAndNot(ArenaAllocator* arena, + HVecAndNot(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); } @@ -725,13 +730,13 @@ class HVecAndNot FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] | [ y1, .. , yn ] = [ x1 | y1, .. , xn | yn ]. class HVecOr FINAL : public HVecBinaryOperation { public: - HVecOr(ArenaAllocator* arena, + HVecOr(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); } @@ -747,13 +752,13 @@ class HVecOr FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] ^ [ y1, .. , yn ] = [ x1 ^ y1, .. , xn ^ yn ]. class HVecXor FINAL : public HVecBinaryOperation { public: - HVecXor(ArenaAllocator* arena, + HVecXor(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); } @@ -769,13 +774,13 @@ class HVecXor FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] << d = [ x1 << d, .. , xn << d ]. class HVecShl FINAL : public HVecBinaryOperation { public: - HVecShl(ArenaAllocator* arena, + HVecShl(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); } @@ -791,13 +796,13 @@ class HVecShl FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] >> d = [ x1 >> d, .. , xn >> d ]. class HVecShr FINAL : public HVecBinaryOperation { public: - HVecShr(ArenaAllocator* arena, + HVecShr(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); } @@ -813,13 +818,13 @@ class HVecShr FINAL : public HVecBinaryOperation { // viz. [ x1, .. , xn ] >>> d = [ x1 >>> d, .. , xn >>> d ]. class HVecUShr FINAL : public HVecBinaryOperation { public: - HVecUShr(ArenaAllocator* arena, + HVecUShr(ArenaAllocator* allocator, HInstruction* left, HInstruction* right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(allocator, left, right, packed_type, vector_length, dex_pc) { DCHECK(HasConsistentPackedTypes(left, packed_type)); } @@ -840,13 +845,13 @@ class HVecUShr FINAL : public HVecBinaryOperation { // set( array(x1, .. , xm) ) = [ x1, .. , xm, 0, .. , 0 ] if m < n. class HVecSetScalars FINAL : public HVecOperation { public: - HVecSetScalars(ArenaAllocator* arena, + HVecSetScalars(ArenaAllocator* allocator, HInstruction* scalars[], DataType::Type packed_type, size_t vector_length, size_t number_of_scalars, uint32_t dex_pc) - : HVecOperation(arena, + : HVecOperation(allocator, packed_type, SideEffects::None(), number_of_scalars, @@ -872,7 +877,7 @@ class HVecSetScalars FINAL : public HVecOperation { // viz. [ a1, .. , an ] + [ x1, .. , xn ] * [ y1, .. , yn ] = [ a1 + x1 * y1, .. , an + xn * yn ]. class HVecMultiplyAccumulate FINAL : public HVecOperation { public: - HVecMultiplyAccumulate(ArenaAllocator* arena, + HVecMultiplyAccumulate(ArenaAllocator* allocator, InstructionKind op, HInstruction* accumulator, HInstruction* mul_left, @@ -880,7 +885,7 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation { DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecOperation(arena, + : HVecOperation(allocator, packed_type, SideEffects::None(), /* number_of_inputs */ 3, @@ -922,14 +927,14 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation { // for m <= n, non-overlapping sums, and signed operands x, y. class HVecSADAccumulate FINAL : public HVecOperation { public: - HVecSADAccumulate(ArenaAllocator* arena, + HVecSADAccumulate(ArenaAllocator* allocator, HInstruction* accumulator, HInstruction* sad_left, HInstruction* sad_right, DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) - : HVecOperation(arena, + : HVecOperation(allocator, packed_type, SideEffects::None(), /* number_of_inputs */ 3, @@ -955,7 +960,7 @@ class HVecSADAccumulate FINAL : public HVecOperation { // yield the vector [ mem(1), .. , mem(n) ]. class HVecLoad FINAL : public HVecMemoryOperation { public: - HVecLoad(ArenaAllocator* arena, + HVecLoad(ArenaAllocator* allocator, HInstruction* base, HInstruction* index, DataType::Type packed_type, @@ -963,7 +968,7 @@ class HVecLoad FINAL : public HVecMemoryOperation { size_t vector_length, bool is_string_char_at, uint32_t dex_pc) - : HVecMemoryOperation(arena, + : HVecMemoryOperation(allocator, packed_type, side_effects, /* number_of_inputs */ 2, @@ -999,7 +1004,7 @@ class HVecLoad FINAL : public HVecMemoryOperation { // sets mem(1) = x1, .. , mem(n) = xn. class HVecStore FINAL : public HVecMemoryOperation { public: - HVecStore(ArenaAllocator* arena, + HVecStore(ArenaAllocator* allocator, HInstruction* base, HInstruction* index, HInstruction* value, @@ -1007,7 +1012,7 @@ class HVecStore FINAL : public HVecMemoryOperation { SideEffects side_effects, size_t vector_length, uint32_t dex_pc) - : HVecMemoryOperation(arena, + : HVecMemoryOperation(allocator, packed_type, side_effects, /* number_of_inputs */ 3, diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 50b870ba8c..9bfb7a5c50 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -109,8 +109,8 @@ static constexpr const char* kPassNameSeparator = "$"; */ class CodeVectorAllocator FINAL : public CodeAllocator { public: - explicit CodeVectorAllocator(ArenaAllocator* arena) - : memory_(arena->Adapter(kArenaAllocCodeBuffer)), + explicit CodeVectorAllocator(ArenaAllocator* allocator) + : memory_(allocator->Adapter(kArenaAllocCodeBuffer)), size_(0) {} virtual uint8_t* Allocate(size_t size) { @@ -352,7 +352,7 @@ class OptimizingCompiler FINAL : public Compiler { private: // Create a 'CompiledMethod' for an optimized graph. - CompiledMethod* Emit(ArenaAllocator* arena, + CompiledMethod* Emit(ArenaAllocator* allocator, CodeVectorAllocator* code_allocator, CodeGenerator* codegen, CompilerDriver* driver, @@ -454,7 +454,7 @@ static std::string ConvertPassNameToOptimizationName(const std::string& pass_nam static HOptimization* BuildOptimization( const std::string& pass_name, - ArenaAllocator* arena, + ArenaAllocator* allocator, HGraph* graph, OptimizingCompilerStats* stats, CodeGenerator* codegen, @@ -467,78 +467,79 @@ static HOptimization* BuildOptimization( std::string opt_name = ConvertPassNameToOptimizationName(pass_name); if (opt_name == BoundsCheckElimination::kBoundsCheckEliminationPassName) { CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); - return new (arena) BoundsCheckElimination(graph, - *most_recent_side_effects, - most_recent_induction); + return new (allocator) BoundsCheckElimination(graph, + *most_recent_side_effects, + most_recent_induction); } else if (opt_name == GVNOptimization::kGlobalValueNumberingPassName) { CHECK(most_recent_side_effects != nullptr); - return new (arena) GVNOptimization(graph, *most_recent_side_effects, pass_name.c_str()); + return new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name.c_str()); } else if (opt_name == HConstantFolding::kConstantFoldingPassName) { - return new (arena) HConstantFolding(graph, pass_name.c_str()); + return new (allocator) HConstantFolding(graph, pass_name.c_str()); } else if (opt_name == HDeadCodeElimination::kDeadCodeEliminationPassName) { - return new (arena) HDeadCodeElimination(graph, stats, pass_name.c_str()); + return new (allocator) HDeadCodeElimination(graph, stats, pass_name.c_str()); } else if (opt_name == HInliner::kInlinerPassName) { size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_; - return new (arena) HInliner(graph, // outer_graph - graph, // outermost_graph - codegen, - dex_compilation_unit, // outer_compilation_unit - dex_compilation_unit, // outermost_compilation_unit - driver, - handles, - stats, - number_of_dex_registers, - /* total_number_of_instructions */ 0, - /* parent */ nullptr); + return new (allocator) HInliner(graph, // outer_graph + graph, // outermost_graph + codegen, + dex_compilation_unit, // outer_compilation_unit + dex_compilation_unit, // outermost_compilation_unit + driver, + handles, + stats, + number_of_dex_registers, + /* total_number_of_instructions */ 0, + /* parent */ nullptr); } else if (opt_name == HSharpening::kSharpeningPassName) { - return new (arena) HSharpening(graph, codegen, dex_compilation_unit, driver, handles); + return new (allocator) HSharpening(graph, codegen, dex_compilation_unit, driver, handles); } else if (opt_name == HSelectGenerator::kSelectGeneratorPassName) { - return new (arena) HSelectGenerator(graph, handles, stats); + return new (allocator) HSelectGenerator(graph, handles, stats); } else if (opt_name == HInductionVarAnalysis::kInductionPassName) { - return new (arena) HInductionVarAnalysis(graph); + return new (allocator) HInductionVarAnalysis(graph); } else if (opt_name == InstructionSimplifier::kInstructionSimplifierPassName) { - return new (arena) InstructionSimplifier(graph, codegen, driver, stats, pass_name.c_str()); + return new (allocator) InstructionSimplifier(graph, codegen, driver, stats, pass_name.c_str()); } else if (opt_name == IntrinsicsRecognizer::kIntrinsicsRecognizerPassName) { - return new (arena) IntrinsicsRecognizer(graph, stats); + return new (allocator) IntrinsicsRecognizer(graph, stats); } else if (opt_name == LICM::kLoopInvariantCodeMotionPassName) { CHECK(most_recent_side_effects != nullptr); - return new (arena) LICM(graph, *most_recent_side_effects, stats); + return new (allocator) LICM(graph, *most_recent_side_effects, stats); } else if (opt_name == LoadStoreAnalysis::kLoadStoreAnalysisPassName) { - return new (arena) LoadStoreAnalysis(graph); + return new (allocator) LoadStoreAnalysis(graph); } else if (opt_name == LoadStoreElimination::kLoadStoreEliminationPassName) { CHECK(most_recent_side_effects != nullptr); CHECK(most_recent_lsa != nullptr); - return - new (arena) LoadStoreElimination(graph, *most_recent_side_effects, *most_recent_lsa, stats); + return new (allocator) LoadStoreElimination(graph, + *most_recent_side_effects, + *most_recent_lsa, stats); } else if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) { - return new (arena) SideEffectsAnalysis(graph); + return new (allocator) SideEffectsAnalysis(graph); } else if (opt_name == HLoopOptimization::kLoopOptimizationPassName) { - return new (arena) HLoopOptimization(graph, driver, most_recent_induction, stats); + return new (allocator) HLoopOptimization(graph, driver, most_recent_induction, stats); } else if (opt_name == CHAGuardOptimization::kCHAGuardOptimizationPassName) { - return new (arena) CHAGuardOptimization(graph); + return new (allocator) CHAGuardOptimization(graph); } else if (opt_name == CodeSinking::kCodeSinkingPassName) { - return new (arena) CodeSinking(graph, stats); + return new (allocator) CodeSinking(graph, stats); } else if (opt_name == ConstructorFenceRedundancyElimination::kPassName) { - return new (arena) ConstructorFenceRedundancyElimination(graph, stats); + return new (allocator) ConstructorFenceRedundancyElimination(graph, stats); #ifdef ART_ENABLE_CODEGEN_arm } else if (opt_name == arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName) { - return new (arena) arm::InstructionSimplifierArm(graph, stats); + return new (allocator) arm::InstructionSimplifierArm(graph, stats); #endif #ifdef ART_ENABLE_CODEGEN_arm64 } else if (opt_name == arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName) { - return new (arena) arm64::InstructionSimplifierArm64(graph, stats); + return new (allocator) arm64::InstructionSimplifierArm64(graph, stats); #endif #ifdef ART_ENABLE_CODEGEN_mips } else if (opt_name == mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName) { - return new (arena) mips::PcRelativeFixups(graph, codegen, stats); + return new (allocator) mips::PcRelativeFixups(graph, codegen, stats); } else if (opt_name == mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName) { - return new (arena) mips::InstructionSimplifierMips(graph, codegen, stats); + return new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats); #endif #ifdef ART_ENABLE_CODEGEN_x86 } else if (opt_name == x86::PcRelativeFixups::kPcRelativeFixupsX86PassName) { - return new (arena) x86::PcRelativeFixups(graph, codegen, stats); + return new (allocator) x86::PcRelativeFixups(graph, codegen, stats); } else if (opt_name == x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName) { - return new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats); + return new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); #endif } return nullptr; @@ -546,7 +547,7 @@ static HOptimization* BuildOptimization( static ArenaVector<HOptimization*> BuildOptimizations( const std::vector<std::string>& pass_names, - ArenaAllocator* arena, + ArenaAllocator* allocator, HGraph* graph, OptimizingCompilerStats* stats, CodeGenerator* codegen, @@ -559,11 +560,11 @@ static ArenaVector<HOptimization*> BuildOptimizations( SideEffectsAnalysis* most_recent_side_effects = nullptr; HInductionVarAnalysis* most_recent_induction = nullptr; LoadStoreAnalysis* most_recent_lsa = nullptr; - ArenaVector<HOptimization*> ret(arena->Adapter()); + ArenaVector<HOptimization*> ret(allocator->Adapter()); for (const std::string& pass_name : pass_names) { HOptimization* opt = BuildOptimization( pass_name, - arena, + allocator, graph, stats, codegen, @@ -757,15 +758,18 @@ static void AllocateRegisters(HGraph* graph, pass_observer); PrepareForRegisterAllocation(graph, stats).Run(); } - SsaLivenessAnalysis liveness(graph, codegen); + // Use local allocator shared by SSA liveness analysis and register allocator. + // (Register allocator creates new objects in the liveness data.) + ScopedArenaAllocator local_allocator(graph->GetArenaStack()); + SsaLivenessAnalysis liveness(graph, codegen, &local_allocator); { PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer); liveness.Analyze(); } { PassScope scope(RegisterAllocator::kRegisterAllocatorPassName, pass_observer); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(graph->GetAllocator(), codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(&local_allocator, codegen, liveness, strategy); register_allocator->AllocateRegisters(); } } @@ -777,11 +781,11 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph, PassObserver* pass_observer, VariableSizedHandleScope* handles) const { OptimizingCompilerStats* stats = compilation_stats_.get(); - ArenaAllocator* arena = graph->GetAllocator(); + ArenaAllocator* allocator = graph->GetAllocator(); if (driver->GetCompilerOptions().GetPassesToRun() != nullptr) { ArenaVector<HOptimization*> optimizations = BuildOptimizations( *driver->GetCompilerOptions().GetPassesToRun(), - arena, + allocator, graph, stats, codegen, @@ -792,43 +796,45 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph, return; } - HDeadCodeElimination* dce1 = new (arena) HDeadCodeElimination( + HDeadCodeElimination* dce1 = new (allocator) HDeadCodeElimination( graph, stats, "dead_code_elimination$initial"); - HDeadCodeElimination* dce2 = new (arena) HDeadCodeElimination( + HDeadCodeElimination* dce2 = new (allocator) HDeadCodeElimination( graph, stats, "dead_code_elimination$after_inlining"); - HDeadCodeElimination* dce3 = new (arena) HDeadCodeElimination( + HDeadCodeElimination* dce3 = new (allocator) HDeadCodeElimination( graph, stats, "dead_code_elimination$final"); - HConstantFolding* fold1 = new (arena) HConstantFolding(graph, "constant_folding"); - InstructionSimplifier* simplify1 = new (arena) InstructionSimplifier( + HConstantFolding* fold1 = new (allocator) HConstantFolding(graph, "constant_folding"); + InstructionSimplifier* simplify1 = new (allocator) InstructionSimplifier( graph, codegen, driver, stats); - HSelectGenerator* select_generator = new (arena) HSelectGenerator(graph, handles, stats); - HConstantFolding* fold2 = new (arena) HConstantFolding( + HSelectGenerator* select_generator = new (allocator) HSelectGenerator(graph, handles, stats); + HConstantFolding* fold2 = new (allocator) HConstantFolding( graph, "constant_folding$after_inlining"); - HConstantFolding* fold3 = new (arena) HConstantFolding(graph, "constant_folding$after_bce"); - SideEffectsAnalysis* side_effects1 = new (arena) SideEffectsAnalysis( + HConstantFolding* fold3 = new (allocator) HConstantFolding(graph, "constant_folding$after_bce"); + SideEffectsAnalysis* side_effects1 = new (allocator) SideEffectsAnalysis( graph, "side_effects$before_gvn"); - SideEffectsAnalysis* side_effects2 = new (arena) SideEffectsAnalysis( + SideEffectsAnalysis* side_effects2 = new (allocator) SideEffectsAnalysis( graph, "side_effects$before_lse"); - GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects1); - LICM* licm = new (arena) LICM(graph, *side_effects1, stats); - HInductionVarAnalysis* induction = new (arena) HInductionVarAnalysis(graph); - BoundsCheckElimination* bce = new (arena) BoundsCheckElimination(graph, *side_effects1, induction); - HLoopOptimization* loop = new (arena) HLoopOptimization(graph, driver, induction, stats); - LoadStoreAnalysis* lsa = new (arena) LoadStoreAnalysis(graph); - LoadStoreElimination* lse = new (arena) LoadStoreElimination(graph, *side_effects2, *lsa, stats); - HSharpening* sharpening = new (arena) HSharpening( + GVNOptimization* gvn = new (allocator) GVNOptimization(graph, *side_effects1); + LICM* licm = new (allocator) LICM(graph, *side_effects1, stats); + HInductionVarAnalysis* induction = new (allocator) HInductionVarAnalysis(graph); + BoundsCheckElimination* bce = + new (allocator) BoundsCheckElimination(graph, *side_effects1, induction); + HLoopOptimization* loop = new (allocator) HLoopOptimization(graph, driver, induction, stats); + LoadStoreAnalysis* lsa = new (allocator) LoadStoreAnalysis(graph); + LoadStoreElimination* lse = + new (allocator) LoadStoreElimination(graph, *side_effects2, *lsa, stats); + HSharpening* sharpening = new (allocator) HSharpening( graph, codegen, dex_compilation_unit, driver, handles); - InstructionSimplifier* simplify2 = new (arena) InstructionSimplifier( + InstructionSimplifier* simplify2 = new (allocator) InstructionSimplifier( graph, codegen, driver, stats, "instruction_simplifier$after_inlining"); - InstructionSimplifier* simplify3 = new (arena) InstructionSimplifier( + InstructionSimplifier* simplify3 = new (allocator) InstructionSimplifier( graph, codegen, driver, stats, "instruction_simplifier$after_bce"); - InstructionSimplifier* simplify4 = new (arena) InstructionSimplifier( + InstructionSimplifier* simplify4 = new (allocator) InstructionSimplifier( graph, codegen, driver, stats, "instruction_simplifier$before_codegen"); - IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, stats); - CHAGuardOptimization* cha_guard = new (arena) CHAGuardOptimization(graph); - CodeSinking* code_sinking = new (arena) CodeSinking(graph, stats); + IntrinsicsRecognizer* intrinsics = new (allocator) IntrinsicsRecognizer(graph, stats); + CHAGuardOptimization* cha_guard = new (allocator) CHAGuardOptimization(graph); + CodeSinking* code_sinking = new (allocator) CodeSinking(graph, stats); ConstructorFenceRedundancyElimination* cfre = - new (arena) ConstructorFenceRedundancyElimination(graph, stats); + new (allocator) ConstructorFenceRedundancyElimination(graph, stats); HOptimization* optimizations1[] = { intrinsics, @@ -887,14 +893,14 @@ static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* return linker_patches; } -CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena, +CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* allocator, CodeVectorAllocator* code_allocator, CodeGenerator* codegen, CompilerDriver* compiler_driver, const DexFile::CodeItem* code_item) const { ArenaVector<linker::LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen); - ArenaVector<uint8_t> stack_map(arena->Adapter(kArenaAllocStackMaps)); - ArenaVector<uint8_t> method_info(arena->Adapter(kArenaAllocStackMaps)); + ArenaVector<uint8_t> stack_map(allocator->Adapter(kArenaAllocStackMaps)); + ArenaVector<uint8_t> method_info(allocator->Adapter(kArenaAllocStackMaps)); size_t stack_map_size = 0; size_t method_info_size = 0; codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size); diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index f31ad828eb..5632f9a453 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -48,7 +48,7 @@ namespace art { LiveInterval* BuildInterval(const size_t ranges[][2], size_t number_of_ranges, - ArenaAllocator* allocator, + ScopedArenaAllocator* allocator, int reg = -1, HInstruction* defined_by = nullptr) { LiveInterval* interval = @@ -81,15 +81,18 @@ void RemoveSuspendChecks(HGraph* graph) { class ArenaPoolAndAllocator { public: - ArenaPoolAndAllocator() : pool_(), allocator_(&pool_), arena_stack_(&pool_) { } + ArenaPoolAndAllocator() + : pool_(), allocator_(&pool_), arena_stack_(&pool_), scoped_allocator_(&arena_stack_) { } ArenaAllocator* GetAllocator() { return &allocator_; } ArenaStack* GetArenaStack() { return &arena_stack_; } + ScopedArenaAllocator* GetScopedAllocator() { return &scoped_allocator_; } private: ArenaPool pool_; ArenaAllocator allocator_; ArenaStack arena_stack_; + ScopedArenaAllocator scoped_allocator_; }; inline HGraph* CreateGraph(ArenaPoolAndAllocator* pool_and_allocator) { @@ -107,6 +110,7 @@ class OptimizingUnitTest : public CommonCompilerTest { ArenaAllocator* GetAllocator() { return pool_and_allocator_->GetAllocator(); } ArenaStack* GetArenaStack() { return pool_and_allocator_->GetArenaStack(); } + ScopedArenaAllocator* GetScopedAllocator() { return pool_and_allocator_->GetScopedAllocator(); } void ResetPoolAndAllocator() { pool_and_allocator_.reset(new ArenaPoolAndAllocator()); diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc index 5ec76b457b..fe98aa9561 100644 --- a/compiler/optimizing/prepare_for_register_allocation.cc +++ b/compiler/optimizing/prepare_for_register_allocation.cc @@ -56,12 +56,12 @@ void PrepareForRegisterAllocation::VisitBoundsCheck(HBoundsCheck* check) { // Add a fake environment for String.charAt() inline info as we want // the exception to appear as being thrown from there. ArtMethod* char_at_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); - ArenaAllocator* arena = GetGraph()->GetAllocator(); - HEnvironment* environment = new (arena) HEnvironment(arena, - /* number_of_vregs */ 0u, - char_at_method, - /* dex_pc */ dex::kDexNoIndex, - check); + ArenaAllocator* allocator = GetGraph()->GetAllocator(); + HEnvironment* environment = new (allocator) HEnvironment(allocator, + /* number_of_vregs */ 0u, + char_at_method, + /* dex_pc */ dex::kDexNoIndex, + check); check->InsertRawEnvironment(environment); } } diff --git a/compiler/optimizing/register_allocation_resolver.cc b/compiler/optimizing/register_allocation_resolver.cc index 1786aa72a1..5ed9e0243f 100644 --- a/compiler/optimizing/register_allocation_resolver.cc +++ b/compiler/optimizing/register_allocation_resolver.cc @@ -22,10 +22,9 @@ namespace art { -RegisterAllocationResolver::RegisterAllocationResolver(ArenaAllocator* allocator, - CodeGenerator* codegen, +RegisterAllocationResolver::RegisterAllocationResolver(CodeGenerator* codegen, const SsaLivenessAnalysis& liveness) - : allocator_(allocator), + : allocator_(codegen->GetGraph()->GetAllocator()), codegen_(codegen), liveness_(liveness) {} @@ -36,7 +35,7 @@ void RegisterAllocationResolver::Resolve(ArrayRef<HInstruction* const> safepoint size_t float_spill_slots, size_t double_spill_slots, size_t catch_phi_spill_slots, - const ArenaVector<LiveInterval*>& temp_intervals) { + ArrayRef<LiveInterval* const> temp_intervals) { size_t spill_slots = int_spill_slots + long_spill_slots + float_spill_slots diff --git a/compiler/optimizing/register_allocation_resolver.h b/compiler/optimizing/register_allocation_resolver.h index 4a148e0abf..278371777d 100644 --- a/compiler/optimizing/register_allocation_resolver.h +++ b/compiler/optimizing/register_allocation_resolver.h @@ -17,7 +17,6 @@ #ifndef ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATION_RESOLVER_H_ #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATION_RESOLVER_H_ -#include "base/arena_containers.h" #include "base/array_ref.h" #include "base/value_object.h" #include "data_type.h" @@ -40,9 +39,7 @@ class SsaLivenessAnalysis; */ class RegisterAllocationResolver : ValueObject { public: - RegisterAllocationResolver(ArenaAllocator* allocator, - CodeGenerator* codegen, - const SsaLivenessAnalysis& liveness); + RegisterAllocationResolver(CodeGenerator* codegen, const SsaLivenessAnalysis& liveness); void Resolve(ArrayRef<HInstruction* const> safepoints, size_t reserved_out_slots, // Includes slot(s) for the art method. @@ -51,7 +48,7 @@ class RegisterAllocationResolver : ValueObject { size_t float_spill_slots, size_t double_spill_slots, size_t catch_phi_spill_slots, - const ArenaVector<LiveInterval*>& temp_intervals); + ArrayRef<LiveInterval* const> temp_intervals); private: // Update live registers of safepoint location summary. diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index c3b33e29d7..ece9904426 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -19,6 +19,8 @@ #include <iostream> #include <sstream> +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "base/bit_vector-inl.h" #include "code_generator.h" #include "register_allocator_graph_color.h" @@ -27,22 +29,24 @@ namespace art { -RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator, +RegisterAllocator::RegisterAllocator(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& liveness) : allocator_(allocator), codegen_(codegen), liveness_(liveness) {} -RegisterAllocator* RegisterAllocator::Create(ArenaAllocator* allocator, - CodeGenerator* codegen, - const SsaLivenessAnalysis& analysis, - Strategy strategy) { +std::unique_ptr<RegisterAllocator> RegisterAllocator::Create(ScopedArenaAllocator* allocator, + CodeGenerator* codegen, + const SsaLivenessAnalysis& analysis, + Strategy strategy) { switch (strategy) { case kRegisterAllocatorLinearScan: - return new (allocator) RegisterAllocatorLinearScan(allocator, codegen, analysis); + return std::unique_ptr<RegisterAllocator>( + new (allocator) RegisterAllocatorLinearScan(allocator, codegen, analysis)); case kRegisterAllocatorGraphColor: - return new (allocator) RegisterAllocatorGraphColor(allocator, codegen, analysis); + return std::unique_ptr<RegisterAllocator>( + new (allocator) RegisterAllocatorGraphColor(allocator, codegen, analysis)); default: LOG(FATAL) << "Invalid register allocation strategy: " << strategy; UNREACHABLE(); @@ -87,18 +91,18 @@ class AllRangesIterator : public ValueObject { DISALLOW_COPY_AND_ASSIGN(AllRangesIterator); }; -bool RegisterAllocator::ValidateIntervals(const ArenaVector<LiveInterval*>& intervals, +bool RegisterAllocator::ValidateIntervals(ArrayRef<LiveInterval* const> intervals, size_t number_of_spill_slots, size_t number_of_out_slots, const CodeGenerator& codegen, - ArenaAllocator* allocator, bool processing_core_registers, bool log_fatal_on_failure) { size_t number_of_registers = processing_core_registers ? codegen.GetNumberOfCoreRegisters() : codegen.GetNumberOfFloatingPointRegisters(); - ArenaVector<ArenaBitVector*> liveness_of_values( - allocator->Adapter(kArenaAllocRegisterAllocatorValidate)); + ScopedArenaAllocator allocator(codegen.GetGraph()->GetArenaStack()); + ScopedArenaVector<ArenaBitVector*> liveness_of_values( + allocator.Adapter(kArenaAllocRegisterAllocatorValidate)); liveness_of_values.reserve(number_of_registers + number_of_spill_slots); size_t max_end = 0u; @@ -112,7 +116,8 @@ bool RegisterAllocator::ValidateIntervals(const ArenaVector<LiveInterval*>& inte // allocated will populate the associated bit vector based on its live ranges. for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) { liveness_of_values.push_back( - ArenaBitVector::Create(allocator, max_end, false, kArenaAllocRegisterAllocatorValidate)); + ArenaBitVector::Create(&allocator, max_end, false, kArenaAllocRegisterAllocatorValidate)); + liveness_of_values.back()->ClearAllBits(); } for (LiveInterval* start_interval : intervals) { diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h index 4375d6851a..eaeec3b261 100644 --- a/compiler/optimizing/register_allocator.h +++ b/compiler/optimizing/register_allocator.h @@ -18,7 +18,7 @@ #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_ #include "arch/instruction_set.h" -#include "base/arena_containers.h" +#include "base/array_ref.h" #include "base/arena_object.h" #include "base/macros.h" @@ -36,7 +36,7 @@ class SsaLivenessAnalysis; /** * Base class for any register allocator. */ -class RegisterAllocator : public ArenaObject<kArenaAllocRegisterAllocator> { +class RegisterAllocator : public DeletableArenaObject<kArenaAllocRegisterAllocator> { public: enum Strategy { kRegisterAllocatorLinearScan, @@ -45,10 +45,10 @@ class RegisterAllocator : public ArenaObject<kArenaAllocRegisterAllocator> { static constexpr Strategy kRegisterAllocatorDefault = kRegisterAllocatorLinearScan; - static RegisterAllocator* Create(ArenaAllocator* allocator, - CodeGenerator* codegen, - const SsaLivenessAnalysis& analysis, - Strategy strategy = kRegisterAllocatorDefault); + static std::unique_ptr<RegisterAllocator> Create(ScopedArenaAllocator* allocator, + CodeGenerator* codegen, + const SsaLivenessAnalysis& analysis, + Strategy strategy = kRegisterAllocatorDefault); virtual ~RegisterAllocator() = default; @@ -64,18 +64,17 @@ class RegisterAllocator : public ArenaObject<kArenaAllocRegisterAllocator> { InstructionSet instruction_set); // Verifies that live intervals do not conflict. Used by unit testing. - static bool ValidateIntervals(const ArenaVector<LiveInterval*>& intervals, + static bool ValidateIntervals(ArrayRef<LiveInterval* const> intervals, size_t number_of_spill_slots, size_t number_of_out_slots, const CodeGenerator& codegen, - ArenaAllocator* allocator, bool processing_core_registers, bool log_fatal_on_failure); static constexpr const char* kRegisterAllocatorPassName = "register"; protected: - RegisterAllocator(ArenaAllocator* allocator, + RegisterAllocator(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& analysis); @@ -88,7 +87,7 @@ class RegisterAllocator : public ArenaObject<kArenaAllocRegisterAllocator> { // to find an optimal split position. LiveInterval* SplitBetween(LiveInterval* interval, size_t from, size_t to); - ArenaAllocator* const allocator_; + ScopedArenaAllocator* allocator_; CodeGenerator* const codegen_; const SsaLivenessAnalysis& liveness_; }; diff --git a/compiler/optimizing/register_allocator_graph_color.cc b/compiler/optimizing/register_allocator_graph_color.cc index 33df607831..ad5248e982 100644 --- a/compiler/optimizing/register_allocator_graph_color.cc +++ b/compiler/optimizing/register_allocator_graph_color.cc @@ -217,13 +217,12 @@ static float ComputeSpillWeight(LiveInterval* interval, const SsaLivenessAnalysi // and thus whether it is safe to prune it from the interference graph early on. class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { public: - InterferenceNode(ArenaAllocator* allocator, - LiveInterval* interval, + InterferenceNode(LiveInterval* interval, const SsaLivenessAnalysis& liveness) : stage(NodeStage::kInitial), interval_(interval), - adjacent_nodes_(allocator->Adapter(kArenaAllocRegisterAllocator)), - coalesce_opportunities_(allocator->Adapter(kArenaAllocRegisterAllocator)), + adjacent_nodes_(nullptr), + coalesce_opportunities_(nullptr), out_degree_(interval->HasRegister() ? std::numeric_limits<size_t>::max() : 0), alias_(this), spill_weight_(ComputeSpillWeight(interval, liveness)), @@ -232,21 +231,26 @@ class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { DCHECK(!interval->IsHighInterval()) << "Pair nodes should be represented by the low interval"; } - void AddInterference(InterferenceNode* other, bool guaranteed_not_interfering_yet) { + void AddInterference(InterferenceNode* other, + bool guaranteed_not_interfering_yet, + ScopedArenaDeque<ScopedArenaVector<InterferenceNode*>>* storage) { DCHECK(!IsPrecolored()) << "To save memory, fixed nodes should not have outgoing interferences"; DCHECK_NE(this, other) << "Should not create self loops in the interference graph"; DCHECK_EQ(this, alias_) << "Should not add interferences to a node that aliases another"; DCHECK_NE(stage, NodeStage::kPruned); DCHECK_NE(other->stage, NodeStage::kPruned); + if (adjacent_nodes_ == nullptr) { + ScopedArenaVector<InterferenceNode*>::allocator_type adapter(storage->get_allocator()); + storage->emplace_back(adapter); + adjacent_nodes_ = &storage->back(); + } if (guaranteed_not_interfering_yet) { - DCHECK(std::find(adjacent_nodes_.begin(), adjacent_nodes_.end(), other) - == adjacent_nodes_.end()); - adjacent_nodes_.push_back(other); + DCHECK(!ContainsElement(GetAdjacentNodes(), other)); + adjacent_nodes_->push_back(other); out_degree_ += EdgeWeightWith(other); } else { - auto it = std::find(adjacent_nodes_.begin(), adjacent_nodes_.end(), other); - if (it == adjacent_nodes_.end()) { - adjacent_nodes_.push_back(other); + if (!ContainsElement(GetAdjacentNodes(), other)) { + adjacent_nodes_->push_back(other); out_degree_ += EdgeWeightWith(other); } } @@ -255,26 +259,29 @@ class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { void RemoveInterference(InterferenceNode* other) { DCHECK_EQ(this, alias_) << "Should not remove interferences from a coalesced node"; DCHECK_EQ(other->stage, NodeStage::kPruned) << "Should only remove interferences when pruning"; - auto it = std::find(adjacent_nodes_.begin(), adjacent_nodes_.end(), other); - if (it != adjacent_nodes_.end()) { - adjacent_nodes_.erase(it); - out_degree_ -= EdgeWeightWith(other); + if (adjacent_nodes_ != nullptr) { + auto it = std::find(adjacent_nodes_->begin(), adjacent_nodes_->end(), other); + if (it != adjacent_nodes_->end()) { + adjacent_nodes_->erase(it); + out_degree_ -= EdgeWeightWith(other); + } } } bool ContainsInterference(InterferenceNode* other) const { DCHECK(!IsPrecolored()) << "Should not query fixed nodes for interferences"; DCHECK_EQ(this, alias_) << "Should not query a coalesced node for interferences"; - auto it = std::find(adjacent_nodes_.begin(), adjacent_nodes_.end(), other); - return it != adjacent_nodes_.end(); + return ContainsElement(GetAdjacentNodes(), other); } LiveInterval* GetInterval() const { return interval_; } - const ArenaVector<InterferenceNode*>& GetAdjacentNodes() const { - return adjacent_nodes_; + ArrayRef<InterferenceNode*> GetAdjacentNodes() const { + return adjacent_nodes_ != nullptr + ? ArrayRef<InterferenceNode*>(*adjacent_nodes_) + : ArrayRef<InterferenceNode*>(); } size_t GetOutDegree() const { @@ -283,16 +290,22 @@ class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { return out_degree_; } - void AddCoalesceOpportunity(CoalesceOpportunity* opportunity) { - coalesce_opportunities_.push_back(opportunity); + void AddCoalesceOpportunity(CoalesceOpportunity* opportunity, + ScopedArenaDeque<ScopedArenaVector<CoalesceOpportunity*>>* storage) { + if (coalesce_opportunities_ == nullptr) { + ScopedArenaVector<CoalesceOpportunity*>::allocator_type adapter(storage->get_allocator()); + storage->emplace_back(adapter); + coalesce_opportunities_ = &storage->back(); + } + coalesce_opportunities_->push_back(opportunity); } void ClearCoalesceOpportunities() { - coalesce_opportunities_.clear(); + coalesce_opportunities_ = nullptr; } bool IsMoveRelated() const { - for (CoalesceOpportunity* opportunity : coalesce_opportunities_) { + for (CoalesceOpportunity* opportunity : GetCoalesceOpportunities()) { if (opportunity->stage == CoalesceStage::kWorklist || opportunity->stage == CoalesceStage::kActive) { return true; @@ -325,8 +338,10 @@ class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { return alias_; } - const ArenaVector<CoalesceOpportunity*>& GetCoalesceOpportunities() const { - return coalesce_opportunities_; + ArrayRef<CoalesceOpportunity*> GetCoalesceOpportunities() const { + return coalesce_opportunities_ != nullptr + ? ArrayRef<CoalesceOpportunity*>(*coalesce_opportunities_) + : ArrayRef<CoalesceOpportunity*>(); } float GetSpillWeight() const { @@ -361,10 +376,10 @@ class InterferenceNode : public ArenaObject<kArenaAllocRegisterAllocator> { // All nodes interfering with this one. // We use an unsorted vector as a set, since a tree or hash set is too heavy for the // set sizes that we encounter. Using a vector leads to much better performance. - ArenaVector<InterferenceNode*> adjacent_nodes_; + ScopedArenaVector<InterferenceNode*>* adjacent_nodes_; // Owned by ColoringIteration. // Interference nodes that this node should be coalesced with to reduce moves. - ArenaVector<CoalesceOpportunity*> coalesce_opportunities_; + ScopedArenaVector<CoalesceOpportunity*>* coalesce_opportunities_; // Owned by ColoringIteration. // The maximum number of colors with which this node could interfere. This could be more than // the number of adjacent nodes if this is a pair node, or if some adjacent nodes are pair nodes. @@ -416,7 +431,7 @@ static bool HasGreaterNodePriority(const InterferenceNode* lhs, class ColoringIteration { public: ColoringIteration(RegisterAllocatorGraphColor* register_allocator, - ArenaAllocator* allocator, + ScopedArenaAllocator* allocator, bool processing_core_regs, size_t num_regs) : register_allocator_(register_allocator), @@ -430,15 +445,17 @@ class ColoringIteration { freeze_worklist_(allocator->Adapter(kArenaAllocRegisterAllocator)), spill_worklist_(HasGreaterNodePriority, allocator->Adapter(kArenaAllocRegisterAllocator)), coalesce_worklist_(CoalesceOpportunity::CmpPriority, - allocator->Adapter(kArenaAllocRegisterAllocator)) {} + allocator->Adapter(kArenaAllocRegisterAllocator)), + adjacent_nodes_links_(allocator->Adapter(kArenaAllocRegisterAllocator)), + coalesce_opportunities_links_(allocator->Adapter(kArenaAllocRegisterAllocator)) {} // Use the intervals collected from instructions to construct an // interference graph mapping intervals to adjacency lists. // Also, collect synthesized safepoint nodes, used to keep // track of live intervals across safepoints. // TODO: Should build safepoints elsewhere. - void BuildInterferenceGraph(const ArenaVector<LiveInterval*>& intervals, - const ArenaVector<InterferenceNode*>& physical_nodes); + void BuildInterferenceGraph(const ScopedArenaVector<LiveInterval*>& intervals, + const ScopedArenaVector<InterferenceNode*>& physical_nodes); // Add coalesce opportunities to interference nodes. void FindCoalesceOpportunities(); @@ -456,8 +473,8 @@ class ColoringIteration { // Return prunable nodes. // The register allocator will need to access prunable nodes after coloring // in order to tell the code generator which registers have been assigned. - const ArenaVector<InterferenceNode*>& GetPrunableNodes() const { - return prunable_nodes_; + ArrayRef<InterferenceNode* const> GetPrunableNodes() const { + return ArrayRef<InterferenceNode* const>(prunable_nodes_); } private: @@ -503,38 +520,46 @@ class ColoringIteration { // needed to split intervals and assign spill slots. RegisterAllocatorGraphColor* register_allocator_; - // An arena allocator used for a single graph coloring attempt. - ArenaAllocator* allocator_; + // A scoped arena allocator used for a single graph coloring attempt. + ScopedArenaAllocator* allocator_; const bool processing_core_regs_; const size_t num_regs_; // A map from live intervals to interference nodes. - ArenaHashMap<LiveInterval*, InterferenceNode*> interval_node_map_; + ScopedArenaHashMap<LiveInterval*, InterferenceNode*> interval_node_map_; // Uncolored nodes that should be pruned from the interference graph. - ArenaVector<InterferenceNode*> prunable_nodes_; + ScopedArenaVector<InterferenceNode*> prunable_nodes_; // A stack of nodes pruned from the interference graph, waiting to be pruned. - ArenaStdStack<InterferenceNode*> pruned_nodes_; + ScopedArenaStdStack<InterferenceNode*> pruned_nodes_; // A queue containing low degree, non-move-related nodes that can pruned immediately. - ArenaDeque<InterferenceNode*> simplify_worklist_; + ScopedArenaDeque<InterferenceNode*> simplify_worklist_; // A queue containing low degree, move-related nodes. - ArenaDeque<InterferenceNode*> freeze_worklist_; + ScopedArenaDeque<InterferenceNode*> freeze_worklist_; // A queue containing high degree nodes. // If we have to prune from the spill worklist, we cannot guarantee // the pruned node a color, so we order the worklist by priority. - ArenaPriorityQueue<InterferenceNode*, decltype(&HasGreaterNodePriority)> spill_worklist_; + ScopedArenaPriorityQueue<InterferenceNode*, decltype(&HasGreaterNodePriority)> spill_worklist_; // A queue containing coalesce opportunities. // We order the coalesce worklist by priority, since some coalesce opportunities (e.g., those // inside of loops) are more important than others. - ArenaPriorityQueue<CoalesceOpportunity*, - decltype(&CoalesceOpportunity::CmpPriority)> coalesce_worklist_; + ScopedArenaPriorityQueue<CoalesceOpportunity*, + decltype(&CoalesceOpportunity::CmpPriority)> coalesce_worklist_; + + // Storage for links to adjacent nodes for interference nodes. + // Using std::deque so that elements do not move when adding new ones. + ScopedArenaDeque<ScopedArenaVector<InterferenceNode*>> adjacent_nodes_links_; + + // Storage for links to coalesce opportunities for interference nodes. + // Using std::deque so that elements do not move when adding new ones. + ScopedArenaDeque<ScopedArenaVector<CoalesceOpportunity*>> coalesce_opportunities_links_; DISALLOW_COPY_AND_ASSIGN(ColoringIteration); }; @@ -547,7 +572,7 @@ static size_t ComputeReservedArtMethodSlots(const CodeGenerator& codegen) { return static_cast<size_t>(InstructionSetPointerSize(codegen.GetInstructionSet())) / kVRegSize; } -RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocator, +RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& liveness, bool iterative_move_coalescing) @@ -574,8 +599,7 @@ RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocat physical_core_nodes_.resize(codegen_->GetNumberOfCoreRegisters(), nullptr); for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) { LiveInterval* interval = LiveInterval::MakeFixedInterval(allocator_, i, DataType::Type::kInt32); - physical_core_nodes_[i] = - new (allocator_) InterferenceNode(allocator_, interval, liveness); + physical_core_nodes_[i] = new (allocator_) InterferenceNode(interval, liveness); physical_core_nodes_[i]->stage = NodeStage::kPrecolored; core_intervals_.push_back(interval); if (codegen_->IsBlockedCoreRegister(i)) { @@ -587,8 +611,7 @@ RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocat for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) { LiveInterval* interval = LiveInterval::MakeFixedInterval(allocator_, i, DataType::Type::kFloat32); - physical_fp_nodes_[i] = - new (allocator_) InterferenceNode(allocator_, interval, liveness); + physical_fp_nodes_[i] = new (allocator_) InterferenceNode(interval, liveness); physical_fp_nodes_[i]->stage = NodeStage::kPrecolored; fp_intervals_.push_back(interval); if (codegen_->IsBlockedFloatingPointRegister(i)) { @@ -597,12 +620,14 @@ RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocat } } +RegisterAllocatorGraphColor::~RegisterAllocatorGraphColor() {} + void RegisterAllocatorGraphColor::AllocateRegisters() { // (1) Collect and prepare live intervals. ProcessInstructions(); for (bool processing_core_regs : {true, false}) { - ArenaVector<LiveInterval*>& intervals = processing_core_regs + ScopedArenaVector<LiveInterval*>& intervals = processing_core_regs ? core_intervals_ : fp_intervals_; size_t num_registers = processing_core_regs @@ -619,17 +644,15 @@ void RegisterAllocatorGraphColor::AllocateRegisters() { << "should be prioritized over long ones, because they cannot be split further.)"; // Many data structures are cleared between graph coloring attempts, so we reduce - // total memory usage by using a new arena allocator for each attempt. - ArenaAllocator coloring_attempt_allocator(allocator_->GetArenaPool()); + // total memory usage by using a new scoped arena allocator for each attempt. + ScopedArenaAllocator coloring_attempt_allocator(allocator_->GetArenaStack()); ColoringIteration iteration(this, &coloring_attempt_allocator, processing_core_regs, num_registers); - // (2) Build the interference graph. Also gather safepoints. - ArenaVector<InterferenceNode*> safepoints( - coloring_attempt_allocator.Adapter(kArenaAllocRegisterAllocator)); - ArenaVector<InterferenceNode*>& physical_nodes = processing_core_regs + // (2) Build the interference graph. + ScopedArenaVector<InterferenceNode*>& physical_nodes = processing_core_regs ? physical_core_nodes_ : physical_fp_nodes_; iteration.BuildInterferenceGraph(intervals, physical_nodes); @@ -691,7 +714,7 @@ void RegisterAllocatorGraphColor::AllocateRegisters() { } // for processing_core_instructions // (6) Resolve locations and deconstruct SSA form. - RegisterAllocationResolver(allocator_, codegen_, liveness_) + RegisterAllocationResolver(codegen_, liveness_) .Resolve(ArrayRef<HInstruction* const>(safepoints_), reserved_art_method_slots_ + reserved_out_slots_, num_int_spill_slots_, @@ -699,7 +722,7 @@ void RegisterAllocatorGraphColor::AllocateRegisters() { num_float_spill_slots_, num_double_spill_slots_, catch_phi_spill_slot_counter_, - temp_intervals_); + ArrayRef<LiveInterval* const>(temp_intervals_)); if (kIsDebugBuild) { Validate(/*log_fatal_on_failure*/ true); @@ -708,8 +731,9 @@ void RegisterAllocatorGraphColor::AllocateRegisters() { bool RegisterAllocatorGraphColor::Validate(bool log_fatal_on_failure) { for (bool processing_core_regs : {true, false}) { - ArenaVector<LiveInterval*> intervals( - allocator_->Adapter(kArenaAllocRegisterAllocatorValidate)); + ScopedArenaAllocator allocator(allocator_->GetArenaStack()); + ScopedArenaVector<LiveInterval*> intervals( + allocator.Adapter(kArenaAllocRegisterAllocatorValidate)); for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) { HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); LiveInterval* interval = instruction->GetLiveInterval(); @@ -718,7 +742,7 @@ bool RegisterAllocatorGraphColor::Validate(bool log_fatal_on_failure) { } } - ArenaVector<InterferenceNode*>& physical_nodes = processing_core_regs + ScopedArenaVector<InterferenceNode*>& physical_nodes = processing_core_regs ? physical_core_nodes_ : physical_fp_nodes_; for (InterferenceNode* fixed : physical_nodes) { @@ -742,11 +766,10 @@ bool RegisterAllocatorGraphColor::Validate(bool log_fatal_on_failure) { + num_float_spill_slots_ + num_double_spill_slots_ + catch_phi_spill_slot_counter_; - bool ok = ValidateIntervals(intervals, + bool ok = ValidateIntervals(ArrayRef<LiveInterval* const>(intervals), spill_slots, reserved_art_method_slots_ + reserved_out_slots_, *codegen_, - allocator_, processing_core_regs, log_fatal_on_failure); if (!ok) { @@ -825,7 +848,7 @@ void RegisterAllocatorGraphColor::ProcessInstruction(HInstruction* instruction) CheckForFixedOutput(instruction); AllocateSpillSlotForCatchPhi(instruction); - ArenaVector<LiveInterval*>& intervals = IsCoreInterval(interval) + ScopedArenaVector<LiveInterval*>& intervals = IsCoreInterval(interval) ? core_intervals_ : fp_intervals_; if (interval->HasSpillSlot() || instruction->IsConstant()) { @@ -1075,11 +1098,12 @@ void ColoringIteration::AddPotentialInterference(InterferenceNode* from, } else if (to->IsPrecolored()) { // It is important that only a single node represents a given fixed register in the // interference graph. We retrieve that node here. - const ArenaVector<InterferenceNode*>& physical_nodes = to->GetInterval()->IsFloatingPoint() - ? register_allocator_->physical_fp_nodes_ - : register_allocator_->physical_core_nodes_; + const ScopedArenaVector<InterferenceNode*>& physical_nodes = + to->GetInterval()->IsFloatingPoint() ? register_allocator_->physical_fp_nodes_ + : register_allocator_->physical_core_nodes_; InterferenceNode* physical_node = physical_nodes[to->GetInterval()->GetRegister()]; - from->AddInterference(physical_node, /*guaranteed_not_interfering_yet*/ false); + from->AddInterference( + physical_node, /*guaranteed_not_interfering_yet*/ false, &adjacent_nodes_links_); DCHECK_EQ(to->GetInterval()->GetRegister(), physical_node->GetInterval()->GetRegister()); DCHECK_EQ(to->GetAlias(), physical_node) << "Fixed nodes should alias the canonical fixed node"; @@ -1097,11 +1121,12 @@ void ColoringIteration::AddPotentialInterference(InterferenceNode* from, physical_nodes[to->GetInterval()->GetHighInterval()->GetRegister()]; DCHECK_EQ(to->GetInterval()->GetHighInterval()->GetRegister(), high_node->GetInterval()->GetRegister()); - from->AddInterference(high_node, /*guaranteed_not_interfering_yet*/ false); + from->AddInterference( + high_node, /*guaranteed_not_interfering_yet*/ false, &adjacent_nodes_links_); } } else { // Standard interference between two uncolored nodes. - from->AddInterference(to, guaranteed_not_interfering_yet); + from->AddInterference(to, guaranteed_not_interfering_yet, &adjacent_nodes_links_); } if (both_directions) { @@ -1156,8 +1181,8 @@ static bool CheckInputOutputCanOverlap(InterferenceNode* in_node, InterferenceNo } void ColoringIteration::BuildInterferenceGraph( - const ArenaVector<LiveInterval*>& intervals, - const ArenaVector<InterferenceNode*>& physical_nodes) { + const ScopedArenaVector<LiveInterval*>& intervals, + const ScopedArenaVector<InterferenceNode*>& physical_nodes) { DCHECK(interval_node_map_.Empty() && prunable_nodes_.empty()); // Build the interference graph efficiently by ordering range endpoints // by position and doing a linear sweep to find interferences. (That is, we @@ -1171,7 +1196,7 @@ void ColoringIteration::BuildInterferenceGraph( // // For simplicity, we create a tuple for each endpoint, and then sort the tuples. // Tuple contents: (position, is_range_beginning, node). - ArenaVector<std::tuple<size_t, bool, InterferenceNode*>> range_endpoints( + ScopedArenaVector<std::tuple<size_t, bool, InterferenceNode*>> range_endpoints( allocator_->Adapter(kArenaAllocRegisterAllocator)); // We reserve plenty of space to avoid excessive copying. @@ -1181,8 +1206,8 @@ void ColoringIteration::BuildInterferenceGraph( for (LiveInterval* sibling = parent; sibling != nullptr; sibling = sibling->GetNextSibling()) { LiveRange* range = sibling->GetFirstRange(); if (range != nullptr) { - InterferenceNode* node = new (allocator_) InterferenceNode( - allocator_, sibling, register_allocator_->liveness_); + InterferenceNode* node = + new (allocator_) InterferenceNode(sibling, register_allocator_->liveness_); interval_node_map_.Insert(std::make_pair(sibling, node)); if (sibling->HasRegister()) { @@ -1217,8 +1242,7 @@ void ColoringIteration::BuildInterferenceGraph( }); // Nodes live at the current position in the linear sweep. - ArenaVector<InterferenceNode*> live( - allocator_->Adapter(kArenaAllocRegisterAllocator)); + ScopedArenaVector<InterferenceNode*> live(allocator_->Adapter(kArenaAllocRegisterAllocator)); // Linear sweep. When we encounter the beginning of a range, we add the corresponding node to the // live set. When we encounter the end of a range, we remove the corresponding node @@ -1261,8 +1285,8 @@ void ColoringIteration::CreateCoalesceOpportunity(InterferenceNode* a, << "Nodes of different memory widths should never be coalesced"; CoalesceOpportunity* opportunity = new (allocator_) CoalesceOpportunity(a, b, kind, position, register_allocator_->liveness_); - a->AddCoalesceOpportunity(opportunity); - b->AddCoalesceOpportunity(opportunity); + a->AddCoalesceOpportunity(opportunity, &coalesce_opportunities_links_); + b->AddCoalesceOpportunity(opportunity, &coalesce_opportunities_links_); coalesce_worklist_.push(opportunity); } @@ -1332,7 +1356,7 @@ void ColoringIteration::FindCoalesceOpportunities() { // Coalesce phi inputs with the corresponding output. HInstruction* defined_by = interval->GetDefinedBy(); if (defined_by != nullptr && defined_by->IsPhi()) { - const ArenaVector<HBasicBlock*>& predecessors = defined_by->GetBlock()->GetPredecessors(); + ArrayRef<HBasicBlock* const> predecessors(defined_by->GetBlock()->GetPredecessors()); HInputsRef inputs = defined_by->GetInputs(); for (size_t i = 0, e = inputs.size(); i < e; ++i) { @@ -1675,7 +1699,7 @@ void ColoringIteration::Combine(InterferenceNode* from, // Add coalesce opportunities. for (CoalesceOpportunity* opportunity : from->GetCoalesceOpportunities()) { if (opportunity->stage != CoalesceStage::kDefunct) { - into->AddCoalesceOpportunity(opportunity); + into->AddCoalesceOpportunity(opportunity, &coalesce_opportunities_links_); } } EnableCoalesceOpportunities(from); @@ -1729,7 +1753,7 @@ void ColoringIteration::Coalesce(CoalesceOpportunity* opportunity) { // Build a mask with a bit set for each register assigned to some // interval in `intervals`. template <typename Container> -static std::bitset<kMaxNumRegs> BuildConflictMask(Container& intervals) { +static std::bitset<kMaxNumRegs> BuildConflictMask(const Container& intervals) { std::bitset<kMaxNumRegs> conflict_mask; for (InterferenceNode* adjacent : intervals) { LiveInterval* conflicting = adjacent->GetInterval(); @@ -1765,7 +1789,7 @@ static size_t FindFirstZeroInConflictMask(std::bitset<kMaxNumRegs> conflict_mask bool ColoringIteration::ColorInterferenceGraph() { DCHECK_LE(num_regs_, kMaxNumRegs) << "kMaxNumRegs is too small"; - ArenaVector<LiveInterval*> colored_intervals( + ScopedArenaVector<LiveInterval*> colored_intervals( allocator_->Adapter(kArenaAllocRegisterAllocator)); bool successful = true; @@ -1888,16 +1912,18 @@ bool ColoringIteration::ColorInterferenceGraph() { return successful; } -void RegisterAllocatorGraphColor::AllocateSpillSlots(const ArenaVector<InterferenceNode*>& nodes) { +void RegisterAllocatorGraphColor::AllocateSpillSlots(ArrayRef<InterferenceNode* const> nodes) { // The register allocation resolver will organize the stack based on value type, // so we assign stack slots for each value type separately. - ArenaVector<LiveInterval*> double_intervals(allocator_->Adapter(kArenaAllocRegisterAllocator)); - ArenaVector<LiveInterval*> long_intervals(allocator_->Adapter(kArenaAllocRegisterAllocator)); - ArenaVector<LiveInterval*> float_intervals(allocator_->Adapter(kArenaAllocRegisterAllocator)); - ArenaVector<LiveInterval*> int_intervals(allocator_->Adapter(kArenaAllocRegisterAllocator)); + ScopedArenaAllocator allocator(allocator_->GetArenaStack()); + ScopedArenaAllocatorAdapter<void> adapter = allocator.Adapter(kArenaAllocRegisterAllocator); + ScopedArenaVector<LiveInterval*> double_intervals(adapter); + ScopedArenaVector<LiveInterval*> long_intervals(adapter); + ScopedArenaVector<LiveInterval*> float_intervals(adapter); + ScopedArenaVector<LiveInterval*> int_intervals(adapter); // The set of parent intervals already handled. - ArenaSet<LiveInterval*> seen(allocator_->Adapter(kArenaAllocRegisterAllocator)); + ScopedArenaSet<LiveInterval*> seen(adapter); // Find nodes that need spill slots. for (InterferenceNode* node : nodes) { @@ -1954,23 +1980,24 @@ void RegisterAllocatorGraphColor::AllocateSpillSlots(const ArenaVector<Interfere } // Color spill slots for each value type. - ColorSpillSlots(&double_intervals, &num_double_spill_slots_); - ColorSpillSlots(&long_intervals, &num_long_spill_slots_); - ColorSpillSlots(&float_intervals, &num_float_spill_slots_); - ColorSpillSlots(&int_intervals, &num_int_spill_slots_); + ColorSpillSlots(ArrayRef<LiveInterval* const>(double_intervals), &num_double_spill_slots_); + ColorSpillSlots(ArrayRef<LiveInterval* const>(long_intervals), &num_long_spill_slots_); + ColorSpillSlots(ArrayRef<LiveInterval* const>(float_intervals), &num_float_spill_slots_); + ColorSpillSlots(ArrayRef<LiveInterval* const>(int_intervals), &num_int_spill_slots_); } -void RegisterAllocatorGraphColor::ColorSpillSlots(ArenaVector<LiveInterval*>* intervals, - size_t* num_stack_slots_used) { +void RegisterAllocatorGraphColor::ColorSpillSlots(ArrayRef<LiveInterval* const> intervals, + /* out */ size_t* num_stack_slots_used) { // We cannot use the original interference graph here because spill slots are assigned to // all of the siblings of an interval, whereas an interference node represents only a single // sibling. So, we assign spill slots linear-scan-style by sorting all the interval endpoints // by position, and assigning the lowest spill slot available when we encounter an interval // beginning. We ignore lifetime holes for simplicity. - ArenaVector<std::tuple<size_t, bool, LiveInterval*>> interval_endpoints( - allocator_->Adapter(kArenaAllocRegisterAllocator)); + ScopedArenaAllocator allocator(allocator_->GetArenaStack()); + ScopedArenaVector<std::tuple<size_t, bool, LiveInterval*>> interval_endpoints( + allocator.Adapter(kArenaAllocRegisterAllocator)); - for (LiveInterval* parent_interval : *intervals) { + for (LiveInterval* parent_interval : intervals) { DCHECK(parent_interval->IsParent()); DCHECK(!parent_interval->HasSpillSlot()); size_t start = parent_interval->GetStart(); @@ -1990,7 +2017,7 @@ void RegisterAllocatorGraphColor::ColorSpillSlots(ArenaVector<LiveInterval*>* in < std::tie(std::get<0>(rhs), std::get<1>(rhs)); }); - ArenaBitVector taken(allocator_, 0, true); + ArenaBitVector taken(&allocator, 0, true, kArenaAllocRegisterAllocator); for (auto it = interval_endpoints.begin(), end = interval_endpoints.end(); it != end; ++it) { // Extract information from the current tuple. LiveInterval* parent_interval; diff --git a/compiler/optimizing/register_allocator_graph_color.h b/compiler/optimizing/register_allocator_graph_color.h index 3f6d674905..3072c92e0f 100644 --- a/compiler/optimizing/register_allocator_graph_color.h +++ b/compiler/optimizing/register_allocator_graph_color.h @@ -18,9 +18,10 @@ #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_GRAPH_COLOR_H_ #include "arch/instruction_set.h" -#include "base/arena_containers.h" #include "base/arena_object.h" +#include "base/array_ref.h" #include "base/macros.h" +#include "base/scoped_arena_containers.h" #include "register_allocator.h" namespace art { @@ -85,11 +86,11 @@ enum class CoalesceKind; */ class RegisterAllocatorGraphColor : public RegisterAllocator { public: - RegisterAllocatorGraphColor(ArenaAllocator* allocator, + RegisterAllocatorGraphColor(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& analysis, bool iterative_move_coalescing = true); - ~RegisterAllocatorGraphColor() OVERRIDE {} + ~RegisterAllocatorGraphColor() OVERRIDE; void AllocateRegisters() OVERRIDE; @@ -141,11 +142,10 @@ class RegisterAllocatorGraphColor : public RegisterAllocator { // Assigns stack slots to a list of intervals, ensuring that interfering intervals are not // assigned the same stack slot. - void ColorSpillSlots(ArenaVector<LiveInterval*>* nodes, - size_t* num_stack_slots_used); + void ColorSpillSlots(ArrayRef<LiveInterval* const> nodes, /* out */ size_t* num_stack_slots_used); // Provide stack slots to nodes that need them. - void AllocateSpillSlots(const ArenaVector<InterferenceNode*>& nodes); + void AllocateSpillSlots(ArrayRef<InterferenceNode* const> nodes); // Whether iterative move coalescing should be performed. Iterative move coalescing // improves code quality, but increases compile time. @@ -154,19 +154,19 @@ class RegisterAllocatorGraphColor : public RegisterAllocator { // Live intervals, split by kind (core and floating point). // These should not contain high intervals, as those are represented by // the corresponding low interval throughout register allocation. - ArenaVector<LiveInterval*> core_intervals_; - ArenaVector<LiveInterval*> fp_intervals_; + ScopedArenaVector<LiveInterval*> core_intervals_; + ScopedArenaVector<LiveInterval*> fp_intervals_; // Intervals for temporaries, saved for special handling in the resolution phase. - ArenaVector<LiveInterval*> temp_intervals_; + ScopedArenaVector<LiveInterval*> temp_intervals_; // Safepoints, saved for special handling while processing instructions. - ArenaVector<HInstruction*> safepoints_; + ScopedArenaVector<HInstruction*> safepoints_; // Interference nodes representing specific registers. These are "pre-colored" nodes // in the interference graph. - ArenaVector<InterferenceNode*> physical_core_nodes_; - ArenaVector<InterferenceNode*> physical_fp_nodes_; + ScopedArenaVector<InterferenceNode*> physical_core_nodes_; + ScopedArenaVector<InterferenceNode*> physical_fp_nodes_; // Allocated stack slot counters. size_t num_int_spill_slots_; diff --git a/compiler/optimizing/register_allocator_linear_scan.cc b/compiler/optimizing/register_allocator_linear_scan.cc index 9803a7b650..cfe63bd758 100644 --- a/compiler/optimizing/register_allocator_linear_scan.cc +++ b/compiler/optimizing/register_allocator_linear_scan.cc @@ -40,7 +40,7 @@ static bool IsLowOfUnalignedPairInterval(LiveInterval* low) { return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister(); } -RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ArenaAllocator* allocator, +RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& liveness) : RegisterAllocator(allocator, codegen, liveness), @@ -81,6 +81,8 @@ RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ArenaAllocator* allocat reserved_out_slots_ = ptr_size / kVRegSize + codegen->GetGraph()->GetMaximumNumberOfOutVRegs(); } +RegisterAllocatorLinearScan::~RegisterAllocatorLinearScan() {} + static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) { if (interval == nullptr) return false; bool is_core_register = (interval->GetType() != DataType::Type::kFloat64) @@ -90,7 +92,7 @@ static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval void RegisterAllocatorLinearScan::AllocateRegisters() { AllocateRegistersInternal(); - RegisterAllocationResolver(allocator_, codegen_, liveness_) + RegisterAllocationResolver(codegen_, liveness_) .Resolve(ArrayRef<HInstruction* const>(safepoints_), reserved_out_slots_, int_spill_slots_.size(), @@ -98,7 +100,7 @@ void RegisterAllocatorLinearScan::AllocateRegisters() { float_spill_slots_.size(), double_spill_slots_.size(), catch_phi_spill_slots_, - temp_intervals_); + ArrayRef<LiveInterval* const>(temp_intervals_)); if (kIsDebugBuild) { processing_core_registers_ = true; @@ -298,7 +300,7 @@ void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) LiveInterval* current = instruction->GetLiveInterval(); if (current == nullptr) return; - ArenaVector<LiveInterval*>& unhandled = core_register + ScopedArenaVector<LiveInterval*>& unhandled = core_register ? unhandled_core_intervals_ : unhandled_fp_intervals_; @@ -425,7 +427,9 @@ class AllRangesIterator : public ValueObject { bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) const { // To simplify unit testing, we eagerly create the array of intervals, and // call the helper method. - ArenaVector<LiveInterval*> intervals(allocator_->Adapter(kArenaAllocRegisterAllocatorValidate)); + ScopedArenaAllocator allocator(allocator_->GetArenaStack()); + ScopedArenaVector<LiveInterval*> intervals( + allocator.Adapter(kArenaAllocRegisterAllocatorValidate)); for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) { HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) { @@ -433,7 +437,7 @@ bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) co } } - const ArenaVector<LiveInterval*>* physical_register_intervals = processing_core_registers_ + const ScopedArenaVector<LiveInterval*>* physical_register_intervals = processing_core_registers_ ? &physical_core_register_intervals_ : &physical_fp_register_intervals_; for (LiveInterval* fixed : *physical_register_intervals) { @@ -448,8 +452,12 @@ bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) co } } - return ValidateIntervals(intervals, GetNumberOfSpillSlots(), reserved_out_slots_, *codegen_, - allocator_, processing_core_registers_, log_fatal_on_failure); + return ValidateIntervals(ArrayRef<LiveInterval* const>(intervals), + GetNumberOfSpillSlots(), + reserved_out_slots_, + *codegen_, + processing_core_registers_, + log_fatal_on_failure); } void RegisterAllocatorLinearScan::DumpInterval(std::ostream& stream, LiveInterval* interval) const { @@ -813,7 +821,7 @@ int RegisterAllocatorLinearScan::FindAvailableRegister(size_t* next_use, LiveInt // Remove interval and its other half if any. Return iterator to the following element. static ArenaVector<LiveInterval*>::iterator RemoveIntervalAndPotentialOtherHalf( - ArenaVector<LiveInterval*>* intervals, ArenaVector<LiveInterval*>::iterator pos) { + ScopedArenaVector<LiveInterval*>* intervals, ScopedArenaVector<LiveInterval*>::iterator pos) { DCHECK(intervals->begin() <= pos && pos < intervals->end()); LiveInterval* interval = *pos; if (interval->IsLowInterval()) { @@ -1044,7 +1052,8 @@ bool RegisterAllocatorLinearScan::AllocateBlockedReg(LiveInterval* current) { } } -void RegisterAllocatorLinearScan::AddSorted(ArenaVector<LiveInterval*>* array, LiveInterval* interval) { +void RegisterAllocatorLinearScan::AddSorted(ScopedArenaVector<LiveInterval*>* array, + LiveInterval* interval) { DCHECK(!interval->IsFixed() && !interval->HasSpillSlot()); size_t insert_at = 0; for (size_t i = array->size(); i > 0; --i) { @@ -1102,7 +1111,7 @@ void RegisterAllocatorLinearScan::AllocateSpillSlotFor(LiveInterval* interval) { return; } - ArenaVector<size_t>* spill_slots = nullptr; + ScopedArenaVector<size_t>* spill_slots = nullptr; switch (interval->GetType()) { case DataType::Type::kFloat64: spill_slots = &double_spill_slots_; diff --git a/compiler/optimizing/register_allocator_linear_scan.h b/compiler/optimizing/register_allocator_linear_scan.h index 9c650a44d2..36788b7c3c 100644 --- a/compiler/optimizing/register_allocator_linear_scan.h +++ b/compiler/optimizing/register_allocator_linear_scan.h @@ -18,7 +18,7 @@ #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_LINEAR_SCAN_H_ #include "arch/instruction_set.h" -#include "base/arena_containers.h" +#include "base/scoped_arena_containers.h" #include "base/macros.h" #include "register_allocator.h" @@ -39,10 +39,10 @@ class SsaLivenessAnalysis; */ class RegisterAllocatorLinearScan : public RegisterAllocator { public: - RegisterAllocatorLinearScan(ArenaAllocator* allocator, + RegisterAllocatorLinearScan(ScopedArenaAllocator* allocator, CodeGenerator* codegen, const SsaLivenessAnalysis& analysis); - ~RegisterAllocatorLinearScan() OVERRIDE {} + ~RegisterAllocatorLinearScan() OVERRIDE; void AllocateRegisters() OVERRIDE; @@ -70,7 +70,7 @@ class RegisterAllocatorLinearScan : public RegisterAllocator { bool AllocateBlockedReg(LiveInterval* interval); // Add `interval` in the given sorted list. - static void AddSorted(ArenaVector<LiveInterval*>* array, LiveInterval* interval); + static void AddSorted(ScopedArenaVector<LiveInterval*>* array, LiveInterval* interval); // Returns whether `reg` is blocked by the code generator. bool IsBlocked(int reg) const; @@ -107,43 +107,43 @@ class RegisterAllocatorLinearScan : public RegisterAllocator { // List of intervals for core registers that must be processed, ordered by start // position. Last entry is the interval that has the lowest start position. // This list is initially populated before doing the linear scan. - ArenaVector<LiveInterval*> unhandled_core_intervals_; + ScopedArenaVector<LiveInterval*> unhandled_core_intervals_; // List of intervals for floating-point registers. Same comments as above. - ArenaVector<LiveInterval*> unhandled_fp_intervals_; + ScopedArenaVector<LiveInterval*> unhandled_fp_intervals_; // Currently processed list of unhandled intervals. Either `unhandled_core_intervals_` // or `unhandled_fp_intervals_`. - ArenaVector<LiveInterval*>* unhandled_; + ScopedArenaVector<LiveInterval*>* unhandled_; // List of intervals that have been processed. - ArenaVector<LiveInterval*> handled_; + ScopedArenaVector<LiveInterval*> handled_; // List of intervals that are currently active when processing a new live interval. // That is, they have a live range that spans the start of the new interval. - ArenaVector<LiveInterval*> active_; + ScopedArenaVector<LiveInterval*> active_; // List of intervals that are currently inactive when processing a new live interval. // That is, they have a lifetime hole that spans the start of the new interval. - ArenaVector<LiveInterval*> inactive_; + ScopedArenaVector<LiveInterval*> inactive_; // Fixed intervals for physical registers. Such intervals cover the positions // where an instruction requires a specific register. - ArenaVector<LiveInterval*> physical_core_register_intervals_; - ArenaVector<LiveInterval*> physical_fp_register_intervals_; + ScopedArenaVector<LiveInterval*> physical_core_register_intervals_; + ScopedArenaVector<LiveInterval*> physical_fp_register_intervals_; // Intervals for temporaries. Such intervals cover the positions // where an instruction requires a temporary. - ArenaVector<LiveInterval*> temp_intervals_; + ScopedArenaVector<LiveInterval*> temp_intervals_; // The spill slots allocated for live intervals. We ensure spill slots // are typed to avoid (1) doing moves and swaps between two different kinds // of registers, and (2) swapping between a single stack slot and a double // stack slot. This simplifies the parallel move resolver. - ArenaVector<size_t> int_spill_slots_; - ArenaVector<size_t> long_spill_slots_; - ArenaVector<size_t> float_spill_slots_; - ArenaVector<size_t> double_spill_slots_; + ScopedArenaVector<size_t> int_spill_slots_; + ScopedArenaVector<size_t> long_spill_slots_; + ScopedArenaVector<size_t> float_spill_slots_; + ScopedArenaVector<size_t> double_spill_slots_; // Spill slots allocated to catch phis. This category is special-cased because // (1) slots are allocated prior to linear scan and in reverse linear order, @@ -151,7 +151,7 @@ class RegisterAllocatorLinearScan : public RegisterAllocator { size_t catch_phi_spill_slots_; // Instructions that need a safepoint. - ArenaVector<HInstruction*> safepoints_; + ScopedArenaVector<HInstruction*> safepoints_; // True if processing core registers. False if processing floating // point registers. diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index 9c8b1df1f8..69ed8c7fcc 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -58,6 +58,16 @@ class RegisterAllocatorTest : public OptimizingUnitTest { HGraph* BuildTwoSubs(HInstruction** first_sub, HInstruction** second_sub); HGraph* BuildDiv(HInstruction** div); void ExpectedExactInRegisterAndSameOutputHint(Strategy strategy); + + bool ValidateIntervals(const ScopedArenaVector<LiveInterval*>& intervals, + const CodeGenerator& codegen) { + return RegisterAllocator::ValidateIntervals(ArrayRef<LiveInterval* const>(intervals), + /* number_of_spill_slots */ 0u, + /* number_of_out_slots */ 0u, + codegen, + /* processing_core_registers */ true, + /* log_fatal_on_failure */ false); + } }; // This macro should include all register allocation strategies that should be tested. @@ -74,10 +84,10 @@ bool RegisterAllocatorTest::Check(const uint16_t* data, Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); return register_allocator->Validate(false); } @@ -91,85 +101,74 @@ TEST_F(RegisterAllocatorTest, ValidateIntervals) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - ArenaVector<LiveInterval*> intervals(GetAllocator()->Adapter()); + ScopedArenaVector<LiveInterval*> intervals(GetScopedAllocator()->Adapter()); // Test with two intervals of the same range. { static constexpr size_t ranges[][2] = {{0, 42}}; - intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetAllocator(), 0)); - intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetAllocator(), 1)); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetScopedAllocator(), 0)); + intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetScopedAllocator(), 1)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[1]->SetRegister(0); - ASSERT_FALSE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_FALSE(ValidateIntervals(intervals, codegen)); intervals.clear(); } // Test with two non-intersecting intervals. { static constexpr size_t ranges1[][2] = {{0, 42}}; - intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetAllocator(), 0)); + intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0)); static constexpr size_t ranges2[][2] = {{42, 43}}; - intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetAllocator(), 1)); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[1]->SetRegister(0); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals.clear(); } // Test with two non-intersecting intervals, with one with a lifetime hole. { static constexpr size_t ranges1[][2] = {{0, 42}, {45, 48}}; - intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetAllocator(), 0)); + intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0)); static constexpr size_t ranges2[][2] = {{42, 43}}; - intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetAllocator(), 1)); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[1]->SetRegister(0); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals.clear(); } // Test with intersecting intervals. { static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}}; - intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetAllocator(), 0)); + intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0)); static constexpr size_t ranges2[][2] = {{42, 47}}; - intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetAllocator(), 1)); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[1]->SetRegister(0); - ASSERT_FALSE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_FALSE(ValidateIntervals(intervals, codegen)); intervals.clear(); } // Test with siblings. { static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}}; - intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetAllocator(), 0)); + intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0)); intervals[0]->SplitAt(43); static constexpr size_t ranges2[][2] = {{42, 47}}; - intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetAllocator(), 1)); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[1]->SetRegister(0); // Sibling of the first interval has no register allocated to it. - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); intervals[0]->GetNextSibling()->SetRegister(0); - ASSERT_FALSE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_FALSE(ValidateIntervals(intervals, codegen)); } } @@ -328,10 +327,10 @@ void RegisterAllocatorTest::Loop3(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_TRUE(register_allocator->Validate(false)); @@ -363,7 +362,7 @@ TEST_F(RegisterAllocatorTest, FirstRegisterUse) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); HXor* first_xor = graph->GetBlocks()[1]->GetFirstInstruction()->AsXor(); @@ -416,10 +415,10 @@ void RegisterAllocatorTest::DeadPhi(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_TRUE(register_allocator->Validate(false)); } @@ -442,9 +441,9 @@ TEST_F(RegisterAllocatorTest, FreeUntil) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocatorLinearScan register_allocator(GetAllocator(), &codegen, liveness); + RegisterAllocatorLinearScan register_allocator(GetScopedAllocator(), &codegen, liveness); // Add an artifical range to cover the temps that will be put in the unhandled list. LiveInterval* unhandled = graph->GetEntryBlock()->GetFirstInstruction()->GetLiveInterval(); @@ -464,15 +463,15 @@ TEST_F(RegisterAllocatorTest, FreeUntil) { // Put the one that should be picked in the middle of the inactive list to ensure // we do not depend on an order. LiveInterval* interval = - LiveInterval::MakeFixedInterval(GetAllocator(), 0, DataType::Type::kInt32); + LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32); interval->AddRange(40, 50); register_allocator.inactive_.push_back(interval); - interval = LiveInterval::MakeFixedInterval(GetAllocator(), 0, DataType::Type::kInt32); + interval = LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32); interval->AddRange(20, 30); register_allocator.inactive_.push_back(interval); - interval = LiveInterval::MakeFixedInterval(GetAllocator(), 0, DataType::Type::kInt32); + interval = LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32); interval->AddRange(60, 70); register_allocator.inactive_.push_back(interval); @@ -570,12 +569,12 @@ void RegisterAllocatorTest::PhiHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Check that the register allocator is deterministic. - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 0); @@ -588,14 +587,14 @@ void RegisterAllocatorTest::PhiHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Set the phi to a specific register, and check that the inputs get allocated // the same register. phi->GetLocations()->UpdateOut(Location::RegisterLocation(2)); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2); @@ -608,14 +607,14 @@ void RegisterAllocatorTest::PhiHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Set input1 to a specific register, and check that the phi and other input get allocated // the same register. input1->GetLocations()->UpdateOut(Location::RegisterLocation(2)); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2); @@ -628,14 +627,14 @@ void RegisterAllocatorTest::PhiHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Set input2 to a specific register, and check that the phi and other input get allocated // the same register. input2->GetLocations()->UpdateOut(Location::RegisterLocation(2)); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2); @@ -693,11 +692,11 @@ void RegisterAllocatorTest::ExpectedInRegisterHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); // Sanity check that in normal conditions, the register should be hinted to 0 (EAX). @@ -709,15 +708,15 @@ void RegisterAllocatorTest::ExpectedInRegisterHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // Check that the field gets put in the register expected by its use. // Don't use SetInAt because we are overriding an already allocated location. ret->GetLocations()->inputs_[0] = Location::RegisterLocation(2); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 2); @@ -765,11 +764,11 @@ void RegisterAllocatorTest::SameAsFirstInputHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); // Sanity check that in normal conditions, the registers are the same. @@ -782,7 +781,7 @@ void RegisterAllocatorTest::SameAsFirstInputHint(Strategy strategy) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); // check that both adds get the same register. @@ -791,8 +790,8 @@ void RegisterAllocatorTest::SameAsFirstInputHint(Strategy strategy) { ASSERT_EQ(first_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput); ASSERT_EQ(second_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 2); @@ -838,11 +837,11 @@ void RegisterAllocatorTest::ExpectedExactInRegisterAndSameOutputHint(Strategy st std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); liveness.Analyze(); - RegisterAllocator* register_allocator = - RegisterAllocator::Create(GetAllocator(), &codegen, liveness, strategy); + std::unique_ptr<RegisterAllocator> register_allocator = + RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy); register_allocator->AllocateRegisters(); // div on x86 requires its first input in eax and the output be the same as the first input. @@ -892,14 +891,14 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { LocationSummary* locations = new (GetAllocator()) LocationSummary(user, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); static constexpr size_t phi_ranges[][2] = {{20, 30}}; - BuildInterval(phi_ranges, arraysize(phi_ranges), GetAllocator(), -1, user); + BuildInterval(phi_ranges, arraysize(phi_ranges), GetScopedAllocator(), -1, user); // Create an interval with lifetime holes. static constexpr size_t ranges1[][2] = {{0, 2}, {4, 6}, {8, 10}}; - LiveInterval* first = BuildInterval(ranges1, arraysize(ranges1), GetAllocator(), -1, one); - first->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 8)); - first->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 7)); - first->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 6)); + LiveInterval* first = BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), -1, one); + first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 8)); + first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 7)); + first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 6)); locations = new (GetAllocator()) LocationSummary(first->GetDefinedBy(), LocationSummary::kNoCall); locations->SetOut(Location::RequiresRegister()); @@ -908,7 +907,7 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { // Create an interval that conflicts with the next interval, to force the next // interval to call `AllocateBlockedReg`. static constexpr size_t ranges2[][2] = {{2, 4}}; - LiveInterval* second = BuildInterval(ranges2, arraysize(ranges2), GetAllocator(), -1, two); + LiveInterval* second = BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), -1, two); locations = new (GetAllocator()) LocationSummary(second->GetDefinedBy(), LocationSummary::kNoCall); locations->SetOut(Location::RequiresRegister()); @@ -919,10 +918,10 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { // "[0, 2(, [4, 6(" in the list of handled intervals, even though we haven't processed intervals // before lifetime position 6 yet. static constexpr size_t ranges3[][2] = {{2, 4}, {8, 10}}; - LiveInterval* third = BuildInterval(ranges3, arraysize(ranges3), GetAllocator(), -1, three); - third->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 8)); - third->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 4)); - third->uses_.push_front(*new(GetAllocator()) UsePosition(user, false, 3)); + LiveInterval* third = BuildInterval(ranges3, arraysize(ranges3), GetScopedAllocator(), -1, three); + third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 8)); + third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 4)); + third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, false, 3)); locations = new (GetAllocator()) LocationSummary(third->GetDefinedBy(), LocationSummary::kNoCall); locations->SetOut(Location::RequiresRegister()); third = third->SplitAt(3); @@ -930,7 +929,7 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { // Because the first part of the split interval was considered handled, this interval // was free to allocate the same register, even though it conflicts with it. static constexpr size_t ranges4[][2] = {{4, 6}}; - LiveInterval* fourth = BuildInterval(ranges4, arraysize(ranges4), GetAllocator(), -1, four); + LiveInterval* fourth = BuildInterval(ranges4, arraysize(ranges4), GetScopedAllocator(), -1, four); locations = new (GetAllocator()) LocationSummary(fourth->GetDefinedBy(), LocationSummary::kNoCall); locations->SetOut(Location::RequiresRegister()); @@ -938,13 +937,13 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); - SsaLivenessAnalysis liveness(graph, &codegen); + SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator()); // Populate the instructions in the liveness object, to please the register allocator. for (size_t i = 0; i < 32; ++i) { liveness.instructions_from_lifetime_position_.push_back(user); } - RegisterAllocatorLinearScan register_allocator(GetAllocator(), &codegen, liveness); + RegisterAllocatorLinearScan register_allocator(GetScopedAllocator(), &codegen, liveness); register_allocator.unhandled_core_intervals_.push_back(fourth); register_allocator.unhandled_core_intervals_.push_back(third); register_allocator.unhandled_core_intervals_.push_back(second); @@ -958,13 +957,12 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { register_allocator.LinearScan(); // Test that there is no conflicts between intervals. - ArenaVector<LiveInterval*> intervals(GetAllocator()->Adapter()); + ScopedArenaVector<LiveInterval*> intervals(GetScopedAllocator()->Adapter()); intervals.push_back(first); intervals.push_back(second); intervals.push_back(third); intervals.push_back(fourth); - ASSERT_TRUE(RegisterAllocator::ValidateIntervals( - intervals, 0, 0, codegen, GetAllocator(), true, false)); + ASSERT_TRUE(ValidateIntervals(intervals, codegen)); } } // namespace art diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc index 9acf6d2906..c673d54458 100644 --- a/compiler/optimizing/scheduler.cc +++ b/compiler/optimizing/scheduler.cc @@ -564,7 +564,7 @@ void HScheduler::Schedule(HGraph* graph) { } void HScheduler::Schedule(HBasicBlock* block) { - ScopedArenaVector<SchedulingNode*> scheduling_nodes(arena_->Adapter(kArenaAllocScheduler)); + ScopedArenaVector<SchedulingNode*> scheduling_nodes(allocator_->Adapter(kArenaAllocScheduler)); // Build the scheduling graph. scheduling_graph_.Clear(); @@ -595,7 +595,7 @@ void HScheduler::Schedule(HBasicBlock* block) { } } - ScopedArenaVector<SchedulingNode*> initial_candidates(arena_->Adapter(kArenaAllocScheduler)); + ScopedArenaVector<SchedulingNode*> initial_candidates(allocator_->Adapter(kArenaAllocScheduler)); if (kDumpDotSchedulingGraphs) { // Remember the list of initial candidates for debug output purposes. initial_candidates.assign(candidates_.begin(), candidates_.end()); diff --git a/compiler/optimizing/scheduler.h b/compiler/optimizing/scheduler.h index 493ec0b07b..3efd26af9b 100644 --- a/compiler/optimizing/scheduler.h +++ b/compiler/optimizing/scheduler.h @@ -156,14 +156,14 @@ class HScheduler; */ class SchedulingNode : public DeletableArenaObject<kArenaAllocScheduler> { public: - SchedulingNode(HInstruction* instr, ScopedArenaAllocator* arena, bool is_scheduling_barrier) + SchedulingNode(HInstruction* instr, ScopedArenaAllocator* allocator, bool is_scheduling_barrier) : latency_(0), internal_latency_(0), critical_path_(0), instruction_(instr), is_scheduling_barrier_(is_scheduling_barrier), - data_predecessors_(arena->Adapter(kArenaAllocScheduler)), - other_predecessors_(arena->Adapter(kArenaAllocScheduler)), + data_predecessors_(allocator->Adapter(kArenaAllocScheduler)), + other_predecessors_(allocator->Adapter(kArenaAllocScheduler)), num_unscheduled_successors_(0) { data_predecessors_.reserve(kPreallocatedPredecessors); } @@ -251,9 +251,9 @@ class SchedulingNode : public DeletableArenaObject<kArenaAllocScheduler> { */ class SchedulingGraph : public ValueObject { public: - SchedulingGraph(const HScheduler* scheduler, ScopedArenaAllocator* arena) + SchedulingGraph(const HScheduler* scheduler, ScopedArenaAllocator* allocator) : scheduler_(scheduler), - arena_(arena), + arena_(allocator), contains_scheduling_barrier_(false), nodes_map_(arena_->Adapter(kArenaAllocScheduler)), heap_location_collector_(nullptr) {} @@ -434,16 +434,16 @@ class CriticalPathSchedulingNodeSelector : public SchedulingNodeSelector { class HScheduler { public: - HScheduler(ScopedArenaAllocator* arena, + HScheduler(ScopedArenaAllocator* allocator, SchedulingLatencyVisitor* latency_visitor, SchedulingNodeSelector* selector) - : arena_(arena), + : allocator_(allocator), latency_visitor_(latency_visitor), selector_(selector), only_optimize_loop_blocks_(true), - scheduling_graph_(this, arena), + scheduling_graph_(this, allocator), cursor_(nullptr), - candidates_(arena_->Adapter(kArenaAllocScheduler)) {} + candidates_(allocator_->Adapter(kArenaAllocScheduler)) {} virtual ~HScheduler() {} void Schedule(HGraph* graph); @@ -471,7 +471,7 @@ class HScheduler { node->SetInternalLatency(latency_visitor_->GetLastVisitedInternalLatency()); } - ScopedArenaAllocator* const arena_; + ScopedArenaAllocator* const allocator_; SchedulingLatencyVisitor* const latency_visitor_; SchedulingNodeSelector* const selector_; bool only_optimize_loop_blocks_; diff --git a/compiler/optimizing/scheduler_arm.h b/compiler/optimizing/scheduler_arm.h index 62cd75cf59..0cb8684376 100644 --- a/compiler/optimizing/scheduler_arm.h +++ b/compiler/optimizing/scheduler_arm.h @@ -137,10 +137,10 @@ class SchedulingLatencyVisitorARM : public SchedulingLatencyVisitor { class HSchedulerARM : public HScheduler { public: - HSchedulerARM(ScopedArenaAllocator* arena, + HSchedulerARM(ScopedArenaAllocator* allocator, SchedulingNodeSelector* selector, SchedulingLatencyVisitorARM* arm_latency_visitor) - : HScheduler(arena, arm_latency_visitor, selector) {} + : HScheduler(allocator, arm_latency_visitor, selector) {} ~HSchedulerARM() OVERRIDE {} bool IsSchedulable(const HInstruction* instruction) const OVERRIDE { diff --git a/compiler/optimizing/scheduler_arm64.h b/compiler/optimizing/scheduler_arm64.h index 6682c66ea6..32f161f26a 100644 --- a/compiler/optimizing/scheduler_arm64.h +++ b/compiler/optimizing/scheduler_arm64.h @@ -131,8 +131,8 @@ class SchedulingLatencyVisitorARM64 : public SchedulingLatencyVisitor { class HSchedulerARM64 : public HScheduler { public: - HSchedulerARM64(ScopedArenaAllocator* arena, SchedulingNodeSelector* selector) - : HScheduler(arena, &arm64_latency_visitor_, selector) {} + HSchedulerARM64(ScopedArenaAllocator* allocator, SchedulingNodeSelector* selector) + : HScheduler(allocator, &arm64_latency_visitor_, selector) {} ~HSchedulerARM64() OVERRIDE {} bool IsSchedulable(const HInstruction* instruction) const OVERRIDE { diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc index 7e1ec70789..dfc1633fe6 100644 --- a/compiler/optimizing/scheduler_test.cc +++ b/compiler/optimizing/scheduler_test.cc @@ -146,8 +146,7 @@ class SchedulerTest : public OptimizingUnitTest { environment->SetRawEnvAt(1, mul); mul->AddEnvUseAt(div_check->GetEnvironment(), 1); - ScopedArenaAllocator allocator(graph_->GetArenaStack()); - SchedulingGraph scheduling_graph(scheduler, &allocator); + SchedulingGraph scheduling_graph(scheduler, GetScopedAllocator()); // Instructions must be inserted in reverse order into the scheduling graph. for (HInstruction* instr : ReverseRange(block_instructions)) { scheduling_graph.AddNode(instr); @@ -273,8 +272,7 @@ class SchedulerTest : public OptimizingUnitTest { entry->AddInstruction(instr); } - ScopedArenaAllocator allocator(graph_->GetArenaStack()); - SchedulingGraph scheduling_graph(scheduler, &allocator); + SchedulingGraph scheduling_graph(scheduler, GetScopedAllocator()); HeapLocationCollector heap_location_collector(graph_); heap_location_collector.VisitBasicBlock(entry); heap_location_collector.BuildAliasingMatrix(); @@ -352,15 +350,13 @@ class SchedulerTest : public OptimizingUnitTest { #if defined(ART_ENABLE_CODEGEN_arm64) TEST_F(SchedulerTest, DependencyGraphAndSchedulerARM64) { CriticalPathSchedulingNodeSelector critical_path_selector; - ScopedArenaAllocator allocator(GetArenaStack()); - arm64::HSchedulerARM64 scheduler(&allocator, &critical_path_selector); + arm64::HSchedulerARM64 scheduler(GetScopedAllocator(), &critical_path_selector); TestBuildDependencyGraphAndSchedule(&scheduler); } TEST_F(SchedulerTest, ArrayAccessAliasingARM64) { CriticalPathSchedulingNodeSelector critical_path_selector; - ScopedArenaAllocator allocator(GetArenaStack()); - arm64::HSchedulerARM64 scheduler(&allocator, &critical_path_selector); + arm64::HSchedulerARM64 scheduler(GetScopedAllocator(), &critical_path_selector); TestDependencyGraphOnAliasingArrayAccesses(&scheduler); } #endif @@ -369,16 +365,14 @@ TEST_F(SchedulerTest, ArrayAccessAliasingARM64) { TEST_F(SchedulerTest, DependencyGraphAndSchedulerARM) { CriticalPathSchedulingNodeSelector critical_path_selector; arm::SchedulingLatencyVisitorARM arm_latency_visitor(/*CodeGenerator*/ nullptr); - ScopedArenaAllocator allocator(GetArenaStack()); - arm::HSchedulerARM scheduler(&allocator, &critical_path_selector, &arm_latency_visitor); + arm::HSchedulerARM scheduler(GetScopedAllocator(), &critical_path_selector, &arm_latency_visitor); TestBuildDependencyGraphAndSchedule(&scheduler); } TEST_F(SchedulerTest, ArrayAccessAliasingARM) { CriticalPathSchedulingNodeSelector critical_path_selector; arm::SchedulingLatencyVisitorARM arm_latency_visitor(/*CodeGenerator*/ nullptr); - ScopedArenaAllocator allocator(GetArenaStack()); - arm::HSchedulerARM scheduler(&allocator, &critical_path_selector, &arm_latency_visitor); + arm::HSchedulerARM scheduler(GetScopedAllocator(), &critical_path_selector, &arm_latency_visitor); TestDependencyGraphOnAliasingArrayAccesses(&scheduler); } #endif diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index fd56601b36..9ab7a89b33 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -56,7 +56,7 @@ void SsaLivenessAnalysis::NumberInstructions() { instructions_from_ssa_index_.push_back(current); current->SetSsaIndex(ssa_index++); current->SetLiveInterval( - LiveInterval::MakeInterval(graph_->GetAllocator(), current->GetType(), current)); + LiveInterval::MakeInterval(allocator_, current->GetType(), current)); } current->SetLifetimePosition(lifetime_position); } @@ -74,7 +74,7 @@ void SsaLivenessAnalysis::NumberInstructions() { instructions_from_ssa_index_.push_back(current); current->SetSsaIndex(ssa_index++); current->SetLiveInterval( - LiveInterval::MakeInterval(graph_->GetAllocator(), current->GetType(), current)); + LiveInterval::MakeInterval(allocator_, current->GetType(), current)); } instructions_from_lifetime_position_.push_back(current); current->SetLifetimePosition(lifetime_position); @@ -88,8 +88,8 @@ void SsaLivenessAnalysis::NumberInstructions() { void SsaLivenessAnalysis::ComputeLiveness() { for (HBasicBlock* block : graph_->GetLinearOrder()) { - block_infos_[block->GetBlockId()] = new (graph_->GetAllocator()) BlockInfo( - graph_->GetAllocator(), *block, number_of_ssa_values_); + block_infos_[block->GetBlockId()] = + new (allocator_) BlockInfo(allocator_, *block, number_of_ssa_values_); } // Compute the live ranges, as well as the initial live_in, live_out, and kill sets. diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index 0d81e9dfe7..9800af76f8 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -20,6 +20,8 @@ #include <iostream> #include "base/iteration_range.h" +#include "base/scoped_arena_allocator.h" +#include "base/scoped_arena_containers.h" #include "nodes.h" #include "utils/intrusive_forward_list.h" @@ -32,7 +34,7 @@ static constexpr int kNoRegister = -1; class BlockInfo : public ArenaObject<kArenaAllocSsaLiveness> { public: - BlockInfo(ArenaAllocator* allocator, const HBasicBlock& block, size_t number_of_ssa_values) + BlockInfo(ScopedArenaAllocator* allocator, const HBasicBlock& block, size_t number_of_ssa_values) : block_(block), live_in_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness), live_out_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness), @@ -82,7 +84,7 @@ class LiveRange FINAL : public ArenaObject<kArenaAllocSsaLiveness> { stream << "[" << start_ << "," << end_ << ")"; } - LiveRange* Dup(ArenaAllocator* allocator) const { + LiveRange* Dup(ScopedArenaAllocator* allocator) const { return new (allocator) LiveRange( start_, end_, next_ == nullptr ? nullptr : next_->Dup(allocator)); } @@ -135,7 +137,7 @@ class UsePosition : public ArenaObject<kArenaAllocSsaLiveness>, return user_->GetBlock()->GetLoopInformation(); } - UsePosition* Clone(ArenaAllocator* allocator) const { + UsePosition* Clone(ScopedArenaAllocator* allocator) const { return new (allocator) UsePosition(user_, input_index_, position_); } @@ -180,7 +182,7 @@ class EnvUsePosition : public ArenaObject<kArenaAllocSsaLiveness>, stream << position_; } - EnvUsePosition* Clone(ArenaAllocator* allocator) const { + EnvUsePosition* Clone(ScopedArenaAllocator* allocator) const { return new (allocator) EnvUsePosition(environment_, input_index_, position_); } @@ -261,17 +263,19 @@ class SafepointPosition : public ArenaObject<kArenaAllocSsaLiveness> { */ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { public: - static LiveInterval* MakeInterval(ArenaAllocator* allocator, + static LiveInterval* MakeInterval(ScopedArenaAllocator* allocator, DataType::Type type, HInstruction* instruction = nullptr) { return new (allocator) LiveInterval(allocator, type, instruction); } - static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, DataType::Type type) { + static LiveInterval* MakeFixedInterval(ScopedArenaAllocator* allocator, + int reg, + DataType::Type type) { return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false); } - static LiveInterval* MakeTempInterval(ArenaAllocator* allocator, DataType::Type type) { + static LiveInterval* MakeTempInterval(ScopedArenaAllocator* allocator, DataType::Type type) { return new (allocator) LiveInterval(allocator, type, nullptr, false, kNoRegister, true); } @@ -969,7 +973,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { } private: - LiveInterval(ArenaAllocator* allocator, + LiveInterval(ScopedArenaAllocator* allocator, DataType::Type type, HInstruction* defined_by = nullptr, bool is_fixed = false, @@ -1082,7 +1086,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { } } - ArenaAllocator* const allocator_; + ScopedArenaAllocator* const allocator_; // Ranges of this interval. We need a quick access to the last range to test // for liveness (see `IsDeadAt`). @@ -1158,15 +1162,15 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { */ class SsaLivenessAnalysis : public ValueObject { public: - SsaLivenessAnalysis(HGraph* graph, CodeGenerator* codegen) + SsaLivenessAnalysis(HGraph* graph, CodeGenerator* codegen, ScopedArenaAllocator* allocator) : graph_(graph), codegen_(codegen), + allocator_(allocator), block_infos_(graph->GetBlocks().size(), nullptr, - graph->GetAllocator()->Adapter(kArenaAllocSsaLiveness)), - instructions_from_ssa_index_(graph->GetAllocator()->Adapter(kArenaAllocSsaLiveness)), - instructions_from_lifetime_position_( - graph->GetAllocator()->Adapter(kArenaAllocSsaLiveness)), + allocator_->Adapter(kArenaAllocSsaLiveness)), + instructions_from_ssa_index_(allocator_->Adapter(kArenaAllocSsaLiveness)), + instructions_from_lifetime_position_(allocator_->Adapter(kArenaAllocSsaLiveness)), number_of_ssa_values_(0) { } @@ -1285,13 +1289,18 @@ class SsaLivenessAnalysis : public ValueObject { HGraph* const graph_; CodeGenerator* const codegen_; - ArenaVector<BlockInfo*> block_infos_; + + // Use a local ScopedArenaAllocator for allocating memory. + // This allocator must remain alive while doing register allocation. + ScopedArenaAllocator* allocator_; + + ScopedArenaVector<BlockInfo*> block_infos_; // Temporary array used when computing live_in, live_out, and kill sets. - ArenaVector<HInstruction*> instructions_from_ssa_index_; + ScopedArenaVector<HInstruction*> instructions_from_ssa_index_; // Temporary array used when inserting moves in the graph. - ArenaVector<HInstruction*> instructions_from_lifetime_position_; + ScopedArenaVector<HInstruction*> instructions_from_lifetime_position_; size_t number_of_ssa_values_; ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive); diff --git a/compiler/optimizing/ssa_liveness_analysis_test.cc b/compiler/optimizing/ssa_liveness_analysis_test.cc index 82ee441aa8..9b78e0ee6c 100644 --- a/compiler/optimizing/ssa_liveness_analysis_test.cc +++ b/compiler/optimizing/ssa_liveness_analysis_test.cc @@ -75,7 +75,7 @@ TEST_F(SsaLivenessAnalysisTest, TestReturnArg) { block->AddInstruction(new (GetAllocator()) HExit()); graph_->BuildDominatorTree(); - SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get()); + SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get(), GetScopedAllocator()); ssa_analysis.Analyze(); std::ostringstream arg_dump; @@ -127,7 +127,7 @@ TEST_F(SsaLivenessAnalysisTest, TestAput) { block->AddInstruction(array_set); graph_->BuildDominatorTree(); - SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get()); + SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get(), GetScopedAllocator()); ssa_analysis.Analyze(); EXPECT_FALSE(graph_->IsDebuggable()); @@ -201,7 +201,7 @@ TEST_F(SsaLivenessAnalysisTest, TestDeoptimize) { block->AddInstruction(array_set); graph_->BuildDominatorTree(); - SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get()); + SsaLivenessAnalysis ssa_analysis(graph_, codegen_.get(), GetScopedAllocator()); ssa_analysis.Analyze(); EXPECT_FALSE(graph_->IsDebuggable()); |