Support 32-bit volatiles.

Change-Id: If40ead8e13986d589ac1d1637034e25fc4108189
diff --git a/build/Android.common.mk b/build/Android.common.mk
index b4fb7aa..7a31ceb 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -24,7 +24,7 @@
 	art/src \
 	dalvik/libdex
 
-ART_CFLAGS := \
+art_cflags := \
 	-O2 \
 	-ggdb3 \
 	-Wall \
@@ -35,6 +35,16 @@
 	-fno-align-jumps \
 	-fstrict-aliasing
 
+ART_HOST_CFLAGS := $(art_cflags) -DANDROID_SMP=1
+
+ART_TARGET_CFLAGS := $(art_cflags)
+ifeq ($(TARGET_CPU_SMP),true)
+  ART_TARGET_CFLAGS += -DANDROID_SMP=1
+else
+  ART_TARGET_CFLAGS += -DANDROID_SMP=0
+endif
+
+
 DEX2OAT_SRC_FILES := \
 	src/dex2oat.cc
 
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index 2abb42a..1b2f41d 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -34,7 +34,11 @@
   endif
   LOCAL_MODULE_TAGS := optional
   LOCAL_SRC_FILES := $(2)
-  LOCAL_CFLAGS := $(ART_CFLAGS)
+  ifeq ($(3),target)
+    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
+  else
+    LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+  endif
   ifeq ($(4),debug)
     LOCAL_CFLAGS += -UNDEBUG
   endif
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 974907e..96202eb 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -33,7 +33,11 @@
   else
     LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES)
   endif
-  LOCAL_CFLAGS := $(ART_CFLAGS)
+  ifeq ($(1),target)
+    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
+  else
+    LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+  endif
   ifeq ($(2),debug)
     LOCAL_CFLAGS += -UNDEBUG
   endif
diff --git a/build/Android.libarttest.mk b/build/Android.libarttest.mk
index 9cde3e5..baf37d9 100644
--- a/build/Android.libarttest.mk
+++ b/build/Android.libarttest.mk
@@ -24,10 +24,11 @@
   LOCAL_MODULE := libarttest
   LOCAL_MODULE_TAGS := tests
   LOCAL_SRC_FILES := $(LIBARTTEST_COMMON_SRC_FILES)
-  LOCAL_CFLAGS := $(ART_CFLAGS) -UNDEBUG
   ifeq ($(1),target)
+    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS) -UNDEBUG
     LOCAL_SHARED_LIBRARIES := libdl libstlport
   else
+    LOCAL_CFLAGS := $(ART_HOST_CFLAGS) -UNDEBUG
     LOCAL_LDLIBS := -ldl -lrt
   endif
   ifeq ($(1),target)
diff --git a/build/Android.test.mk b/build/Android.test.mk
index 90fc44a..6c4c858 100644
--- a/build/Android.test.mk
+++ b/build/Android.test.mk
@@ -28,13 +28,14 @@
   LOCAL_MODULE := $(notdir $(basename $(2:%.arm=%)))
   LOCAL_MODULE_TAGS := tests
   LOCAL_SRC_FILES := $(2)
-  LOCAL_CFLAGS := $(ART_CFLAGS) -UNDEBUG
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
   LOCAL_SHARED_LIBRARIES := libarttest libartd
   ifeq ($(1),target)
+    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS) -UNDEBUG
     LOCAL_SHARED_LIBRARIES += libdl libicuuc libicui18n libnativehelper libstlport libz
     LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
   else
+    LOCAL_CFLAGS := $(ART_HOST_CFLAGS) -UNDEBUG
     LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libz-host
     LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_host libgtest_main_host
   endif
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 7e09ccc..8070e8d 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -304,7 +304,7 @@
         rlDest = oatGetDestWide(cUnit, mir, 0, 1);
         RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
 #if ANDROID_SMP != 0
-        if (isVolatile) {
+        if (field->IsVolatile()) {
             oatGenMemBarrier(cUnit, kSY);
         }
 #endif
@@ -367,7 +367,7 @@
         rlDest = oatGetDest(cUnit, mir, 0);
         rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
 #if ANDROID_SMP != 0
-        if (isVolatile) {
+        if (field->IsVolatile()) {
             oatGenMemBarrier(cUnit, kSY);
         }
 #endif
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index db4dd09..a763d6e 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -468,7 +468,7 @@
         storeValue(cUnit, rlDest, rlResult);
     } else {
 #if ANDROID_SMP != 0
-        bool isVolatile = dvmIsVolatileField(fieldPtr);
+        bool isVolatile = fieldPtr->IsVolatile();
 #else
         bool isVolatile = false;
 #endif
@@ -501,7 +501,7 @@
         storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, size);
     } else {
 #if ANDROID_SMP != 0
-        bool isVolatile = dvmIsVolatileField(fieldPtr);
+        bool isVolatile = fieldPtr->IsVolatile();
 #else
         bool isVolatile = false;
 #endif
@@ -539,7 +539,7 @@
         storeValue(cUnit, rlDest, rlResult);
     } else {
 #if ANDROID_SMP != 0
-        bool isVolatile = dvmIsVolatileField(fieldPtr);
+        bool isVolatile = fieldPtr->IsVolatile();
 #else
         bool isVolatile = false;
 #endif
@@ -580,7 +580,7 @@
         storePair(cUnit, r0, rlSrc.lowReg, rlSrc.highReg);
     } else {
 #if ANDROID_SMP != 0
-        bool isVolatile = dvmIsVolatileField(fieldPtr);
+        bool isVolatile = fieldPtr->IsVolatile();
 #else
         bool isVolatile = false;
 #endif
diff --git a/src/object.h b/src/object.h
index 959abcb..ed41494 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1,8 +1,25 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef ART_SRC_OBJECT_H_
 #define ART_SRC_OBJECT_H_
 
+#include <cutils/atomic.h>
+#include <cutils/atomic-inline.h>
+
 #include <vector>
 
 #include "UniquePtr.h"
@@ -362,35 +379,43 @@
 
   uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const {
     Heap::VerifyObject(this);
-    const byte* raw_addr = reinterpret_cast<const byte*>(this) +
-        field_offset.Int32Value();
+    const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
+    const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
     if (is_volatile) {
-      UNIMPLEMENTED(WARNING);
+      return android_atomic_acquire_load(word_addr);
+    } else {
+      return *word_addr;
     }
-    return *reinterpret_cast<const uint32_t*>(raw_addr);
   }
 
   void SetField32(MemberOffset offset, uint32_t new_value, bool is_volatile) {
     Heap::VerifyObject(this);
     byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+    uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr);
     if (is_volatile) {
-      UNIMPLEMENTED(WARNING);
+      /*
+       * TODO: add an android_atomic_synchronization_store() function and
+       * use it in the 32-bit volatile set handlers.  On some platforms we
+       * can use a fast atomic instruction and avoid the barriers.
+       */
+      ANDROID_MEMBAR_STORE();
+      *word_addr = new_value;
+      ANDROID_MEMBAR_FULL();
+    } else {
+      *word_addr = new_value;
     }
-    *reinterpret_cast<uint32_t*>(raw_addr) = new_value;
   }
 
   uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const {
     Heap::VerifyObject(this);
-    const byte* raw_addr = reinterpret_cast<const byte*>(this) +
-        field_offset.Int32Value();
+    const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
     if (is_volatile) {
       UNIMPLEMENTED(WARNING);
     }
     return *reinterpret_cast<const uint64_t*>(raw_addr);
   }
 
