Add support to indicate whether intrinsics require a dex cache

A structural change to indicate whether a given intrinsic requires access
to a dex cache.  I updated the needs_environment_ field to indicate
whether an HInvoke needs an environment or a dex cache, and if an HInvoke
represents an intrisified method, we utilize this field to determine if
the HInvoke needs a dex cache.

Bug: 21481923
Change-Id: I9dd25a385e1a1397603da6c4c43f6c1aea511b32
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7e49199..851dd4f 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2931,7 +2931,7 @@
 };
 
 enum class Intrinsics {
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) k ## Name,
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache) k ## Name,
 #include "intrinsics_list.h"
   kNone,
   INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -2940,9 +2940,9 @@
 };
 std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
 
-enum IntrinsicNeedsEnvironment {
-  kNoEnvironment,        // Intrinsic does not require an environment.
-  kNeedsEnvironment      // Intrinsic requires an environment.
+enum IntrinsicNeedsEnvironmentOrCache {
+  kNoEnvironmentOrCache,        // Intrinsic does not require an environment or dex cache.
+  kNeedsEnvironmentOrCache      // Intrinsic requires an environment or requires a dex cache.
 };
 
 class HInvoke : public HInstruction {
@@ -2951,7 +2951,9 @@
 
   // Runtime needs to walk the stack, so Dex -> Dex calls need to
   // know their environment.
-  bool NeedsEnvironment() const OVERRIDE { return needs_environment_ == kNeedsEnvironment; }
+  bool NeedsEnvironment() const OVERRIDE {
+    return needs_environment_or_cache_ == kNeedsEnvironmentOrCache;
+  }
 
   void SetArgumentAt(size_t index, HInstruction* argument) {
     SetRawInputAt(index, argument);
@@ -2976,9 +2978,9 @@
     return intrinsic_;
   }
 
-  void SetIntrinsic(Intrinsics intrinsic, IntrinsicNeedsEnvironment needs_environment) {
+  void SetIntrinsic(Intrinsics intrinsic, IntrinsicNeedsEnvironmentOrCache needs_env_or_cache) {
     intrinsic_ = intrinsic;
-    needs_environment_ = needs_environment;
+    needs_environment_or_cache_ = needs_env_or_cache;
   }
 
   bool IsFromInlinedInvoke() const {
@@ -3006,7 +3008,7 @@
       dex_method_index_(dex_method_index),
       original_invoke_type_(original_invoke_type),
       intrinsic_(Intrinsics::kNone),
-      needs_environment_(kNeedsEnvironment) {
+      needs_environment_or_cache_(kNeedsEnvironmentOrCache) {
     uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
     inputs_.SetSize(number_of_inputs);
   }
@@ -3023,7 +3025,7 @@
   const uint32_t dex_method_index_;
   const InvokeType original_invoke_type_;
   Intrinsics intrinsic_;
-  IntrinsicNeedsEnvironment needs_environment_;
+  IntrinsicNeedsEnvironmentOrCache needs_environment_or_cache_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(HInvoke);
@@ -3148,7 +3150,10 @@
   MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
   CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
   bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
-  bool NeedsDexCache() const OVERRIDE { return !IsRecursive() && !IsStringInit(); }
+  bool NeedsDexCache() const OVERRIDE {
+    if (intrinsic_ != Intrinsics::kNone) { return needs_environment_or_cache_; }
+    return !IsRecursive() && !IsStringInit();
+  }
   bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
   uint32_t GetCurrentMethodInputIndex() const { return GetNumberOfArguments(); }
   bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }