From 57b81ecbe74138992dd447251e94ed06cd5eb802 Mon Sep 17 00:00:00 2001 From: agicsaki Date: Tue, 11 Aug 2015 17:39:37 -0700 Subject: [PATCH] Add support to indicate whether intrinsics require an environment A structural change to indicate whether a given intrinsic requires access to an environment. I added a field to HInvoke objects to indicate if they need an environment whose default value is true and is only updated if an intrinsic is marked as not requiring an environment. At this point there is no functional change, as all intrinsics are marked as requiring an environment. This change adds the structure for future inliner work which will allow us to inline more intrinsified calls. Change-Id: I2930e3cef7b785384bf95b95a542d34af442f3b9 --- compiler/optimizing/intrinsics.cc | 22 +++++- compiler/optimizing/intrinsics.h | 4 +- compiler/optimizing/intrinsics_arm.h | 4 +- compiler/optimizing/intrinsics_arm64.h | 4 +- compiler/optimizing/intrinsics_list.h | 135 ++++++++++++++++---------------- compiler/optimizing/intrinsics_x86.h | 4 +- compiler/optimizing/intrinsics_x86_64.h | 4 +- compiler/optimizing/nodes.h | 16 +++- 8 files changed, 108 insertions(+), 85 deletions(-) diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 55e964ea8..a3cb14422 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -31,7 +31,7 @@ static inline InvokeType GetIntrinsicInvokeType(Intrinsics i) { switch (i) { case Intrinsics::kNone: return kInterface; // Non-sensical for intrinsic. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ case Intrinsics::k ## Name: \ return IsStatic; #include "intrinsics_list.h" @@ -42,7 +42,21 @@ INTRINSICS_LIST(OPTIMIZING_INTRINSICS) return kInterface; } - +// Function that returns whether an intrinsic needs an environment or not. +static inline IntrinsicNeedsEnvironment IntrinsicNeedsEnvironment(Intrinsics i) { + switch (i) { + case Intrinsics::kNone: + return kNeedsEnvironment; // Non-sensical for intrinsic. +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ + case Intrinsics::k ## Name: \ + return NeedsEnvironment; +#include "intrinsics_list.h" +INTRINSICS_LIST(OPTIMIZING_INTRINSICS) +#undef INTRINSICS_LIST +#undef OPTIMIZING_INTRINSICS + } + return kNeedsEnvironment; +} static Primitive::Type GetType(uint64_t data, bool is_op_size) { if (is_op_size) { @@ -357,7 +371,7 @@ void IntrinsicsRecognizer::Run() { << intrinsic << " for " << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile()); } else { - invoke->SetIntrinsic(intrinsic); + invoke->SetIntrinsic(intrinsic, IntrinsicNeedsEnvironment(intrinsic)); } } } @@ -371,7 +385,7 @@ std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) { case Intrinsics::kNone: os << "None"; break; -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ case Intrinsics::k ## Name: \ os << # Name; \ break; diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 90449828a..d1a17b6de 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -54,7 +54,7 @@ class IntrinsicVisitor : public ValueObject { switch (invoke->GetIntrinsic()) { case Intrinsics::kNone: return; -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ case Intrinsics::k ## Name: \ Visit ## Name(invoke); \ return; @@ -69,7 +69,7 @@ INTRINSICS_LIST(OPTIMIZING_INTRINSICS) // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ } #include "intrinsics_list.h" diff --git a/compiler/optimizing/intrinsics_arm.h b/compiler/optimizing/intrinsics_arm.h index 8bfb7d468..c21e9c0d2 100644 --- a/compiler/optimizing/intrinsics_arm.h +++ b/compiler/optimizing/intrinsics_arm.h @@ -39,7 +39,7 @@ class IntrinsicLocationsBuilderARM FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) @@ -65,7 +65,7 @@ class IntrinsicCodeGeneratorARM FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h index ba2188983..ebaf5e595 100644 --- a/compiler/optimizing/intrinsics_arm64.h +++ b/compiler/optimizing/intrinsics_arm64.h @@ -41,7 +41,7 @@ class IntrinsicLocationsBuilderARM64 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) @@ -65,7 +65,7 @@ class IntrinsicCodeGeneratorARM64 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h index d28c5a3f2..1c01805ab 100644 --- a/compiler/optimizing/intrinsics_list.h +++ b/compiler/optimizing/intrinsics_list.h @@ -18,75 +18,76 @@ #define ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ // All intrinsics supported by the optimizing compiler. Format is name, then whether it is expected -// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual). +// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an +// environment. #define INTRINSICS_LIST(V) \ - V(DoubleDoubleToRawLongBits, kStatic) \ - V(DoubleLongBitsToDouble, kStatic) \ - V(FloatFloatToRawIntBits, kStatic) \ - V(FloatIntBitsToFloat, kStatic) \ - V(IntegerReverse, kStatic) \ - V(IntegerReverseBytes, kStatic) \ - V(IntegerNumberOfLeadingZeros, kStatic) \ - V(LongReverse, kStatic) \ - V(LongReverseBytes, kStatic) \ - V(LongNumberOfLeadingZeros, kStatic) \ - V(ShortReverseBytes, kStatic) \ - V(MathAbsDouble, kStatic) \ - V(MathAbsFloat, kStatic) \ - V(MathAbsLong, kStatic) \ - V(MathAbsInt, kStatic) \ - V(MathMinDoubleDouble, kStatic) \ - V(MathMinFloatFloat, kStatic) \ - V(MathMinLongLong, kStatic) \ - V(MathMinIntInt, kStatic) \ - V(MathMaxDoubleDouble, kStatic) \ - V(MathMaxFloatFloat, kStatic) \ - V(MathMaxLongLong, kStatic) \ - V(MathMaxIntInt, kStatic) \ - V(MathSqrt, kStatic) \ - V(MathCeil, kStatic) \ - V(MathFloor, kStatic) \ - V(MathRint, kStatic) \ - V(MathRoundDouble, kStatic) \ - V(MathRoundFloat, kStatic) \ - V(SystemArrayCopyChar, kStatic) \ - V(ThreadCurrentThread, kStatic) \ - V(MemoryPeekByte, kStatic) \ - V(MemoryPeekIntNative, kStatic) \ - V(MemoryPeekLongNative, kStatic) \ - V(MemoryPeekShortNative, kStatic) \ - V(MemoryPokeByte, kStatic) \ - V(MemoryPokeIntNative, kStatic) \ - V(MemoryPokeLongNative, kStatic) \ - V(MemoryPokeShortNative, kStatic) \ - V(StringCharAt, kDirect) \ - V(StringCompareTo, kDirect) \ - V(StringGetCharsNoCheck, kDirect) \ - V(StringIndexOf, kDirect) \ - V(StringIndexOfAfter, kDirect) \ - V(StringNewStringFromBytes, kStatic) \ - V(StringNewStringFromChars, kStatic) \ - V(StringNewStringFromString, kStatic) \ - V(UnsafeCASInt, kDirect) \ - V(UnsafeCASLong, kDirect) \ - V(UnsafeCASObject, kDirect) \ - V(UnsafeGet, kDirect) \ - V(UnsafeGetVolatile, kDirect) \ - V(UnsafeGetObject, kDirect) \ - V(UnsafeGetObjectVolatile, kDirect) \ - V(UnsafeGetLong, kDirect) \ - V(UnsafeGetLongVolatile, kDirect) \ - V(UnsafePut, kDirect) \ - V(UnsafePutOrdered, kDirect) \ - V(UnsafePutVolatile, kDirect) \ - V(UnsafePutObject, kDirect) \ - V(UnsafePutObjectOrdered, kDirect) \ - V(UnsafePutObjectVolatile, kDirect) \ - V(UnsafePutLong, kDirect) \ - V(UnsafePutLongOrdered, kDirect) \ - V(UnsafePutLongVolatile, kDirect) \ - V(ReferenceGetReferent, kDirect) + V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironment) \ + V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironment) \ + V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironment) \ + V(FloatIntBitsToFloat, kStatic, kNeedsEnvironment) \ + V(IntegerReverse, kStatic, kNeedsEnvironment) \ + V(IntegerReverseBytes, kStatic, kNeedsEnvironment) \ + V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironment) \ + V(LongReverse, kStatic, kNeedsEnvironment) \ + V(LongReverseBytes, kStatic, kNeedsEnvironment) \ + V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironment) \ + V(ShortReverseBytes, kStatic, kNeedsEnvironment) \ + V(MathAbsDouble, kStatic, kNeedsEnvironment) \ + V(MathAbsFloat, kStatic, kNeedsEnvironment) \ + V(MathAbsLong, kStatic, kNeedsEnvironment) \ + V(MathAbsInt, kStatic, kNeedsEnvironment) \ + V(MathMinDoubleDouble, kStatic, kNeedsEnvironment) \ + V(MathMinFloatFloat, kStatic, kNeedsEnvironment) \ + V(MathMinLongLong, kStatic, kNeedsEnvironment) \ + V(MathMinIntInt, kStatic, kNeedsEnvironment) \ + V(MathMaxDoubleDouble, kStatic, kNeedsEnvironment) \ + V(MathMaxFloatFloat, kStatic, kNeedsEnvironment) \ + V(MathMaxLongLong, kStatic, kNeedsEnvironment) \ + V(MathMaxIntInt, kStatic, kNeedsEnvironment) \ + V(MathSqrt, kStatic, kNeedsEnvironment) \ + V(MathCeil, kStatic, kNeedsEnvironment) \ + V(MathFloor, kStatic, kNeedsEnvironment) \ + V(MathRint, kStatic, kNeedsEnvironment) \ + V(MathRoundDouble, kStatic, kNeedsEnvironment) \ + V(MathRoundFloat, kStatic, kNeedsEnvironment) \ + V(SystemArrayCopyChar, kStatic, kNeedsEnvironment) \ + V(ThreadCurrentThread, kStatic, kNeedsEnvironment) \ + V(MemoryPeekByte, kStatic, kNeedsEnvironment) \ + V(MemoryPeekIntNative, kStatic, kNeedsEnvironment) \ + V(MemoryPeekLongNative, kStatic, kNeedsEnvironment) \ + V(MemoryPeekShortNative, kStatic, kNeedsEnvironment) \ + V(MemoryPokeByte, kStatic, kNeedsEnvironment) \ + V(MemoryPokeIntNative, kStatic, kNeedsEnvironment) \ + V(MemoryPokeLongNative, kStatic, kNeedsEnvironment) \ + V(MemoryPokeShortNative, kStatic, kNeedsEnvironment) \ + V(StringCharAt, kDirect, kNeedsEnvironment) \ + V(StringCompareTo, kDirect, kNeedsEnvironment) \ + V(StringGetCharsNoCheck, kDirect, kNeedsEnvironment) \ + V(StringIndexOf, kDirect, kNeedsEnvironment) \ + V(StringIndexOfAfter, kDirect, kNeedsEnvironment) \ + V(StringNewStringFromBytes, kStatic, kNeedsEnvironment) \ + V(StringNewStringFromChars, kStatic, kNeedsEnvironment) \ + V(StringNewStringFromString, kStatic, kNeedsEnvironment) \ + V(UnsafeCASInt, kDirect, kNeedsEnvironment) \ + V(UnsafeCASLong, kDirect, kNeedsEnvironment) \ + V(UnsafeCASObject, kDirect, kNeedsEnvironment) \ + V(UnsafeGet, kDirect, kNeedsEnvironment) \ + V(UnsafeGetVolatile, kDirect, kNeedsEnvironment) \ + V(UnsafeGetObject, kDirect, kNeedsEnvironment) \ + V(UnsafeGetObjectVolatile, kDirect, kNeedsEnvironment) \ + V(UnsafeGetLong, kDirect, kNeedsEnvironment) \ + V(UnsafeGetLongVolatile, kDirect, kNeedsEnvironment) \ + V(UnsafePut, kDirect, kNeedsEnvironment) \ + V(UnsafePutOrdered, kDirect, kNeedsEnvironment) \ + V(UnsafePutVolatile, kDirect, kNeedsEnvironment) \ + V(UnsafePutObject, kDirect, kNeedsEnvironment) \ + V(UnsafePutObjectOrdered, kDirect, kNeedsEnvironment) \ + V(UnsafePutObjectVolatile, kDirect, kNeedsEnvironment) \ + V(UnsafePutLong, kDirect, kNeedsEnvironment) \ + V(UnsafePutLongOrdered, kDirect, kNeedsEnvironment) \ + V(UnsafePutLongVolatile, kDirect, kNeedsEnvironment) \ + V(ReferenceGetReferent, kDirect, kNeedsEnvironment) #endif // ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ #undef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ // #define is only for lint. diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h index 4292ec7b9..ac68f3990 100644 --- a/compiler/optimizing/intrinsics_x86.h +++ b/compiler/optimizing/intrinsics_x86.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderX86 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) @@ -61,7 +61,7 @@ class IntrinsicCodeGeneratorX86 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h index 0e0e72c1f..17293af4d 100644 --- a/compiler/optimizing/intrinsics_x86_64.h +++ b/compiler/optimizing/intrinsics_x86_64.h @@ -36,7 +36,7 @@ class IntrinsicLocationsBuilderX86_64 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) @@ -61,7 +61,7 @@ class IntrinsicCodeGeneratorX86_64 FINAL : public IntrinsicVisitor { // Define visitor methods. -#define OPTIMIZING_INTRINSICS(Name, IsStatic) \ +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ void Visit ## Name(HInvoke* invoke) OVERRIDE; #include "intrinsics_list.h" INTRINSICS_LIST(OPTIMIZING_INTRINSICS) diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index dba923324..e6df42962 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2890,7 +2890,7 @@ class HDoubleConstant : public HConstant { }; enum class Intrinsics { -#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name, +#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) k ## Name, #include "intrinsics_list.h" kNone, INTRINSICS_LIST(OPTIMIZING_INTRINSICS) @@ -2899,13 +2899,18 @@ enum class Intrinsics { }; std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic); +enum IntrinsicNeedsEnvironment { + kNoEnvironment, // Intrinsic does not require an environment. + kNeedsEnvironment // Intrinsic requires an environment. +}; + class HInvoke : public HInstruction { public: size_t InputCount() const OVERRIDE { return inputs_.Size(); } // Runtime needs to walk the stack, so Dex -> Dex calls need to // know their environment. - bool NeedsEnvironment() const OVERRIDE { return true; } + bool NeedsEnvironment() const OVERRIDE { return needs_environment_ == kNeedsEnvironment; } void SetArgumentAt(size_t index, HInstruction* argument) { SetRawInputAt(index, argument); @@ -2930,8 +2935,9 @@ class HInvoke : public HInstruction { return intrinsic_; } - void SetIntrinsic(Intrinsics intrinsic) { + void SetIntrinsic(Intrinsics intrinsic, IntrinsicNeedsEnvironment needs_environment) { intrinsic_ = intrinsic; + needs_environment_ = needs_environment; } bool IsFromInlinedInvoke() const { @@ -2958,7 +2964,8 @@ class HInvoke : public HInstruction { dex_pc_(dex_pc), dex_method_index_(dex_method_index), original_invoke_type_(original_invoke_type), - intrinsic_(Intrinsics::kNone) { + intrinsic_(Intrinsics::kNone), + needs_environment_(kNeedsEnvironment) { uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs; inputs_.SetSize(number_of_inputs); } @@ -2975,6 +2982,7 @@ class HInvoke : public HInstruction { const uint32_t dex_method_index_; const InvokeType original_invoke_type_; Intrinsics intrinsic_; + IntrinsicNeedsEnvironment needs_environment_; private: DISALLOW_COPY_AND_ASSIGN(HInvoke); -- 2.11.0