diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
| -rw-r--r-- | compiler/optimizing/nodes.h | 151 |
1 files changed, 77 insertions, 74 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index e3f4d8f035..afa17cefa2 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -125,6 +125,11 @@ enum GraphAnalysisResult { kAnalysisSuccess, }; +template <typename T> +static inline typename std::make_unsigned<T>::type MakeUnsigned(T x) { + return static_cast<typename std::make_unsigned<T>::type>(x); +} + class HInstructionList : public ValueObject { public: HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {} @@ -325,6 +330,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { invoke_type_(invoke_type), in_ssa_form_(false), should_generate_constructor_barrier_(should_generate_constructor_barrier), + number_of_cha_guards_(0), instruction_set_(instruction_set), cached_null_constant_(nullptr), cached_int_constants_(std::less<int32_t>(), arena->Adapter(kArenaAllocConstantsMap)), @@ -546,9 +552,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { } bool HasShouldDeoptimizeFlag() const { - // TODO: if all CHA guards can be eliminated, there is no need for the flag - // even if cha_single_implementation_list_ is not empty. - return !cha_single_implementation_list_.empty(); + return number_of_cha_guards_ != 0; } bool HasTryCatch() const { return has_try_catch_; } @@ -567,6 +571,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { ReferenceTypeInfo GetInexactObjectRti() const { return inexact_object_rti_; } + uint32_t GetNumberOfCHAGuards() { return number_of_cha_guards_; } + void SetNumberOfCHAGuards(uint32_t num) { number_of_cha_guards_ = num; } + void IncrementNumberOfCHAGuards() { number_of_cha_guards_++; } + private: void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const; void RemoveDeadBlocks(const ArenaBitVector& visited); @@ -662,6 +670,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { const bool should_generate_constructor_barrier_; + // Number of CHA guards in the graph. Used to short-circuit the + // CHA guard optimization pass when there is no CHA guard left. + uint32_t number_of_cha_guards_; + const InstructionSet instruction_set_; // Cached constants. @@ -2342,6 +2354,32 @@ class HBackwardInstructionIterator : public ValueObject { DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator); }; +class HVariableInputSizeInstruction : public HInstruction { + public: + using HInstruction::GetInputRecords; // Keep the const version visible. + ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE { + return ArrayRef<HUserRecord<HInstruction*>>(inputs_); + } + + void AddInput(HInstruction* input); + void InsertInputAt(size_t index, HInstruction* input); + void RemoveInputAt(size_t index); + + protected: + HVariableInputSizeInstruction(SideEffects side_effects, + uint32_t dex_pc, + ArenaAllocator* arena, + size_t number_of_inputs, + ArenaAllocKind kind) + : HInstruction(side_effects, dex_pc), + inputs_(number_of_inputs, arena->Adapter(kind)) {} + + ArenaVector<HUserRecord<HInstruction*>> inputs_; + + private: + DISALLOW_COPY_AND_ASSIGN(HVariableInputSizeInstruction); +}; + template<size_t N> class HTemplateInstruction: public HInstruction { public: @@ -2433,15 +2471,19 @@ class HReturn FINAL : public HTemplateInstruction<1> { DISALLOW_COPY_AND_ASSIGN(HReturn); }; -class HPhi FINAL : public HInstruction { +class HPhi FINAL : public HVariableInputSizeInstruction { public: HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type, uint32_t dex_pc = kNoDexPc) - : HInstruction(SideEffects::None(), dex_pc), - inputs_(number_of_inputs, arena->Adapter(kArenaAllocPhiInputs)), + : HVariableInputSizeInstruction( + SideEffects::None(), + dex_pc, + arena, + number_of_inputs, + kArenaAllocPhiInputs), reg_number_(reg_number) { SetPackedField<TypeField>(ToPhiType(type)); DCHECK_NE(GetType(), Primitive::kPrimVoid); @@ -2459,14 +2501,6 @@ class HPhi FINAL : public HInstruction { bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); } - using HInstruction::GetInputRecords; // Keep the const version visible. - ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL { - return ArrayRef<HUserRecord<HInstruction*>>(inputs_); - } - - void AddInput(HInstruction* input); - void RemoveInputAt(size_t index); - Primitive::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); } void SetType(Primitive::Type new_type) { // Make sure that only valid type changes occur. The following are allowed: @@ -2522,7 +2556,6 @@ class HPhi FINAL : public HInstruction { static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>; - ArenaVector<HUserRecord<HInstruction*>> inputs_; const uint32_t reg_number_; DISALLOW_COPY_AND_ASSIGN(HPhi); @@ -2899,14 +2932,20 @@ class HDeoptimize FINAL : public HTemplateInstruction<1> { // if it's true, starts to do deoptimization. // It has a 4-byte slot on stack. // TODO: allocate a register for this flag. -class HShouldDeoptimizeFlag FINAL : public HExpression<0> { +class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction { public: - // TODO: use SideEffects to aid eliminating some CHA guards. - explicit HShouldDeoptimizeFlag(uint32_t dex_pc) - : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) { + // 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) { } - // We don't eliminate CHA guards yet. + Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimInt; } + + // We do all CHA guard elimination/motion in a single pass, after which there is no + // further guard elimination/motion since a guard might have been used for justification + // of the elimination of another guard. Therefore, we pretend this guard cannot be moved + // to avoid other optimizations trying to move it. bool CanBeMoved() const OVERRIDE { return false; } DECLARE_INSTRUCTION(ShouldDeoptimizeFlag); @@ -3786,15 +3825,10 @@ enum IntrinsicExceptions { kCanThrow // Intrinsic may throw exceptions. }; -class HInvoke : public HInstruction { +class HInvoke : public HVariableInputSizeInstruction { public: bool NeedsEnvironment() const OVERRIDE; - using HInstruction::GetInputRecords; // Keep the const version visible. - ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE { - return ArrayRef<HUserRecord<HInstruction*>>(inputs_); - } - void SetArgumentAt(size_t index, HInstruction* argument) { SetRawInputAt(index, argument); } @@ -3873,12 +3907,14 @@ class HInvoke : public HInstruction { uint32_t dex_method_index, ArtMethod* resolved_method, InvokeType invoke_type) - : HInstruction( - SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays. + : HVariableInputSizeInstruction( + SideEffects::AllExceptGCDependency(), // Assume write/read on all fields/arrays. + dex_pc, + arena, + number_of_arguments + number_of_other_inputs, + kArenaAllocInvokeInputs), number_of_arguments_(number_of_arguments), resolved_method_(resolved_method), - inputs_(number_of_arguments + number_of_other_inputs, - arena->Adapter(kArenaAllocInvokeInputs)), dex_method_index_(dex_method_index), intrinsic_(Intrinsics::kNone), intrinsic_optimizations_(0) { @@ -3889,7 +3925,6 @@ class HInvoke : public HInstruction { uint32_t number_of_arguments_; ArtMethod* const resolved_method_; - ArenaVector<HUserRecord<HInstruction*>> inputs_; const uint32_t dex_method_index_; Intrinsics intrinsic_; @@ -3947,12 +3982,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { // Used for app->boot calls with non-relocatable image and for JIT-compiled calls. kDirectAddress, - // Use ArtMethod* at an address that will be known at link time, embed the direct - // address in the code. If the image is relocatable, emit .patch_oat entry. - // Used for app->boot calls with relocatable image and boot->boot calls, whether - // the image relocatable or not. - kDirectAddressWithFixup, - // Load from resolved methods array in the dex cache using a PC-relative load. // Used when we need to use the dex cache, for example for invoke-static that // may cause class initialization (the entry may point to a resolution method), @@ -3971,20 +4000,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { // Recursive call, use local PC-relative call instruction. kCallSelf, - // Use PC-relative call instruction patched at link time. - // Used for calls within an oat file, boot->boot or app->app. - kCallPCRelative, - - // Call to a known target address, embed the direct address in code. - // Used for app->boot call with non-relocatable image and for JIT-compiled calls. - kCallDirect, - - // Call to a target address that will be known at link time, embed the direct - // address in code. If the image is relocatable, emit .patch_oat entry. - // Used for app->boot calls with relocatable image and boot->boot calls, whether - // the image relocatable or not. - kCallDirectWithFixup, - // Use code pointer from the ArtMethod*. // Used when we don't know the target code. This is also the last-resort-kind used when // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture. @@ -4000,7 +4015,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { // - the method address for kDirectAddress // - the dex cache arrays offset for kDexCachePcRel. uint64_t method_load_data; - uint64_t direct_code_ptr; }; HInvokeStaticOrDirect(ArenaAllocator* arena, @@ -4110,7 +4124,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { return false; } } - bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; } QuickEntrypointEnum GetStringInitEntryPoint() const { DCHECK(IsStringInit()); @@ -4127,11 +4140,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { return dispatch_info_.method_load_data; } - uint64_t GetDirectCodePtr() const { - DCHECK(HasDirectCodePtr()); - return dispatch_info_.direct_code_ptr; - } - ClinitCheckRequirement GetClinitCheckRequirement() const { return GetPackedField<ClinitCheckRequirementField>(); } @@ -4179,10 +4187,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { DECLARE_INSTRUCTION(InvokeStaticOrDirect); - protected: - void InsertInputAt(size_t index, HInstruction* input); - void RemoveInputAt(size_t index); - private: static constexpr size_t kFieldClinitCheckRequirement = kNumberOfInvokePackedBits; static constexpr size_t kFieldClinitCheckRequirementSize = @@ -5493,9 +5497,8 @@ class HLoadClass FINAL : public HInstruction { // GetIncludePatchInformation(). kBootImageAddress, - // Load from the resolved types array at an absolute address. - // Used for classes outside the boot image referenced by JIT-compiled code. - kDexCacheAddress, + // Load from the root table associated with the JIT compiled method. + kJitTableAddress, // Load from resolved types array in the dex cache using a PC-relative load. // Used for classes outside boot image when we know that we can access @@ -5515,9 +5518,7 @@ class HLoadClass FINAL : public HInstruction { const DexFile& dex_file, bool is_referrers_class, uint32_t dex_pc, - bool needs_access_check, - bool is_in_dex_cache, - bool is_in_boot_image) + bool needs_access_check) : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc), special_input_(HUserRecord<HInstruction*>(current_method)), type_index_(type_index), @@ -5530,8 +5531,8 @@ class HLoadClass FINAL : public HInstruction { SetPackedField<LoadKindField>( is_referrers_class ? LoadKind::kReferrersClass : LoadKind::kDexCacheViaMethod); SetPackedFlag<kFlagNeedsAccessCheck>(needs_access_check); - SetPackedFlag<kFlagIsInDexCache>(is_in_dex_cache); - SetPackedFlag<kFlagIsInBootImage>(is_in_boot_image); + SetPackedFlag<kFlagIsInDexCache>(false); + SetPackedFlag<kFlagIsInBootImage>(false); SetPackedFlag<kFlagGenerateClInitCheck>(false); } @@ -5588,7 +5589,6 @@ class HLoadClass FINAL : public HInstruction { NeedsAccessCheck(); } - bool CanThrow() const OVERRIDE { return CanCallRuntime(); } @@ -5613,7 +5613,9 @@ class HLoadClass FINAL : public HInstruction { return load_data_.address; } - bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return !IsReferrersClass(); } + bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { + return !IsReferrersClass(); + } static SideEffects SideEffectsForArchRuntimeCalls() { return SideEffects::CanTriggerGC(); @@ -5672,7 +5674,8 @@ class HLoadClass FINAL : public HInstruction { } static bool HasAddress(LoadKind load_kind) { - return load_kind == LoadKind::kBootImageAddress || load_kind == LoadKind::kDexCacheAddress; + return load_kind == LoadKind::kBootImageAddress || + load_kind == LoadKind::kJitTableAddress; } static bool HasDexCacheReference(LoadKind load_kind) { @@ -5691,7 +5694,7 @@ class HLoadClass FINAL : public HInstruction { union { uint32_t dex_cache_element_index; // Only for dex cache reference. - uint64_t address; // Up to 64-bit, needed for kDexCacheAddress on 64-bit targets. + uint64_t address; // Up to 64-bit, needed for kJitTableAddress on 64-bit targets. } load_data_; ReferenceTypeInfo loaded_class_rti_; |