Revert "Revert "Refactor HGraphBuilder and SsaBuilder to remove HLocals""
This patch merges the instruction-building phases from HGraphBuilder
and SsaBuilder into a single HInstructionBuilder class. As a result,
it is not necessary to generate HLocal, HLoadLocal and HStoreLocal
instructions any more, as the builder produces SSA form directly.
Saves 5-15% of arena-allocated memory (see bug for more data):
GMS 20.46MB => 19.26MB (-5.86%)
Maps 24.12MB => 21.47MB (-10.98%)
YouTube 28.60MB => 26.01MB (-9.05%)
This CL fixed an issue with parsing quickened instructions.
Bug: 27894376
Bug: 27998571
Bug: 27995065
Change-Id: I20dbe1bf2d0fe296377478db98cb86cba695e694
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 50a1334..4f46d5e 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -24,14 +24,14 @@
#include "dex_file-inl.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
+#include "instruction_builder.h"
#include "optimizing_compiler_stats.h"
#include "primitive.h"
#include "nodes.h"
+#include "ssa_builder.h"
namespace art {
-class Instruction;
-
class HGraphBuilder : public ValueObject {
public:
HGraphBuilder(HGraph* graph,
@@ -42,245 +42,65 @@
CompilerDriver* driver,
OptimizingCompilerStats* compiler_stats,
const uint8_t* interpreter_metadata,
- Handle<mirror::DexCache> dex_cache)
- : arena_(graph->GetArena()),
- locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
- current_block_(nullptr),
- graph_(graph),
+ Handle<mirror::DexCache> dex_cache,
+ StackHandleScopeCollection* handles)
+ : graph_(graph),
dex_file_(dex_file),
code_item_(code_item),
dex_compilation_unit_(dex_compilation_unit),
compiler_driver_(driver),
- outer_compilation_unit_(outer_compilation_unit),
- return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])),
- code_start_(code_item.insns_),
- block_builder_(graph, dex_file, code_item),
- latest_result_(nullptr),
compilation_stats_(compiler_stats),
- interpreter_metadata_(interpreter_metadata),
- dex_cache_(dex_cache) {}
+ block_builder_(graph, dex_file, code_item),
+ ssa_builder_(graph, handles),
+ instruction_builder_(graph,
+ &block_builder_,
+ &ssa_builder_,
+ dex_file,
+ code_item_,
+ Primitive::GetType(dex_compilation_unit_->GetShorty()[0]),
+ dex_compilation_unit,
+ outer_compilation_unit,
+ driver,
+ interpreter_metadata,
+ compiler_stats,
+ dex_cache) {}
// Only for unit testing.
HGraphBuilder(HGraph* graph,
const DexFile::CodeItem& code_item,
+ StackHandleScopeCollection* handles,
Primitive::Type return_type = Primitive::kPrimInt)
- : arena_(graph->GetArena()),
- locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
- current_block_(nullptr),
- graph_(graph),
+ : graph_(graph),
dex_file_(nullptr),
code_item_(code_item),
dex_compilation_unit_(nullptr),
compiler_driver_(nullptr),
- outer_compilation_unit_(nullptr),
- return_type_(return_type),
- code_start_(code_item.insns_),
- block_builder_(graph, nullptr, code_item),
- latest_result_(nullptr),
- compilation_stats_(nullptr),
- interpreter_metadata_(nullptr),
null_dex_cache_(),
- dex_cache_(null_dex_cache_) {}
+ compilation_stats_(nullptr),
+ block_builder_(graph, nullptr, code_item),
+ ssa_builder_(graph, handles),
+ instruction_builder_(graph,
+ &block_builder_,
+ &ssa_builder_,
+ /* dex_file */ nullptr,
+ code_item_,
+ return_type,
+ /* dex_compilation_unit */ nullptr,
+ /* outer_compilation_unit */ nullptr,
+ /* compiler_driver */ nullptr,
+ /* interpreter_metadata */ nullptr,
+ /* compiler_stats */ nullptr,
+ null_dex_cache_) {}
- GraphAnalysisResult BuildGraph(StackHandleScopeCollection* handles);
+ GraphAnalysisResult BuildGraph();
static constexpr const char* kBuilderPassName = "builder";
private:
- bool GenerateInstructions();
- bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc);
-
- void FindNativeDebugInfoLocations(ArenaBitVector* locations);
-
- bool CanDecodeQuickenedInfo() const;
- uint16_t LookupQuickenedInfo(uint32_t dex_pc);
-
- HBasicBlock* FindBlockStartingAt(uint32_t dex_pc) const {
- return block_builder_.GetBlockAt(dex_pc);
- }
-
- void InitializeLocals(uint16_t count);
- HLocal* GetLocalAt(uint32_t register_index) const;
- void UpdateLocal(uint32_t register_index, HInstruction* instruction, uint32_t dex_pc) const;
- HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type, uint32_t dex_pc) const;
- void InitializeParameters(uint16_t number_of_parameters);
-
- // Returns whether the current method needs access check for the type.
- // Output parameter finalizable is set to whether the type is finalizable.
- bool NeedsAccessCheck(uint32_t type_index, /*out*/bool* finalizable) const;
-
- template<typename T>
- void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- template<typename T>
- void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- template<typename T>
- void Binop_23x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- void Binop_23x_cmp(const Instruction& instruction,
- Primitive::Type type,
- ComparisonBias bias,
- uint32_t dex_pc);
-
- template<typename T>
- void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- template<typename T>
- void Binop_12x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- template<typename T>
- void Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc);
-
- template<typename T>
- void Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc);
-
- template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_pc);
- template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc);
-
- void Conversion_12x(const Instruction& instruction,
- Primitive::Type input_type,
- Primitive::Type result_type,
- uint32_t dex_pc);
-
- void BuildCheckedDivRem(uint16_t out_reg,
- uint16_t first_reg,
- int64_t second_reg_or_constant,
- uint32_t dex_pc,
- Primitive::Type type,
- bool second_is_lit,
- bool is_div);
-
- void BuildReturn(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
- // Builds an instance field access node and returns whether the instruction is supported.
- bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
-
- void BuildUnresolvedStaticFieldAccess(const Instruction& instruction,
- uint32_t dex_pc,
- bool is_put,
- Primitive::Type field_type);
- // Builds a static field access node and returns whether the instruction is supported.
- bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
-
- void BuildArrayAccess(const Instruction& instruction,
- uint32_t dex_pc,
- bool is_get,
- Primitive::Type anticipated_type);
-
- // Builds an invocation node and returns whether the instruction is supported.
- bool BuildInvoke(const Instruction& instruction,
- uint32_t dex_pc,
- uint32_t method_idx,
- uint32_t number_of_vreg_arguments,
- bool is_range,
- uint32_t* args,
- uint32_t register_index);
-
- // Builds a new array node and the instructions that fill it.
- void BuildFilledNewArray(uint32_t dex_pc,
- uint32_t type_index,
- uint32_t number_of_vreg_arguments,
- bool is_range,
- uint32_t* args,
- uint32_t register_index);
-
- void BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc);
-
- // Fills the given object with data as specified in the fill-array-data
- // instruction. Currently only used for non-reference and non-floating point
- // arrays.
- template <typename T>
- void BuildFillArrayData(HInstruction* object,
- const T* data,
- uint32_t element_count,
- Primitive::Type anticipated_type,
- uint32_t dex_pc);
-
- // Fills the given object with data as specified in the fill-array-data
- // instruction. The data must be for long and double arrays.
- void BuildFillWideArrayData(HInstruction* object,
- const int64_t* data,
- uint32_t element_count,
- uint32_t dex_pc);
-
- // Builds a `HInstanceOf`, or a `HCheckCast` instruction.
- void BuildTypeCheck(const Instruction& instruction,
- uint8_t destination,
- uint8_t reference,
- uint16_t type_index,
- uint32_t dex_pc);
-
- // Builds an instruction sequence for a switch statement.
- void BuildSwitch(const Instruction& instruction, uint32_t dex_pc);
-
+ void MaybeRecordStat(MethodCompilationStat compilation_stat);
bool SkipCompilation(size_t number_of_branches);
- void MaybeRecordStat(MethodCompilationStat compilation_stat);
-
- // Returns the outer-most compiling method's class.
- mirror::Class* GetOutermostCompilingClass() const;
-
- // Returns the class whose method is being compiled.
- mirror::Class* GetCompilingClass() const;
-
- // Returns whether `type_index` points to the outer-most compiling method's class.
- bool IsOutermostCompilingClass(uint16_t type_index) const;
-
- void PotentiallySimplifyFakeString(uint16_t original_dex_register,
- uint32_t dex_pc,
- HInvoke* invoke);
-
- bool SetupInvokeArguments(HInvoke* invoke,
- uint32_t number_of_vreg_arguments,
- uint32_t* args,
- uint32_t register_index,
- bool is_range,
- const char* descriptor,
- size_t start_index,
- size_t* argument_index);
-
- bool HandleInvoke(HInvoke* invoke,
- uint32_t number_of_vreg_arguments,
- uint32_t* args,
- uint32_t register_index,
- bool is_range,
- const char* descriptor,
- HClinitCheck* clinit_check);
-
- bool HandleStringInit(HInvoke* invoke,
- uint32_t number_of_vreg_arguments,
- uint32_t* args,
- uint32_t register_index,
- bool is_range,
- const char* descriptor);
-
- HClinitCheck* ProcessClinitCheckForInvoke(
- uint32_t dex_pc,
- ArtMethod* method,
- uint32_t method_idx,
- HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- // Build a HNewInstance instruction.
- bool BuildNewInstance(uint16_t type_index, uint32_t dex_pc);
-
- // Return whether the compiler can assume `cls` is initialized.
- bool IsInitialized(Handle<mirror::Class> cls) const
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- // Try to resolve a method using the class linker. Return null if a method could
- // not be resolved.
- ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type);
-
- ArenaAllocator* const arena_;
-
- ArenaVector<HLocal*> locals_;
-
- HBasicBlock* current_block_;
HGraph* const graph_;
-
- // The dex file where the method being compiled is, and the bytecode data.
const DexFile* const dex_file_;
const DexFile::CodeItem& code_item_;
@@ -290,31 +110,13 @@
CompilerDriver* const compiler_driver_;
- // The compilation unit of the outermost method being compiled. That is the
- // method being compiled (and not inlined), and potentially inlining other
- // methods.
- const DexCompilationUnit* const outer_compilation_unit_;
-
- // The return type of the method being compiled.
- const Primitive::Type return_type_;
-
- // The pointer in the dex file where the instructions of the code item
- // being currently compiled start.
- const uint16_t* code_start_;
-
- HBasicBlockBuilder block_builder_;
-
- // The last invoke or fill-new-array being built. Only to be
- // used by move-result instructions.
- HInstruction* latest_result_;
+ ScopedNullHandle<mirror::DexCache> null_dex_cache_;
OptimizingCompilerStats* compilation_stats_;
- const uint8_t* interpreter_metadata_;
-
- // Dex cache for dex_file_.
- ScopedNullHandle<mirror::DexCache> null_dex_cache_;
- Handle<mirror::DexCache> dex_cache_;
+ HBasicBlockBuilder block_builder_;
+ SsaBuilder ssa_builder_;
+ HInstructionBuilder instruction_builder_;
DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
};