Generates barrier in constructor.

Bug: 8209406

We need to generate a memory barrier at the end of constructor where non static
final fields are initialized.
This introduces the new greenland intrinsic "ConstructorBarrier" to be handled
by the Quick and the Portable compilers.

Change-Id: Id2eb0af61f689581a192d20742a248726adf7f9b
diff --git a/src/compiler/dex/portable/mir_to_gbc.cc b/src/compiler/dex/portable/mir_to_gbc.cc
index 4cae511..66efd64 100644
--- a/src/compiler/dex/portable/mir_to_gbc.cc
+++ b/src/compiler/dex/portable/mir_to_gbc.cc
@@ -816,6 +816,12 @@
   DefineValue(cu, res, rl_dest.orig_sreg);
 }
 
+static void EmitConstructorBarrier(CompilationUnit* cu) {
+  llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(
+      compiler_llvm::IntrinsicHelper::ConstructorBarrier);
+  cu->irb->CreateCall(intr);
+}
+
 /*
  * Target-independent code generation.  Use only high-level
  * load/store utilities here, or target-dependent genXX() handlers
@@ -1025,6 +1031,12 @@
       break;
 
     case Instruction::RETURN_VOID: {
+        if (((cu->access_flags & kAccConstructor) != 0) &&
+            cu->compiler->RequiresConstructorBarrier(Thread::Current(),
+                                                     cu->dex_file,
+                                                     cu->class_def_idx)) {
+          EmitConstructorBarrier(cu);
+        }
         if (!(cu->attrs & METHOD_IS_LEAF)) {
           EmitSuspendCheck(cu);
         }
@@ -2892,6 +2904,11 @@
   }
 }
 
+static void CvtConstructorBarrier(CompilationUnit* cu) {
+  Codegen* cg = cu->cg.get();
+  cg->GenMemBarrier(cu, kStoreStore);
+}
+
 /* Look up the RegLocation associated with a Value.  Must already be defined */
 static RegLocation ValToLoc(CompilationUnit* cu, llvm::Value* val)
 {
@@ -3308,6 +3325,10 @@
                    next_bb = target_bb;
                 }
                 break;
+              case compiler_llvm::IntrinsicHelper::ConstructorBarrier: {
+                CvtConstructorBarrier(cu);
+                break;
+              }
 
               default:
                 LOG(FATAL) << "Unexpected intrinsic " << cu->intrinsic_helper->GetName(id);
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 086d29d..4c9b31c 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -3588,6 +3588,12 @@
       return call_inst.getArgOperand(0);
     }
 
+    //==- Constructor barrier-----------------------------------------------==//
+    case IntrinsicHelper::ConstructorBarrier: {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+      return NULL;
+    }
+
     //==- Unknown Cases ----------------------------------------------------==//
     case IntrinsicHelper::MaxIntrinsicId:
     case IntrinsicHelper::UnknownId:
diff --git a/src/compiler_llvm/intrinsic_func_list.def b/src/compiler_llvm/intrinsic_func_list.def
index b3ea3f9..92537ba 100644
--- a/src/compiler_llvm/intrinsic_func_list.def
+++ b/src/compiler_llvm/intrinsic_func_list.def
@@ -1768,6 +1768,16 @@
                           kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
+//----------------------------------------------------------------------------
+// Memory barrier
+//----------------------------------------------------------------------------
+// void constructor_barrier()
+_EVAL_DEF_INTRINSICS_FUNC(ConstructorBarrier,
+                          art_portable_constructor_barrier,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
 // Clean up all internal used macros
 #undef _EXPAND_ARG0
 #undef _EXPAND_ARG1
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 85506e4..e722c68 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -18,6 +18,7 @@
 #define ART_SRC_COMPILER_LLVM_IR_BUILDER_H_
 
 #include "backend_types.h"
+#include "compiler/dex/compiler_enums.h"
 #include "intrinsic_helper.h"
 #include "md_builder.h"
 #include "runtime_support_builder.h"
@@ -94,6 +95,15 @@
     return inst;
   }
 
+  //--------------------------------------------------------------------------
+  // Extend memory barrier
+  //--------------------------------------------------------------------------
+  void CreateMemoryBarrier(MemBarrierKind barrier_kind) {
+#if ANDROID_SMP
+    // TODO: select atomic ordering according to given barrier kind.
+    CreateFence(llvm::SequentiallyConsistent);
+#endif
+  }
 
   //--------------------------------------------------------------------------
   // TBAA
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index ccda55c..ae8bb4a 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -897,4 +897,12 @@
   return 0;
 }
 
+//----------------------------------------------------------------------------
+// Memory barrier
+//----------------------------------------------------------------------------
+
+void art_portable_constructor_barrier() {
+  LOG(FATAL) << "Implemented by IRBuilder.";
+}
+
 }  // extern "C"