Corresponding CL of thread flags for portable.

Change-Id: I6ad0c6159115e0d8879e0d9d674d760cd48f29c9
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 7ea12f9..af2fcc4 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -53,6 +53,7 @@
 ; Exception
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+declare %JavaObject* @art_get_and_clear_exception(%JavaObject*)
 declare void @art_throw_div_zero_from_code()
 declare void @art_throw_array_bounds_from_code(i32, i32)
 declare void @art_throw_no_such_method_from_code(i32)
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index bcca08d..8750c0b 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -161,8 +161,6 @@
 
   void Expand_MarkGCCard(llvm::CallInst& call_inst);
 
-  llvm::Value* Expand_GetException();
-
   llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
 
   llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
@@ -775,21 +773,6 @@
   return;
 }
 
-llvm::Value* GBCExpanderPass::Expand_GetException() {
-  // Get thread-local exception field address
-  llvm::Value* exception_object_addr =
-    irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ExceptionOffset().Int32Value(),
-                                            irb_.getJObjectTy(),
-                                            kTBAAJRuntime);
-
-  // Set thread-local exception field address to NULL
-  irb_.Runtime().EmitStoreToThreadOffset(art::Thread::ExceptionOffset().Int32Value(),
-                                         irb_.getJNull(),
-                                         kTBAAJRuntime);
-
-  return exception_object_addr;
-}
-
 llvm::Value*
 GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
   uint32_t string_idx =
@@ -2721,7 +2704,7 @@
       return NULL;
     }
     case IntrinsicHelper::GetException: {
-      return Expand_GetException();
+      return irb_.Runtime().EmitGetAndClearException();
     }
     case IntrinsicHelper::IsExceptionPending: {
       return irb_.Runtime().EmitIsExceptionPending();
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index aac4cd8..872701d 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -463,6 +463,17 @@
 AttrListPtr func_art_pop_shadow_frame_from_code_PAL;
 func_art_pop_shadow_frame_from_code->setAttributes(func_art_pop_shadow_frame_from_code_PAL);
 
+Function* func_art_get_and_clear_exception = mod->getFunction("art_get_and_clear_exception");
+if (!func_art_get_and_clear_exception) {
+func_art_get_and_clear_exception = Function::Create(
+ /*Type=*/FuncTy_4,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_get_and_clear_exception", mod); // (external, no body)
+func_art_get_and_clear_exception->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_get_and_clear_exception_PAL;
+func_art_get_and_clear_exception->setAttributes(func_art_get_and_clear_exception_PAL);
+
 Function* func_art_throw_div_zero_from_code = mod->getFunction("art_throw_div_zero_from_code");
 if (!func_art_throw_div_zero_from_code) {
 func_art_throw_div_zero_from_code = Function::Create(
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 61fffbe..ca9cbdf 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1257,16 +1257,7 @@
 
   DecodedInstruction dec_insn(insn);
 
-  // Get thread-local exception field address
-  llvm::Value* exception_object_addr =
-    irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
-                                            irb_.getJObjectTy(),
-                                            kTBAAJRuntime);
-
-  // Set thread-local exception field address to NULL
-  irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
-                                         irb_.getJNull(),
-                                         kTBAAJRuntime);
+  llvm::Value* exception_object_addr = irb_.Runtime().EmitGetAndClearException();
 
   // Keep the exception object in the Dalvik register
   EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, exception_object_addr);
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 6be113d..76665f7 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -133,7 +133,12 @@
 }
 
 
-/* Check */
+/* Exception */
+
+llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
+  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
+}
 
 llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
   Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
@@ -143,12 +148,15 @@
   return irb_.CreateIsNotNull(exception);
 }
 
+
+/* Suspend */
+
 void RuntimeSupportBuilder::EmitTestSuspend() {
   Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
-  Value* suspend_count = EmitLoadFromThreadOffset(Thread::SuspendCountOffset().Int32Value(),
-                                                  irb_.getJIntTy(),
+  Value* suspend_count = EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
+                                                  irb_.getInt16Ty(),
                                                   kTBAARuntimeInfo);
-  Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getJInt(0));
+  Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
 
   Function* parent_func = irb_.GetInsertBlock()->getParent();
   BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", parent_func);
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index 05b9e53..ab076bb 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -56,8 +56,11 @@
                                                llvm::Value* method, uint32_t size);
   virtual void EmitPopShadowFrame(llvm::Value* old_shadow_frame);
 
-  /* Check */
+  /* Exception */
+  virtual llvm::Value* EmitGetAndClearException();
   virtual llvm::Value* EmitIsExceptionPending();
+
+  /* Suspend */
   virtual void EmitTestSuspend();
 
   /* Monitor */
