diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
| -rw-r--r-- | compiler/optimizing/nodes.h | 151 |
1 files changed, 118 insertions, 33 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 939e62c6dd..7df586692b 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -21,6 +21,7 @@ #include <array> #include <type_traits> +#include "base/arena_bit_vector.h" #include "base/arena_containers.h" #include "base/arena_object.h" #include "base/stl_util.h" @@ -34,7 +35,6 @@ #include "mirror/class.h" #include "offsets.h" #include "primitive.h" -#include "utils/arena_bit_vector.h" namespace art { @@ -75,6 +75,7 @@ static constexpr uint32_t kMaxIntShiftValue = 0x1f; static constexpr uint64_t kMaxLongShiftValue = 0x3f; static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1); +static constexpr uint16_t kUnknownClassDefIndex = static_cast<uint16_t>(-1); static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1); @@ -550,6 +551,12 @@ class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> { // Note that `other` *must* be populated before entering this function. bool IsIn(const HLoopInformation& other) const; + // Returns true if instruction is not defined within this loop or any loop nested inside + // this loop. If must_dominate is set, only definitions that actually dominate the loop + // header can be invariant. Otherwise, any definition outside the loop, including + // definitions that appear after the loop, is invariant. + bool IsLoopInvariant(HInstruction* instruction, bool must_dominate) const; + const ArenaBitVector& GetBlocks() const { return blocks_; } void Add(HBasicBlock* block); @@ -1079,14 +1086,25 @@ class HLoopInformationOutwardIterator : public ValueObject { #define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) +#ifndef ART_ENABLE_CODEGEN_arm64 #define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) +#else +#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \ + M(Arm64IntermediateAddress, Instruction) +#endif + +#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) #define FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M) +#ifndef ART_ENABLE_CODEGEN_x86 +#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) +#else #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \ M(X86ComputeBaseMethodAddress, Instruction) \ M(X86LoadFromConstantTable, Instruction) \ M(X86PackedSwitch, Instruction) +#endif #define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M) @@ -1094,6 +1112,7 @@ class HLoopInformationOutwardIterator : public ValueObject { FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \ FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \ FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \ + FOR_EACH_CONCRETE_INSTRUCTION_MIPS(M) \ FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M) \ FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \ FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M) @@ -1370,6 +1389,10 @@ class SideEffects : public ValueObject { return SideEffects(flags_ & ~other.flags_); } + void Add(SideEffects other) { + flags_ |= other.flags_; + } + bool Includes(SideEffects other) const { return (other.flags_ & flags_) == other.flags_; } @@ -1943,6 +1966,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { } SideEffects GetSideEffects() const { return side_effects_; } + void AddSideEffects(SideEffects other) { side_effects_.Add(other); } size_t GetLifetimePosition() const { return lifetime_position_; } void SetLifetimePosition(size_t position) { lifetime_position_ = position; } @@ -1962,7 +1986,9 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { return NeedsEnvironment() || IsLoadClass() || IsLoadString(); } - virtual bool NeedsDexCache() const { return false; } + // Returns whether the code generation of the instruction will require to have access + // to the dex cache of the current method's declaring class via the current method. + virtual bool NeedsDexCacheOfDeclaringClass() const { return false; } // Does this instruction have any use in an environment before // control flow hits 'other'? @@ -2012,7 +2038,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { // order of blocks where this instruction's live interval start. size_t lifetime_position_; - const SideEffects side_effects_; + SideEffects side_effects_; // TODO: for primitive types this should be marked as invalid. ReferenceTypeInfo reference_type_info_; @@ -3350,15 +3376,15 @@ class HInvokeStaticOrDirect : public HInvoke { }; struct DispatchInfo { - const MethodLoadKind method_load_kind; - const CodePtrLocation code_ptr_location; + MethodLoadKind method_load_kind; + CodePtrLocation code_ptr_location; // The method load data holds // - thread entrypoint offset for kStringInit method if this is a string init invoke. // Note that there are multiple string init methods, each having its own offset. // - the method address for kDirectAddress // - the dex cache arrays offset for kDexCachePcRel. - const uint64_t method_load_data; - const uint64_t direct_code_ptr; + uint64_t method_load_data; + uint64_t direct_code_ptr; }; HInvokeStaticOrDirect(ArenaAllocator* arena, @@ -3387,6 +3413,10 @@ class HInvokeStaticOrDirect : public HInvoke { target_method_(target_method), dispatch_info_(dispatch_info) {} + void SetDispatchInfo(const DispatchInfo& dispatch_info) { + dispatch_info_ = dispatch_info; + } + bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const OVERRIDE { // We access the method via the dex cache so we can't do an implicit null check. // TODO: for intrinsics we can generate implicit null checks. @@ -3401,11 +3431,13 @@ class HInvokeStaticOrDirect : public HInvoke { MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; } CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; } bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; } - bool NeedsDexCache() const OVERRIDE; + bool NeedsDexCacheOfDeclaringClass() const OVERRIDE; bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; } uint32_t GetCurrentMethodInputIndex() const { return GetNumberOfArguments(); } bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; } - bool HasPcRelDexCache() const { return GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative; } + bool HasPcRelDexCache() const { + return GetMethodLoadKind() == MethodLoadKind::kDexCachePcRelative; + } bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; } MethodReference GetTargetMethod() const { return target_method_; } @@ -4059,24 +4091,31 @@ class HXor : public HBinaryOperation { // the calling convention. class HParameterValue : public HExpression<0> { public: - HParameterValue(uint8_t index, + HParameterValue(const DexFile& dex_file, + uint16_t type_index, + uint8_t index, Primitive::Type parameter_type, bool is_this = false) : HExpression(parameter_type, SideEffects::None(), kNoDexPc), + dex_file_(dex_file), + type_index_(type_index), index_(index), is_this_(is_this), can_be_null_(!is_this) {} + const DexFile& GetDexFile() const { return dex_file_; } + uint16_t GetTypeIndex() const { return type_index_; } uint8_t GetIndex() const { return index_; } + bool IsThis() const { return is_this_; } bool CanBeNull() const OVERRIDE { return can_be_null_; } void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; } - bool IsThis() const { return is_this_; } - DECLARE_INSTRUCTION(ParameterValue); private: + const DexFile& dex_file_; + const uint16_t type_index_; // The index of this parameter in the parameters list. Must be less // than HGraph::number_of_in_vregs_. const uint8_t index_; @@ -4158,7 +4197,7 @@ class HTypeConversion : public HExpression<1> { Primitive::Type GetInputType() const { return GetInput()->GetType(); } Primitive::Type GetResultType() const { return GetType(); } - // Required by the x86 and ARM code generators when producing calls + // Required by the x86, ARM, MIPS and MIPS64 code generators when producing calls // to the runtime. bool CanBeMoved() const OVERRIDE { return true; } @@ -4309,18 +4348,21 @@ class FieldInfo : public ValueObject { 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), 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) {} 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_; } @@ -4330,6 +4372,7 @@ class FieldInfo : public ValueObject { 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_; }; @@ -4341,13 +4384,20 @@ class HInstanceFieldGet : public HExpression<1> { 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_type, is_volatile, field_idx, dex_file, dex_cache) { + : HExpression(field_type, + SideEffects::FieldReadOfType(field_type, is_volatile), + dex_pc), + field_info_(field_offset, + field_type, + is_volatile, + field_idx, + declaring_class_def_index, + dex_file, + dex_cache) { SetRawInputAt(0, value); } @@ -4387,12 +4437,19 @@ class HInstanceFieldSet : public HTemplateInstruction<2> { 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_type, is_volatile, field_idx, dex_file, dex_cache), + : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), + dex_pc), + field_info_(field_offset, + field_type, + is_volatile, + field_idx, + declaring_class_def_index, + dex_file, + dex_cache), value_can_be_null_(true) { SetRawInputAt(0, object); SetRawInputAt(1, value); @@ -4424,8 +4481,11 @@ class HArrayGet : public HExpression<2> { HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type, - uint32_t dex_pc) - : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) { + uint32_t dex_pc, + SideEffects additional_side_effects = SideEffects::None()) + : HExpression(type, + SideEffects::ArrayReadOfType(type).Union(additional_side_effects), + dex_pc) { SetRawInputAt(0, array); SetRawInputAt(1, index); } @@ -4460,10 +4520,13 @@ class HArraySet : public HTemplateInstruction<3> { HInstruction* index, HInstruction* value, Primitive::Type expected_component_type, - uint32_t dex_pc) + uint32_t dex_pc, + SideEffects additional_side_effects = SideEffects::None()) : HTemplateInstruction( SideEffects::ArrayWriteOfType(expected_component_type).Union( - SideEffectsForArchRuntimeCalls(value->GetType())), dex_pc), + SideEffectsForArchRuntimeCalls(value->GetType())).Union( + additional_side_effects), + dex_pc), expected_component_type_(expected_component_type), needs_type_check_(value->GetType() == Primitive::kPrimNot), value_can_be_null_(true), @@ -4518,6 +4581,10 @@ class HArraySet : public HTemplateInstruction<3> { : expected_component_type_; } + Primitive::Type GetRawExpectedComponentType() const { + return expected_component_type_; + } + static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) { return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None(); } @@ -4576,6 +4643,7 @@ class HBoundsCheck : public HExpression<2> { bool CanThrow() const OVERRIDE { return true; } + HInstruction* GetIndex() const { return InputAt(0); } DECLARE_INSTRUCTION(BoundsCheck); @@ -4711,7 +4779,7 @@ class HLoadClass : public HExpression<1> { const DexFile& GetDexFile() { return dex_file_; } - bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; } + bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return !is_referrers_class_; } static SideEffects SideEffectsForArchRuntimeCalls() { return SideEffects::CanTriggerGC(); @@ -4753,7 +4821,7 @@ class HLoadString : public HExpression<1> { // TODO: Can we deopt or debug when we resolve a string? bool NeedsEnvironment() const OVERRIDE { return false; } - bool NeedsDexCache() const OVERRIDE { return true; } + bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return true; } bool CanBeNull() const OVERRIDE { return false; } static SideEffects SideEffectsForArchRuntimeCalls() { @@ -4807,13 +4875,20 @@ class HStaticFieldGet : public HExpression<1> { 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_type, is_volatile, field_idx, dex_file, dex_cache) { + : HExpression(field_type, + SideEffects::FieldReadOfType(field_type, is_volatile), + dex_pc), + field_info_(field_offset, + field_type, + is_volatile, + field_idx, + declaring_class_def_index, + dex_file, + dex_cache) { SetRawInputAt(0, cls); } @@ -4850,12 +4925,19 @@ class HStaticFieldSet : public HTemplateInstruction<2> { 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_type, is_volatile, field_idx, dex_file, dex_cache), + : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), + dex_pc), + field_info_(field_offset, + field_type, + is_volatile, + field_idx, + declaring_class_def_index, + dex_file, + dex_cache), value_can_be_null_(true) { SetRawInputAt(0, cls); SetRawInputAt(1, value); @@ -5389,6 +5471,9 @@ class HParallelMove : public HTemplateInstruction<0> { } // namespace art +#ifdef ART_ENABLE_CODEGEN_arm64 +#include "nodes_arm64.h" +#endif #ifdef ART_ENABLE_CODEGEN_x86 #include "nodes_x86.h" #endif |