Remove intialized static storage from dex cache.

The initialized static storage array is used by compiled code to determine if
for a sget/sput class initialization is necessary. The compiled code typically
doesn't require this test as the class is pre-initialized or the class being
accessed is the same as the current method.

Change-Id: Icbc45e692b3d0ac61e559e69edb6c9b29439e571
diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
index b206a25..6423cd7 100644
--- a/compiler/llvm/gbc_expander.cc
+++ b/compiler/llvm/gbc_expander.cc
@@ -199,8 +199,6 @@
   //----------------------------------------------------------------------------
   llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
 
-  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
-
   llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
 
   llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
@@ -287,8 +285,6 @@
 
   llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
 
-  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
-
   llvm::Value*
   Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
 
@@ -720,16 +716,6 @@
 }
 
 llvm::Value*
-GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
-  llvm::Value* static_storage_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheInitializedStaticStorageOffset());
-
-  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
-
-  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
-}
-
-llvm::Value*
 GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
   llvm::Value* resolved_type_dex_cache_addr =
     EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedTypesOffset());
@@ -1213,17 +1199,6 @@
 }
 
 llvm::Value*
-GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
-  uint32_t type_idx =
-    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
-
-  llvm::Value* storage_field_addr =
-    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
-
-  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
-}
-
-llvm::Value*
 GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
   uint32_t callee_method_idx =
     llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
@@ -1837,21 +1812,31 @@
   llvm::BasicBlock* block_load_static =
     CreateBasicBlockWithDexPC(dex_pc, "load_static");
 
+  llvm::BasicBlock* block_check_init = CreateBasicBlockWithDexPC(dex_pc, "init");
   llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
   // Load static storage from dex cache
-  llvm::Value* storage_field_addr =
-    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+  llvm::Value* storage_field_addr = EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
   llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 
-  llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+  // Test: Is the class resolved?
+  llvm::Value* equal_null = irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
 
-  // Test: Is the static storage of this class initialized?
-  llvm::Value* equal_null =
-    irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
+  irb_.CreateCondBr(equal_null, block_load_static, block_check_init, kUnlikely);
 
-  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
+  // storage_object_addr != null, so check if its initialized.
+  irb_.SetInsertPoint(block_check_init);
+
+  llvm::Value* class_status =
+      irb_.LoadFromObjectOffset(storage_object_addr,
+                                art::mirror::Class::StatusOffset().Int32Value(),
+                                irb_.getJIntTy(), kTBAAHeapInstance);
+
+  llvm::Value* is_not_initialized =
+      irb_.CreateICmpULT(class_status, irb_.getInt32(art::mirror::Class::kStatusInitialized));
+
+  irb_.CreateCondBr(is_not_initialized, block_load_static, block_cont, kUnlikely);
 
   // Failback routine to load the class object
   irb_.SetInsertPoint(block_load_static);
@@ -1880,9 +1865,8 @@
 
   llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
 
-  phi->addIncoming(storage_object_addr, block_original);
+  phi->addIncoming(storage_object_addr, block_check_init);
   phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
-
   return phi;
 }
 
@@ -1895,10 +1879,11 @@
   int ssb_index;
   bool is_referrers_class;
   bool is_volatile;
+  bool is_initialized;
 
   bool is_fast_path = driver_->ComputeStaticFieldInfo(
     field_idx, dex_compilation_unit_, false,
-    &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+    &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
 
   llvm::Value* static_field_value;
 
@@ -1979,10 +1964,11 @@
   int ssb_index;
   bool is_referrers_class;
   bool is_volatile;
+  bool is_initialized;
 
   bool is_fast_path = driver_->ComputeStaticFieldInfo(
     field_idx, dex_compilation_unit_, true,
-    &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+    &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
 
   if (!is_fast_path) {
     llvm::Function* runtime_func;
@@ -3360,9 +3346,6 @@
     case IntrinsicHelper::LoadDeclaringClassSSB: {
       return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
     }
-    case IntrinsicHelper::LoadClassSSBFromDexCache: {
-      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
-    }
     case IntrinsicHelper::InitializeAndLoadClassSSB: {
       return ExpandToRuntime(InitializeStaticStorage, call_inst);
     }