diff --git a/src/compiler_llvm/runtime_support_builder_arm.cc b/src/compiler_llvm/runtime_support_builder_arm.cc
index 16ecff4..7a166ad 100644
--- a/src/compiler_llvm/runtime_support_builder_arm.cc
+++ b/src/compiler_llvm/runtime_support_builder_arm.cc
@@ -30,6 +30,24 @@
 
 using namespace llvm;
 
+namespace {
+
+char LDRSTRSuffixByType(art::compiler_llvm::IRBuilder& irb, llvm::Type* type) {
+  int width = type->isPointerTy() ?
+              irb.getSizeOfPtrEquivInt()*8 :
+              llvm::cast<IntegerType>(type)->getBitWidth();
+  switch (width) {
+    case 8:  return 'b';
+    case 16: return 'h';
+    case 32: return ' ';
+    default:
+      LOG(FATAL) << "Unsupported width: " << width;
+      return ' ';
+  }
+}
+
+} // namespace
+
 namespace art {
 namespace compiler_llvm {
 
@@ -48,7 +66,9 @@
                                                                 TBAASpecialType s_ty) {
   FunctionType* func_ty = FunctionType::get(/*Result=*/type,
                                             /*isVarArg=*/false);
-  std::string inline_asm(StringPrintf("ldr $0, [r9, #%d]", static_cast<int>(offset)));
+  std::string inline_asm(StringPrintf("ldr%c $0, [r9, #%d]",
+                                      LDRSTRSuffixByType(irb_, type),
+                                      static_cast<int>(offset)));
   InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "=r", true);
   CallInst* result = irb_.CreateCall(func);
   result->setOnlyReadsMemory();
@@ -61,7 +81,9 @@
   FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                             /*Params=*/value->getType(),
                                             /*isVarArg=*/false);
-  std::string inline_asm(StringPrintf("str $0, [r9, #%d]", static_cast<int>(offset)));
+  std::string inline_asm(StringPrintf("str%c $0, [r9, #%d]",
+                                      LDRSTRSuffixByType(irb_, value->getType()),
+                                      static_cast<int>(offset)));
   InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "r", true);
   CallInst* call_inst = irb_.CreateCall(func, value);
   irb_.SetTBAA(call_inst, s_ty);
diff --git a/src/compiler_llvm/runtime_support_builder_x86.cc b/src/compiler_llvm/runtime_support_builder_x86.cc
index a927fc5..cf38594 100644
--- a/src/compiler_llvm/runtime_support_builder_x86.cc
+++ b/src/compiler_llvm/runtime_support_builder_x86.cc
@@ -37,7 +37,7 @@
 
 llvm::Value* RuntimeSupportBuilderX86::EmitGetCurrentThread() {
   Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
-  std::string inline_asm(StringPrintf("movl %%fs:%d, $0", Thread::SelfOffset().Int32Value()));
+  std::string inline_asm(StringPrintf("mov %%fs:%d, $0", Thread::SelfOffset().Int32Value()));
   InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), inline_asm, "=r", false);
   CallInst* thread = irb_.CreateCall(func);
   thread->setDoesNotAccessMemory();
@@ -49,7 +49,7 @@
                                                                 TBAASpecialType s_ty) {
   FunctionType* func_ty = FunctionType::get(/*Result=*/type,
                                             /*isVarArg=*/false);
-  std::string inline_asm(StringPrintf("movl %%fs:%d, $0", static_cast<int>(offset)));
+  std::string inline_asm(StringPrintf("mov %%fs:%d, $0", static_cast<int>(offset)));
   InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "=r", true);
   CallInst* result = irb_.CreateCall(func);
   result->setOnlyReadsMemory();
@@ -62,7 +62,7 @@
   FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                             /*Params=*/value->getType(),
                                             /*isVarArg=*/false);
-  std::string inline_asm(StringPrintf("movl $0, %%fs:%d", static_cast<int>(offset)));
+  std::string inline_asm(StringPrintf("mov $0, %%fs:%d", static_cast<int>(offset)));
   InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "r", true);
   CallInst* call_inst = irb_.CreateCall(func, value);
   irb_.SetTBAA(call_inst, s_ty);
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 5b94edc..b27754e 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -59,6 +59,7 @@
   V(GetObjectInstance, art_get_obj_instance_from_code) \
   V(InitializeStaticStorage, art_initialize_static_storage_from_code) \
   V(FillArrayData, art_fill_array_data_from_code) \
+  V(GetAndClearException, art_get_and_clear_exception) \
   V(IsExceptionPending, art_is_exception_pending_from_code) \
   V(FindCatchBlock, art_find_catch_block_from_code) \
   V(MarkGCCard, art_mark_gc_card_from_code) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index cbbccb6..3bb4ae5 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -167,6 +167,14 @@
   }
 }
 
+void* art_get_and_clear_exception(Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(self->IsExceptionPending());
+  Throwable* exception = self->GetException();
+  self->ClearException();
+  return exception;
+}
+
 int32_t art_find_catch_block_from_code(AbstractMethod* current_method,
                                        uint32_t ti_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {