diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r-- | compiler/optimizing/nodes.h | 229 |
1 files changed, 97 insertions, 132 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 4a77bed44a..7d6f6164ec 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -171,6 +171,7 @@ class HInstructionList : public ValueObject { friend class HGraph; friend class HInstruction; friend class HInstructionIterator; + friend class HInstructionIteratorHandleChanges; friend class HBackwardInstructionIterator; DISALLOW_COPY_AND_ASSIGN(HInstructionList); @@ -330,6 +331,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)), @@ -551,9 +553,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_; } @@ -572,6 +572,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); @@ -667,6 +671,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. @@ -2305,6 +2313,9 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { }; std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs); +// Iterates over the instructions, while preserving the next instruction +// in case the current instruction gets removed from the list by the user +// of this iterator. class HInstructionIterator : public ValueObject { public: explicit HInstructionIterator(const HInstructionList& instructions) @@ -2326,6 +2337,28 @@ class HInstructionIterator : public ValueObject { DISALLOW_COPY_AND_ASSIGN(HInstructionIterator); }; +// Iterates over the instructions without saving the next instruction, +// therefore handling changes in the graph potentially made by the user +// of this iterator. +class HInstructionIteratorHandleChanges : public ValueObject { + public: + explicit HInstructionIteratorHandleChanges(const HInstructionList& instructions) + : instruction_(instructions.first_instruction_) { + } + + bool Done() const { return instruction_ == nullptr; } + HInstruction* Current() const { return instruction_; } + void Advance() { + instruction_ = instruction_->GetNext(); + } + + private: + HInstruction* instruction_; + + DISALLOW_COPY_AND_ASSIGN(HInstructionIteratorHandleChanges); +}; + + class HBackwardInstructionIterator : public ValueObject { public: explicit HBackwardInstructionIterator(const HInstructionList& instructions) @@ -2349,6 +2382,11 @@ class HBackwardInstructionIterator : public ValueObject { 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); @@ -2489,11 +2527,6 @@ class HPhi FINAL : public HVariableInputSizeInstruction { 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_); - } - 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: @@ -2925,14 +2958,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); @@ -3816,11 +3855,6 @@ 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); } @@ -3974,12 +4008,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), @@ -3998,20 +4026,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. @@ -4027,7 +4041,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, @@ -4137,7 +4150,6 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { return false; } } - bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; } QuickEntrypointEnum GetStringInitEntryPoint() const { DCHECK(IsStringInit()); @@ -4154,11 +4166,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>(); } @@ -5075,60 +5082,62 @@ class HNullCheck FINAL : public HExpression<1> { DISALLOW_COPY_AND_ASSIGN(HNullCheck); }; +// Embeds an ArtField and all the information required by the compiler. We cache +// that information to avoid requiring the mutator lock every time we need it. class FieldInfo : public ValueObject { public: - FieldInfo(MemberOffset field_offset, + FieldInfo(ArtField* field, + MemberOffset field_offset, Primitive::Type field_type, bool is_volatile, uint32_t index, uint16_t declaring_class_def_index, - const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache) - : field_offset_(field_offset), + const DexFile& dex_file) + : field_(field), + field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile), index_(index), declaring_class_def_index_(declaring_class_def_index), - dex_file_(dex_file), - dex_cache_(dex_cache) {} + dex_file_(dex_file) {} + ArtField* GetField() const { return field_; } MemberOffset GetFieldOffset() const { return field_offset_; } Primitive::Type GetFieldType() const { return field_type_; } uint32_t GetFieldIndex() const { return index_; } uint16_t GetDeclaringClassDefIndex() const { return declaring_class_def_index_;} const DexFile& GetDexFile() const { return dex_file_; } bool IsVolatile() const { return is_volatile_; } - Handle<mirror::DexCache> GetDexCache() const { return dex_cache_; } private: + ArtField* const field_; const MemberOffset field_offset_; const Primitive::Type field_type_; const bool is_volatile_; const uint32_t index_; const uint16_t declaring_class_def_index_; const DexFile& dex_file_; - const Handle<mirror::DexCache> dex_cache_; }; class HInstanceFieldGet FINAL : public HExpression<1> { public: HInstanceFieldGet(HInstruction* value, + ArtField* field, Primitive::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, uint16_t declaring_class_def_index, const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc), - field_info_(field_offset, + field_info_(field, + field_offset, field_type, is_volatile, field_idx, declaring_class_def_index, - dex_file, - dex_cache) { + dex_file) { SetRawInputAt(0, value); } @@ -5164,22 +5173,22 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> { public: HInstanceFieldSet(HInstruction* object, HInstruction* value, + ArtField* field, Primitive::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, uint16_t declaring_class_def_index, const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc), - field_info_(field_offset, + field_info_(field, + field_offset, field_type, is_volatile, field_idx, declaring_class_def_index, - dex_file, - dex_cache) { + dex_file) { SetPackedFlag<kFlagValueCanBeNull>(true); SetRawInputAt(0, object); SetRawInputAt(1, value); @@ -5537,9 +5546,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), @@ -5552,8 +5559,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); } @@ -5782,41 +5789,31 @@ class HLoadString FINAL : public HInstruction { uint32_t dex_pc) : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc), special_input_(HUserRecord<HInstruction*>(current_method)), - string_index_(string_index) { - SetPackedFlag<kFlagIsInDexCache>(false); + string_index_(string_index), + dex_file_(dex_file) { SetPackedField<LoadKindField>(LoadKind::kDexCacheViaMethod); - load_data_.dex_file_ = &dex_file; } - void SetLoadKindWithAddress(LoadKind load_kind, uint64_t address) { - DCHECK(HasAddress(load_kind)); - load_data_.address = address; - SetLoadKindInternal(load_kind); - } - - void SetLoadKindWithStringReference(LoadKind load_kind, - const DexFile& dex_file, - dex::StringIndex string_index) { - DCHECK(HasStringReference(load_kind)); - load_data_.dex_file_ = &dex_file; - string_index_ = string_index; - SetLoadKindInternal(load_kind); - } + void SetLoadKind(LoadKind load_kind); LoadKind GetLoadKind() const { return GetPackedField<LoadKindField>(); } - const DexFile& GetDexFile() const; + const DexFile& GetDexFile() const { + return dex_file_; + } dex::StringIndex GetStringIndex() const { - DCHECK(HasStringReference(GetLoadKind()) || /* For slow paths. */ !IsInDexCache()); return string_index_; } - uint64_t GetAddress() const { - DCHECK(HasAddress(GetLoadKind())); - return load_data_.address; + Handle<mirror::String> GetString() const { + return string_; + } + + void SetString(Handle<mirror::String> str) { + string_ = str; } bool CanBeMoved() const OVERRIDE { return true; } @@ -5835,7 +5832,7 @@ class HLoadString FINAL : public HInstruction { load_kind == LoadKind::kJitTableAddress) { return false; } - return !IsInDexCache(); + return true; } bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { @@ -5849,15 +5846,6 @@ class HLoadString FINAL : public HInstruction { return SideEffects::CanTriggerGC(); } - bool IsInDexCache() const { return GetPackedFlag<kFlagIsInDexCache>(); } - - void MarkInDexCache() { - SetPackedFlag<kFlagIsInDexCache>(true); - DCHECK(!NeedsEnvironment()); - RemoveEnvironment(); - SetSideEffects(SideEffects::None()); - } - void AddSpecialInput(HInstruction* special_input); using HInstruction::GetInputRecords; // Keep the const version visible. @@ -5873,26 +5861,13 @@ class HLoadString FINAL : public HInstruction { DECLARE_INSTRUCTION(LoadString); private: - static constexpr size_t kFlagIsInDexCache = kNumberOfGenericPackedBits; - static constexpr size_t kFieldLoadKind = kFlagIsInDexCache + 1; + static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits; static constexpr size_t kFieldLoadKindSize = MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast)); static constexpr size_t kNumberOfLoadStringPackedBits = kFieldLoadKind + kFieldLoadKindSize; static_assert(kNumberOfLoadStringPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>; - static bool HasStringReference(LoadKind load_kind) { - return load_kind == LoadKind::kBootImageLinkTimeAddress || - load_kind == LoadKind::kBootImageLinkTimePcRelative || - load_kind == LoadKind::kBssEntry || - load_kind == LoadKind::kDexCacheViaMethod || - load_kind == LoadKind::kJitTableAddress; - } - - static bool HasAddress(LoadKind load_kind) { - return load_kind == LoadKind::kBootImageAddress; - } - void SetLoadKindInternal(LoadKind load_kind); // The special input is the HCurrentMethod for kDexCacheViaMethod. @@ -5900,26 +5875,16 @@ class HLoadString FINAL : public HInstruction { // for PC-relative loads, i.e. kDexCachePcRelative or kBootImageLinkTimePcRelative. HUserRecord<HInstruction*> special_input_; - // String index serves also as the hash code and it's also needed for slow-paths, - // so it must not be overwritten with other load data. dex::StringIndex string_index_; + const DexFile& dex_file_; - union { - const DexFile* dex_file_; // For string reference. - uint64_t address; // Up to 64-bit, needed for kDexCacheAddress on 64-bit targets. - } load_data_; + Handle<mirror::String> string_; DISALLOW_COPY_AND_ASSIGN(HLoadString); }; std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs); // Note: defined outside class to see operator<<(., HLoadString::LoadKind). -inline const DexFile& HLoadString::GetDexFile() const { - DCHECK(HasStringReference(GetLoadKind())) << GetLoadKind(); - return *load_data_.dex_file_; -} - -// Note: defined outside class to see operator<<(., HLoadString::LoadKind). inline void HLoadString::AddSpecialInput(HInstruction* special_input) { // The special input is used for PC-relative loads on some architectures, // including literal pool loads, which are PC-relative too. @@ -5970,22 +5935,22 @@ class HClinitCheck FINAL : public HExpression<1> { class HStaticFieldGet FINAL : public HExpression<1> { public: HStaticFieldGet(HInstruction* cls, + ArtField* field, Primitive::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, uint16_t declaring_class_def_index, const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc), - field_info_(field_offset, + field_info_(field, + field_offset, field_type, is_volatile, field_idx, declaring_class_def_index, - dex_file, - dex_cache) { + dex_file) { SetRawInputAt(0, cls); } @@ -6018,22 +5983,22 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { public: HStaticFieldSet(HInstruction* cls, HInstruction* value, + ArtField* field, Primitive::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, uint16_t declaring_class_def_index, const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache, uint32_t dex_pc) : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc), - field_info_(field_offset, + field_info_(field, + field_offset, field_type, is_volatile, field_idx, declaring_class_def_index, - dex_file, - dex_cache) { + dex_file) { SetPackedFlag<kFlagValueCanBeNull>(true); SetRawInputAt(0, cls); SetRawInputAt(1, value); |