diff options
author | 2024-01-17 14:38:07 +0100 | |
---|---|---|
committer | 2024-01-22 10:27:42 +0100 | |
commit | dbf9d9309f3df9c9ac8a9e30277b31ebb2977f4d (patch) | |
tree | 5e5950e962e90410acb6e73a4c53752d9c709ac9 | |
parent | f99be32df8d55405aa70c44899f058e7a842de3e (diff) |
Create list of intrinsics with specialized HIR.
Split the intrinsics list to differentiate intrinsics with
and without HIR. Eliminate unreachable intrinsic functions
for intrinsics with HIR.
Test: m test-art-host-gtest
Test: restrunner.py --host --optimizing
Bug: 319045458
Change-Id: I6144ef6b6ec547c30f2911c41125a1f07f6f6d50
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 60 | ||||
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 72 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_riscv64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.h | 4 | ||||
-rw-r--r-- | runtime/intrinsics_list.h | 85 | ||||
-rw-r--r-- | runtime/oat/image.cc | 4 |
10 files changed, 106 insertions, 136 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index e8c94dd6b4..8f2f25355d 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -27,6 +27,7 @@ #include "base/scoped_arena_containers.h" #include "code_generator.h" #include "handle.h" +#include "intrinsics.h" #include "mirror/class.h" #include "nodes.h" #include "obj_ptr-inl.h" @@ -738,50 +739,21 @@ void GraphChecker::VisitInvoke(HInvoke* invoke) { // Check for intrinsics which should have been replaced by intermediate representation in the // instruction builder. - switch (invoke->GetIntrinsic()) { - case Intrinsics::kIntegerRotateRight: - case Intrinsics::kLongRotateRight: - case Intrinsics::kIntegerRotateLeft: - case Intrinsics::kLongRotateLeft: - case Intrinsics::kIntegerCompare: - case Intrinsics::kLongCompare: - case Intrinsics::kIntegerSignum: - case Intrinsics::kLongSignum: - case Intrinsics::kFloatIsNaN: - case Intrinsics::kDoubleIsNaN: - case Intrinsics::kStringIsEmpty: - case Intrinsics::kUnsafeLoadFence: - case Intrinsics::kUnsafeStoreFence: - case Intrinsics::kUnsafeFullFence: - case Intrinsics::kJdkUnsafeLoadFence: - case Intrinsics::kJdkUnsafeStoreFence: - case Intrinsics::kJdkUnsafeFullFence: - case Intrinsics::kVarHandleFullFence: - case Intrinsics::kVarHandleAcquireFence: - case Intrinsics::kVarHandleReleaseFence: - case Intrinsics::kVarHandleLoadLoadFence: - case Intrinsics::kVarHandleStoreStoreFence: - case Intrinsics::kMathMinIntInt: - case Intrinsics::kMathMinLongLong: - case Intrinsics::kMathMinFloatFloat: - case Intrinsics::kMathMinDoubleDouble: - case Intrinsics::kMathMaxIntInt: - case Intrinsics::kMathMaxLongLong: - case Intrinsics::kMathMaxFloatFloat: - case Intrinsics::kMathMaxDoubleDouble: - case Intrinsics::kMathAbsInt: - case Intrinsics::kMathAbsLong: - case Intrinsics::kMathAbsFloat: - case Intrinsics::kMathAbsDouble: - AddError( - StringPrintf("The graph contains an instrinsic which should have been replaced in the " - "instruction builder: %s:%d in block %d.", - invoke->DebugName(), - invoke->GetId(), - invoke->GetBlock()->GetBlockId())); - break; - default: - break; + if (IsIntrinsicWithSpecializedHir(invoke->GetIntrinsic()) && + // FIXME: The inliner can currently create graphs with any of the intrinsics with HIR. + // However, we are able to compensate for `StringCharAt` and `StringLength` in the + // `HInstructionSimplifier`, so we're allowing these two intrinsics for now, preserving + // the old behavior. Besides fixing the bug, we should also clean up the simplifier + // and remove `SimplifyStringCharAt` and `SimplifyStringLength`. Bug: 319045458 + invoke->GetIntrinsic() != Intrinsics::kStringCharAt && + invoke->GetIntrinsic() != Intrinsics::kStringLength) { + AddError( + StringPrintf("The graph contains the instrinsic %d which should have been replaced in the " + "instruction builder: %s:%d in block %d.", + enum_cast<int>(invoke->GetIntrinsic()), + invoke->DebugName(), + invoke->GetId(), + invoke->GetBlock()->GetBlockId())); } } diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 23d47c3857..ca0a8e81af 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -2009,6 +2009,7 @@ bool HInstructionBuilder::BuildSimpleIntrinsic(ArtMethod* method, break; default: // We do not have intermediate representation for other intrinsics. + DCHECK(!IsIntrinsicWithSpecializedHir(intrinsic)); return false; } DCHECK(instruction != nullptr); diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index d74d5d2a40..d14d264204 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -45,11 +45,23 @@ class IntrinsicVisitor : public ValueObject { switch (invoke->GetIntrinsic()) { case Intrinsics::kNone: return; + +#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \ + case Intrinsics::k ## Name: + ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR) +#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR + // Note: clang++ can optimize this `switch` to a range check and a virtual dispatch + // with indexed load from the vtable using an adjusted `invoke->GetIntrinsic()` + // as the index. However, a non-empty `case` causes clang++ to produce much worse + // code, so we want to limit this check to debug builds only. + DCHECK(false) << "Unexpected intrinsic with HIR: " << invoke->GetIntrinsic(); + return; + #define OPTIMIZING_INTRINSICS(Name, ...) \ case Intrinsics::k ## Name: \ Visit ## Name(invoke); \ return; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Do not put a default case. That way the compiler will complain if we missed a case. @@ -58,10 +70,10 @@ class IntrinsicVisitor : public ValueObject { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, ...) \ - virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) {} - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) -#undef OPTIMIZING_INTRINSICS +#define DECLARE_VISIT_INTRINSIC(Name, ...) \ + virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) = 0; + ART_INTRINSICS_WITH_HINVOKE_LIST(DECLARE_VISIT_INTRINSIC) +#undef DECLARE_VISIT_INTRINSIC static void MoveArguments(HInvoke* invoke, CodeGenerator* codegen, @@ -153,6 +165,18 @@ class IntrinsicVisitor : public ValueObject { DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); }; +static inline bool IsIntrinsicWithSpecializedHir(Intrinsics intrinsic) { + switch (intrinsic) { +#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \ + case Intrinsics::k ## Name: + ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR) +#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR + return true; + default: + return false; + } +} + #define GENERIC_OPTIMIZATION(name, bit) \ public: \ void Set##name() { SetBit(k##name); } \ @@ -278,44 +302,8 @@ void IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ << " should have been converted to HIR"; \ } #define UNREACHABLE_INTRINSICS(Arch) \ -UNREACHABLE_INTRINSIC(Arch, MathMinIntInt) \ -UNREACHABLE_INTRINSIC(Arch, MathMinLongLong) \ -UNREACHABLE_INTRINSIC(Arch, MathMinFloatFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathMinDoubleDouble) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxIntInt) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxLongLong) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxFloatFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathMaxDoubleDouble) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsInt) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsLong) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsFloat) \ -UNREACHABLE_INTRINSIC(Arch, MathAbsDouble) \ UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ -UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ -UNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ -UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ -UNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ -UNREACHABLE_INTRINSIC(Arch, LongCompare) \ -UNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ -UNREACHABLE_INTRINSIC(Arch, LongSignum) \ -UNREACHABLE_INTRINSIC(Arch, StringCharAt) \ -UNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ -UNREACHABLE_INTRINSIC(Arch, StringLength) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ -UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeStoreFence) \ -UNREACHABLE_INTRINSIC(Arch, JdkUnsafeFullFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleFullFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence) \ -UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence) +UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) template <typename IntrinsicLocationsBuilder, typename Codegenerator> bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h index 50e2e43f5f..d103cafdf7 100644 --- a/compiler/optimizing/intrinsics_arm64.h +++ b/compiler/optimizing/intrinsics_arm64.h @@ -48,7 +48,7 @@ class IntrinsicLocationsBuilderARM64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -71,7 +71,7 @@ class IntrinsicCodeGeneratorARM64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_arm_vixl.h b/compiler/optimizing/intrinsics_arm_vixl.h index fd86866d4e..7dcb52403b 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.h +++ b/compiler/optimizing/intrinsics_arm_vixl.h @@ -37,7 +37,7 @@ class IntrinsicLocationsBuilderARMVIXL final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -62,7 +62,7 @@ class IntrinsicCodeGeneratorARMVIXL final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_riscv64.h b/compiler/optimizing/intrinsics_riscv64.h index 8160c054ee..43068c04c2 100644 --- a/compiler/optimizing/intrinsics_riscv64.h +++ b/compiler/optimizing/intrinsics_riscv64.h @@ -42,7 +42,7 @@ class IntrinsicLocationsBuilderRISCV64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, ...) \ void Visit##Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -65,7 +65,7 @@ class IntrinsicCodeGeneratorRISCV64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, ...) \ void Visit##Name(HInvoke* invoke); - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h index 289a3c342c..565a92a11b 100644 --- a/compiler/optimizing/intrinsics_x86.h +++ b/compiler/optimizing/intrinsics_x86.h @@ -40,7 +40,7 @@ class IntrinsicLocationsBuilderX86 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -63,7 +63,7 @@ class IntrinsicCodeGeneratorX86 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h index 4a76c5c8ec..704fa9be0d 100644 --- a/compiler/optimizing/intrinsics_x86_64.h +++ b/compiler/optimizing/intrinsics_x86_64.h @@ -40,7 +40,7 @@ class IntrinsicLocationsBuilderX86_64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether @@ -63,7 +63,7 @@ class IntrinsicCodeGeneratorX86_64 final : public IntrinsicVisitor { #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \ void Visit ## Name(HInvoke* invoke) override; - ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS) + ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS) #undef OPTIMIZING_INTRINSICS private: diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h index d931c26b94..d6fa39f1fc 100644 --- a/runtime/intrinsics_list.h +++ b/runtime/intrinsics_list.h @@ -83,57 +83,75 @@ V(VarHandleWeakCompareAndSetPlain, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetPlain", "([Ljava/lang/Object;)Z") \ V(VarHandleWeakCompareAndSetRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetRelease", "([Ljava/lang/Object;)Z") -// The complete list of intrinsics. -#define ART_INTRINSICS_LIST(V) \ +// Intrinics that have specialized intermediate representation in the compiler +// and therefore should never be recorded in a generic `HInvoke`. +#define ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(V) \ + V(DoubleIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \ + V(FloatIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \ + V(IntegerCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \ + V(IntegerRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \ + V(IntegerRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \ + V(IntegerSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \ + V(LongCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \ + V(LongRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \ + V(LongRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \ + V(LongSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \ + V(MathAbsDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \ + V(MathAbsFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \ + V(MathAbsLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \ + V(MathAbsInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \ + V(MathMinDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \ + V(MathMinFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \ + V(MathMinLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \ + V(MathMinIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \ + V(MathMaxDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \ + V(MathMaxFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \ + V(MathMaxLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \ + V(MathMaxIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \ + V(StringCharAt, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \ + V(StringIsEmpty, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \ + V(StringLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \ + V(UnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \ + V(UnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \ + V(UnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \ + V(JdkUnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "loadFence", "()V") \ + V(JdkUnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "storeFence", "()V") \ + V(JdkUnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "fullFence", "()V") \ + V(VarHandleFullFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \ + V(VarHandleAcquireFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \ + V(VarHandleReleaseFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \ + V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \ + V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") + +// Intrinics without specialized intermediate representation in the compiler, using `HInvoke`. +#define ART_INTRINSICS_WITH_HINVOKE_LIST(V) \ V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \ V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \ V(DoubleIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \ - V(DoubleIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \ V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \ V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \ V(FloatFloatToIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \ V(FloatIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \ - V(FloatIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \ V(FloatIntBitsToFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \ V(IntegerReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \ V(IntegerReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \ V(IntegerBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \ - V(IntegerCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \ V(IntegerDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Integer;", "divideUnsigned", "(II)I") \ V(IntegerHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \ V(IntegerLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \ V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \ V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \ - V(IntegerRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \ - V(IntegerRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \ - V(IntegerSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \ V(LongReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \ V(LongReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \ V(LongBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \ - V(LongCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \ V(LongDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Long;", "divideUnsigned", "(JJ)J") \ V(LongHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \ V(LongLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \ V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \ V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \ - V(LongRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \ - V(LongRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \ - V(LongSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \ V(ShortReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \ - V(MathAbsDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \ - V(MathAbsFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \ - V(MathAbsLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \ - V(MathAbsInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \ V(MathFmaDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(DDD)D") \ V(MathFmaFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(FFF)F") \ - V(MathMinDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \ - V(MathMinFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \ - V(MathMinLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \ - V(MathMinIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \ - V(MathMaxDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \ - V(MathMaxFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \ - V(MathMaxLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \ - V(MathMaxIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \ V(MathCos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \ V(MathSin, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \ V(MathAcos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \ @@ -184,7 +202,6 @@ V(FP16LessEquals, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "lessEquals", "(SS)Z") \ V(FP16Min, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "min", "(SS)S") \ V(FP16Max, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "max", "(SS)S") \ - V(StringCharAt, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \ V(StringCompareTo, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \ V(StringEquals, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \ V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \ @@ -192,8 +209,6 @@ V(StringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(II)I") \ V(StringStringIndexOf, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I") \ V(StringStringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;I)I") \ - V(StringIsEmpty, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \ - V(StringLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \ V(StringNewStringFromBytes, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \ V(StringNewStringFromChars, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \ V(StringNewStringFromString, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \ @@ -237,9 +252,6 @@ V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \ V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \ V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \ - V(UnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \ - V(UnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \ - V(UnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \ V(JdkUnsafeCASInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \ V(JdkUnsafeCASLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \ V(JdkUnsafeCASObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ @@ -274,17 +286,9 @@ V(JdkUnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \ V(JdkUnsafeGetAndSetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \ V(JdkUnsafeGetAndSetReference, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetReference", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \ - V(JdkUnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "loadFence", "()V") \ - V(JdkUnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "storeFence", "()V") \ - V(JdkUnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "fullFence", "()V") \ V(ReferenceGetReferent, kDirect, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \ V(ReferenceRefersTo, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "refersTo", "(Ljava/lang/Object;)Z") \ V(ThreadInterrupted, kStatic, kNeedsEnvironment, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") \ - V(VarHandleFullFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \ - V(VarHandleAcquireFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \ - V(VarHandleReleaseFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \ - V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \ - V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \ V(ReachabilityFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \ V(CRC32Update, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "update", "(II)I") \ V(CRC32UpdateBytes, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/util/zip/CRC32;", "updateBytes", "(I[BII)I") \ @@ -295,4 +299,9 @@ V(IntegerValueOf, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "valueOf", "(I)Ljava/lang/Integer;") \ ART_SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V) +// The complete list of intrinsics. +#define ART_INTRINSICS_LIST(V) \ + ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(V) \ + ART_INTRINSICS_WITH_HINVOKE_LIST(V) + #endif // ART_RUNTIME_INTRINSICS_LIST_H_ diff --git a/runtime/oat/image.cc b/runtime/oat/image.cc index ae602ece05..b005cd0586 100644 --- a/runtime/oat/image.cc +++ b/runtime/oat/image.cc @@ -34,8 +34,8 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -// Last change: Add DexCacheSection. -const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '8', '\0' }; +// Last change: Split intrinsics list - with and without HIR. +const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '9', '\0' }; ImageHeader::ImageHeader(uint32_t image_reservation_size, uint32_t component_count, |