diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r-- | compiler/optimizing/nodes.h | 103 |
1 files changed, 79 insertions, 24 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 68f1a2406a..c70674b0ad 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -26,9 +26,11 @@ #include "base/arena_object.h" #include "base/array_ref.h" #include "base/iteration_range.h" +#include "base/mutex.h" #include "base/quasi_atomic.h" #include "base/stl_util.h" #include "base/transform_array_ref.h" +#include "art_method.h" #include "data_type.h" #include "deoptimization_kind.h" #include "dex/dex_file.h" @@ -128,6 +130,7 @@ enum GraphAnalysisResult { kAnalysisInvalidBytecode, kAnalysisFailThrowCatchLoop, kAnalysisFailAmbiguousArrayOp, + kAnalysisFailIrreducibleLoopAndStringInit, kAnalysisSuccess, }; @@ -314,6 +317,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { uint32_t method_idx, InstructionSet instruction_set, InvokeType invoke_type = kInvalidInvokeType, + bool dead_reference_safe = false, bool debuggable = false, bool osr = false, int start_instruction_id = 0) @@ -333,6 +337,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { has_simd_(false), has_loops_(false), has_irreducible_loops_(false), + dead_reference_safe_(dead_reference_safe), debuggable_(debuggable), current_instruction_id_(start_instruction_id), dex_file_(dex_file), @@ -523,6 +528,12 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { has_bounds_checks_ = value; } + // Is the code known to be robust against eliminating dead references + // and the effects of early finalization? + bool IsDeadReferenceSafe() const { return dead_reference_safe_; } + + void MarkDeadReferenceUnsafe() { dead_reference_safe_ = false; } + bool IsDebuggable() const { return debuggable_; } // Returns a constant of the given type and value. If it does not exist @@ -701,6 +712,14 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { // so there might be false positives. bool has_irreducible_loops_; + // Is the code known to be robust against eliminating dead references + // and the effects of early finalization? If false, dead reference variables + // are kept if they might be visible to the garbage collector. + // Currently this means that the class was declared to be dead-reference-safe, + // the method accesses no reachability-sensitive fields or data, and the same + // is true for any methods that were inlined into the current one. + bool dead_reference_safe_; + // Indicates whether the graph should be compiled in a way that // ensures full debuggability. If false, we can apply more // aggressive optimizations that may limit the level of debugging. @@ -892,7 +911,7 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { explicit TryCatchInformation(const HTryBoundary& try_entry) : try_entry_(&try_entry), catch_dex_file_(nullptr), - catch_type_index_(DexFile::kDexNoIndex16) { + catch_type_index_(dex::TypeIndex::Invalid()) { DCHECK(try_entry_ != nullptr); } @@ -911,9 +930,9 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { bool IsCatchBlock() const { return catch_dex_file_ != nullptr; } - bool IsCatchAllTypeIndex() const { + bool IsValidTypeIndex() const { DCHECK(IsCatchBlock()); - return !catch_type_index_.IsValid(); + return catch_type_index_.IsValid(); } dex::TypeIndex GetCatchTypeIndex() const { @@ -926,6 +945,10 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { return *catch_dex_file_; } + void SetInvalidTypeIndex() { + catch_type_index_ = dex::TypeIndex::Invalid(); + } + private: // One of possibly several TryBoundary instructions entering the block's try. // Only set for try blocks. @@ -933,7 +956,7 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { // Exception type information. Only set for catch blocks. const DexFile* catch_dex_file_; - const dex::TypeIndex catch_type_index_; + dex::TypeIndex catch_type_index_; }; static constexpr size_t kNoLifetime = -1; @@ -1453,6 +1476,7 @@ class HLoopInformationOutwardIterator : public ValueObject { M(VecSetScalars, VecOperation) \ M(VecMultiplyAccumulate, VecOperation) \ M(VecSADAccumulate, VecOperation) \ + M(VecDotProd, VecOperation) \ M(VecLoad, VecMemoryOperation) \ M(VecStore, VecMemoryOperation) \ @@ -1494,6 +1518,14 @@ class HLoopInformationOutwardIterator : public ValueObject { M(X86PackedSwitch, Instruction) #endif +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) +#define FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M) \ + M(X86AndNot, Instruction) \ + M(X86MaskOrResetLeastSetBit, Instruction) +#else +#define FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M) +#endif + #define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M) #define FOR_EACH_CONCRETE_INSTRUCTION(M) \ @@ -1504,7 +1536,8 @@ class HLoopInformationOutwardIterator : public ValueObject { 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) + FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M) \ + FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M) #define FOR_EACH_ABSTRACT_INSTRUCTION(M) \ M(Condition, BinaryOperation) \ @@ -3229,7 +3262,7 @@ class HDeoptimize final : public HVariableInputSizeInstruction { SideEffects::All(), dex_pc, allocator, - /* number_of_inputs */ 1, + /* number_of_inputs= */ 1, kArenaAllocMisc) { SetPackedFlag<kFieldCanBeMoved>(false); SetPackedField<DeoptimizeKindField>(kind); @@ -3254,7 +3287,7 @@ class HDeoptimize final : public HVariableInputSizeInstruction { SideEffects::CanTriggerGC(), dex_pc, allocator, - /* number_of_inputs */ 2, + /* number_of_inputs= */ 2, kArenaAllocMisc) { SetPackedFlag<kFieldCanBeMoved>(true); SetPackedField<DeoptimizeKindField>(kind); @@ -4322,7 +4355,7 @@ class HInvoke : public HVariableInputSizeInstruction { bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; } ArtMethod* GetResolvedMethod() const { return resolved_method_; } - void SetResolvedMethod(ArtMethod* method) { resolved_method_ = method; } + void SetResolvedMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); DECLARE_ABSTRACT_INSTRUCTION(Invoke); @@ -4354,12 +4387,14 @@ class HInvoke : public HVariableInputSizeInstruction { number_of_arguments + number_of_other_inputs, kArenaAllocInvokeInputs), number_of_arguments_(number_of_arguments), - resolved_method_(resolved_method), dex_method_index_(dex_method_index), intrinsic_(Intrinsics::kNone), intrinsic_optimizations_(0) { SetPackedField<InvokeTypeField>(invoke_type); SetPackedFlag<kFlagCanThrow>(true); + // Check mutator lock, constructors lack annotalysis support. + Locks::mutator_lock_->AssertNotExclusiveHeld(Thread::Current()); + SetResolvedMethod(resolved_method); } DEFAULT_COPY_CONSTRUCTOR(Invoke); @@ -4384,7 +4419,7 @@ class HInvokeUnresolved final : public HInvoke { : HInvoke(kInvokeUnresolved, allocator, number_of_arguments, - 0u /* number_of_other_inputs */, + /* number_of_other_inputs= */ 0u, return_type, dex_pc, dex_method_index, @@ -4410,7 +4445,7 @@ class HInvokePolymorphic final : public HInvoke { : HInvoke(kInvokePolymorphic, allocator, number_of_arguments, - 0u /* number_of_other_inputs */, + /* number_of_other_inputs= */ 0u, return_type, dex_pc, dex_method_index, @@ -4436,11 +4471,11 @@ class HInvokeCustom final : public HInvoke { : HInvoke(kInvokeCustom, allocator, number_of_arguments, - /* number_of_other_inputs */ 0u, + /* number_of_other_inputs= */ 0u, return_type, dex_pc, - /* dex_method_index */ dex::kDexNoIndex, - /* resolved_method */ nullptr, + /* dex_method_index= */ dex::kDexNoIndex, + /* resolved_method= */ nullptr, kStatic), call_site_index_(call_site_index) { } @@ -4533,8 +4568,7 @@ class HInvokeStaticOrDirect final : public 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 - // one other if the method is a string factory. + // potentially one other if the clinit check is explicit. (NeedsCurrentMethodInput(dispatch_info.method_load_kind) ? 1u : 0u) + (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u), return_type, @@ -4845,10 +4879,11 @@ class HNeg final : public HUnaryOperation { class HNewArray final : public HExpression<2> { public: - HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc) + HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc, size_t component_size_shift) : HExpression(kNewArray, DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) { SetRawInputAt(0, cls); SetRawInputAt(1, length); + SetPackedField<ComponentSizeShiftField>(component_size_shift); } bool IsClonable() const override { return true; } @@ -4870,10 +4905,23 @@ class HNewArray final : public HExpression<2> { return InputAt(1); } + size_t GetComponentSizeShift() { + return GetPackedField<ComponentSizeShiftField>(); + } + DECLARE_INSTRUCTION(NewArray); protected: DEFAULT_COPY_CONSTRUCTOR(NewArray); + + private: + static constexpr size_t kFieldComponentSizeShift = kNumberOfGenericPackedBits; + static constexpr size_t kFieldComponentSizeShiftSize = MinimumBitsToStore(3u); + static constexpr size_t kNumberOfNewArrayPackedBits = + kFieldComponentSizeShift + kFieldComponentSizeShiftSize; + static_assert(kNumberOfNewArrayPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); + using ComponentSizeShiftField = + BitField<size_t, kFieldComponentSizeShift, kFieldComponentSizeShift>; }; class HAdd final : public HBinaryOperation { @@ -5656,6 +5704,10 @@ class HTypeConversion final : public HExpression<1> { bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override { return true; } + // Return whether the conversion is implicit. This includes conversion to the same type. + bool IsImplicitConversion() const { + return DataType::IsTypeConversionImplicit(GetInputType(), GetResultType()); + } // Try to statically evaluate the conversion and return a HConstant // containing the result. If the input cannot be converted, return nullptr. @@ -5862,7 +5914,7 @@ class HArrayGet final : public HExpression<2> { type, SideEffects::ArrayReadOfType(type), dex_pc, - /* is_string_char_at */ false) { + /* is_string_char_at= */ false) { } HArrayGet(HInstruction* array, @@ -6136,6 +6188,9 @@ class HBoundsCheck final : public HExpression<2> { private: static constexpr size_t kFlagIsStringCharAt = kNumberOfGenericPackedBits; + static constexpr size_t kNumberOfBoundsCheckPackedBits = kFlagIsStringCharAt + 1; + static_assert(kNumberOfBoundsCheckPackedBits <= HInstruction::kMaxNumberOfPackedBits, + "Too many packed fields."); }; class HSuspendCheck final : public HExpression<0> { @@ -6301,7 +6356,7 @@ class HLoadClass final : public HInstruction { ReferenceTypeInfo GetLoadedClassRTI() { if (GetPackedFlag<kFlagValidLoadedClassRTI>()) { // Note: The is_exact flag from the return value should not be used. - return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact */ true); + return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact= */ true); } else { return ReferenceTypeInfo::CreateInvalid(); } @@ -7054,7 +7109,7 @@ class HTypeCheckInstruction : public HVariableInputSizeInstruction { side_effects, dex_pc, allocator, - /* number_of_inputs */ check_kind == TypeCheckKind::kBitstringCheck ? 4u : 2u, + /* number_of_inputs= */ check_kind == TypeCheckKind::kBitstringCheck ? 4u : 2u, kArenaAllocTypeCheckInputs), klass_(klass) { SetPackedField<TypeCheckKindField>(check_kind); @@ -7110,7 +7165,7 @@ class HTypeCheckInstruction : public HVariableInputSizeInstruction { ReferenceTypeInfo GetTargetClassRTI() { if (GetPackedFlag<kFlagValidTargetClassRTI>()) { // Note: The is_exact flag from the return value should not be used. - return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact */ true); + return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact= */ true); } else { return ReferenceTypeInfo::CreateInvalid(); } @@ -7377,7 +7432,7 @@ class HMemoryBarrier final : public HExpression<0> { // } // // See also: -// * CompilerDriver::RequiresConstructorBarrier +// * DexCompilationUnit::RequiresConstructorBarrier // * QuasiAtomic::ThreadFenceForConstructor // class HConstructorFence final : public HVariableInputSizeInstruction { @@ -7423,7 +7478,7 @@ class HConstructorFence final : public HVariableInputSizeInstruction { SideEffects::AllReads(), dex_pc, allocator, - /* number_of_inputs */ 1, + /* number_of_inputs= */ 1, kArenaAllocConstructorFenceInputs) { DCHECK(fence_object != nullptr); SetRawInputAt(0, fence_object); @@ -7741,7 +7796,7 @@ class HIntermediateAddress final : public HExpression<2> { #ifdef ART_ENABLE_CODEGEN_mips #include "nodes_mips.h" #endif -#ifdef ART_ENABLE_CODEGEN_x86 +#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) #include "nodes_x86.h" #endif |