-  void SetField64(MemberOffset offset, uint64_t new_value,
-                  bool is_volatile = false) {
+  void SetField64(MemberOffset offset, uint64_t new_value, bool is_volatile) {
     Heap::VerifyObject(this);
     byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
     if (is_volatile) {
@@ -401,25 +426,6 @@
 
  protected:
   // Accessors for non-Java type fields
-  uint16_t GetField16(MemberOffset field_offset, bool is_volatile) const {
-    Heap::VerifyObject(this);
-    const byte* raw_addr = reinterpret_cast<const byte*>(this) +
-        field_offset.Int32Value();
-    if (is_volatile) {
-      UNIMPLEMENTED(WARNING);
-    }
-    return *reinterpret_cast<const uint16_t*>(raw_addr);
-  }
-
-  void SetField16(MemberOffset offset, uint16_t new_value, bool is_volatile) {
-    Heap::VerifyObject(this);
-    byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
-    if (is_volatile) {
-      UNIMPLEMENTED(WARNING);
-    }
-    *reinterpret_cast<uint16_t*>(raw_addr) = new_value;
-  }
-
   template<class T>
   T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const {
     Heap::VerifyObject(this);
@@ -721,7 +727,7 @@
   }
 
   void SetMethodIndex(uint16_t new_method_index) {
-    SetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_),
+    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_),
                new_method_index, false);
   }
 
@@ -748,21 +754,21 @@
   uint16_t NumRegisters() const;
 
   void SetNumRegisters(uint16_t new_num_registers) {
-    SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_),
+    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_),
                new_num_registers, false);
   }
 
   uint16_t NumIns() const;
 
   void SetNumIns(uint16_t new_num_ins) {
-    SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_),
+    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_),
                new_num_ins, false);
   }
 
   uint16_t NumOuts() const;
 
   void SetNumOuts(uint16_t new_num_outs) {
-    SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_),
+    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_),
                new_num_outs, false);
   }
 
@@ -1051,7 +1057,7 @@
 
   uint32_t java_generic_types_are_initialized_;
 
-  // access flags; low 16 bits are defined by spec (could be uint16_t?)
+  // Access flags; low 16 bits are defined by spec.
   uint32_t access_flags_;
 
   // Compiled code associated with this method for callers from managed code.
@@ -1081,7 +1087,7 @@
   //
   // For abstract methods in an interface class, this is the offset
   // of the method in "iftable_->Get(n)->GetMethodArray()".
-  uint32_t method_index_;  // (could be uint16_t)
+  uint32_t method_index_;
 
   // The target native method registered with this method
   const void* native_method_;
@@ -1090,9 +1096,9 @@
   //
   // For a native method, we compute the size of the argument list, and
   // set "insSize" and "registerSize" equal to it.
-  uint32_t num_ins_;  // (could be uint16_t)
-  uint32_t num_outs_;  // (could be uint16_t)
-  uint32_t num_registers_;  // ins + locals  // (could be uint16_t)
+  uint32_t num_ins_;
+  uint32_t num_outs_;
+  uint32_t num_registers_;  // ins + locals
 
   // Method prototype descriptor string (return and argument types).
   uint32_t proto_idx_;
@@ -2598,22 +2604,22 @@
 
 inline uint16_t Method::GetMethodIndex() const {
   DCHECK(GetDeclaringClass()->IsResolved());
-  return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
 }
 
 inline uint16_t Method::NumRegisters() const {
   DCHECK(GetDeclaringClass()->IsLoaded());
-  return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), false);
 }
 
 inline uint16_t Method::NumIns() const {
   DCHECK(GetDeclaringClass()->IsLoaded());
-  return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), false);
 }
 
 inline uint16_t Method::NumOuts() const {
   DCHECK(GetDeclaringClass()->IsLoaded());
-  return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), false);
 }
 
 inline uint32_t Method::GetProtoIdx() const {