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
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index e8c94dd..8f2f253 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 @@
// 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 23d47c3..ca0a8e8 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -2009,6 +2009,7 @@
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 d74d5d2..d14d264 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -45,11 +45,23 @@
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 @@
// 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 @@
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 @@
<< " 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 50e2e43..d103caf 100644
--- a/compiler/optimizing/intrinsics_arm64.h
+++ b/compiler/optimizing/intrinsics_arm64.h
@@ -48,7 +48,7 @@
#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 @@
#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 fd86866..7dcb524 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.h
+++ b/compiler/optimizing/intrinsics_arm_vixl.h
@@ -37,7 +37,7 @@
#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 @@
#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 8160c05..43068c0 100644
--- a/compiler/optimizing/intrinsics_riscv64.h
+++ b/compiler/optimizing/intrinsics_riscv64.h
@@ -42,7 +42,7 @@
#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 @@
#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 289a3c3..565a92a 100644
--- a/compiler/optimizing/intrinsics_x86.h
+++ b/compiler/optimizing/intrinsics_x86.h
@@ -40,7 +40,7 @@
#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 @@
#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 4a76c5c..704fa9b 100644
--- a/compiler/optimizing/intrinsics_x86_64.h
+++ b/compiler/optimizing/intrinsics_x86_64.h
@@ -40,7 +40,7 @@
#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 @@
#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 d931c26..d6fa39f 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -83,49 +83,23 @@
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) \
- 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") \
+// 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(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") \
@@ -134,6 +108,50 @@
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(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(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(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(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(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(ShortReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
+ 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(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 ae602ec..b005cd0 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,