Use intrinsic codegen for compiling intrinsic methods.

When compiling an intrinsic method, generate a graph that
invokes the same method and try to compile it. If the call
is actually intrinsified (or simplified to other HIR) and
yields a leaf method, use the result of this compilation
attempt, otherwise compile the actual code or JNI stub.

Note that CodeGenerator::CreateThrowingSlowPathLocations()
actually marks the locations as kNoCall if the throw is not
in a catch block, thus considering some throwing methods
(for example, String.charAt()) as leaf methods.

We would ideally want to use the intrinsic codegen for all
intrinsics that do not generate a slow-path call to the
default implementation. Relying on the leaf method is
suboptimal as we're missing out on methods that do other
types of calls, for example runtime calls. This shall be
fixed in a subsequent CL.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 67717501
Change-Id: I640fda7c22d4ff494b5ff77ebec3b7f5f75af652
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 892bc59..acdce26 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -22,6 +22,8 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
+#include "base/bit_field.h"
+#include "base/bit_utils.h"
 
 namespace art {
 
@@ -44,7 +46,7 @@
   virtual ~CompiledCode();
 
   InstructionSet GetInstructionSet() const {
-    return instruction_set_;
+    return GetPackedField<InstructionSetField>();
   }
 
   ArrayRef<const uint8_t> GetQuickCode() const;
@@ -68,6 +70,11 @@
   static const void* CodePointer(const void* code_pointer, InstructionSet instruction_set);
 
  protected:
+  static constexpr size_t kInstructionSetFieldSize =
+      MinimumBitsToStore(static_cast<size_t>(InstructionSet::kLast));
+  static constexpr size_t kNumberOfCompiledCodePackedBits = kInstructionSetFieldSize;
+  static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte;
+
   template <typename T>
   static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array);
 
@@ -75,13 +82,26 @@
     return compiler_driver_;
   }
 
+  template <typename BitFieldType>
+  typename BitFieldType::value_type GetPackedField() const {
+    return BitFieldType::Decode(packed_fields_);
+  }
+
+  template <typename BitFieldType>
+  void SetPackedField(typename BitFieldType::value_type value) {
+    DCHECK(IsUint<BitFieldType::size>(static_cast<uintptr_t>(value)));
+    packed_fields_ = BitFieldType::Update(value, packed_fields_);
+  }
+
  private:
+  using InstructionSetField = BitField<InstructionSet, 0u, kInstructionSetFieldSize>;
+
   CompilerDriver* const compiler_driver_;
 
-  const InstructionSet instruction_set_;
-
-  // Used to store the PIC code for Quick.
+  // Used to store the compiled code.
   const LengthPrefixedArray<uint8_t>* const quick_code_;
+
+  uint32_t packed_fields_;
 };
 
 class CompiledMethod FINAL : public CompiledCode {
@@ -116,6 +136,18 @@
 
   static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m);
 
+  bool IsIntrinsic() const {
+    return GetPackedField<IsIntrinsicField>();
+  }
+
+  // Marks the compiled method as being generated using an intrinsic codegen.
+  // Such methods have no relationships to their code items.
+  // This affects debug information generated at link time.
+  void MarkAsIntrinsic() {
+    DCHECK(!IsIntrinsic());
+    SetPackedField<IsIntrinsicField>(/* value */ true);
+  }
+
   size_t GetFrameSizeInBytes() const {
     return frame_size_in_bytes_;
   }
@@ -137,6 +169,14 @@
   ArrayRef<const linker::LinkerPatch> GetPatches() const;
 
  private:
+  static constexpr size_t kIsIntrinsicLsb = kNumberOfCompiledCodePackedBits;
+  static constexpr size_t kIsIntrinsicSize = 1u;
+  static constexpr size_t kNumberOfCompiledMethodPackedBits = kIsIntrinsicLsb + kIsIntrinsicSize;
+  static_assert(kNumberOfCompiledMethodPackedBits <= CompiledCode::kMaxNumberOfPackedBits,
+                "Too many packed fields.");
+
+  using IsIntrinsicField = BitField<bool, kIsIntrinsicLsb, kIsIntrinsicSize>;
+
   // For quick code, the size of the activation used by the code.
   const size_t frame_size_in_bytes_;
   // For quick code, a bit mask describing spilled GPR callee-save registers.