diff a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp
@@ -765,91 +765,209 @@
   __ mov(NOT_LP64(rax) LP64_ONLY(c_rarg1), array);
   __ jump(ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry));
   __ bind(skip);
 }
 
+#if INCLUDE_TSAN
+
+TemplateTable::TsanMemoryReleaseAcquireFunction TemplateTable::tsan_release_acquire_method(
+    TsanMemoryReadWriteFunction tsan_function) {
+  if (tsan_function == SharedRuntime::tsan_read1
+      || tsan_function == SharedRuntime::tsan_read2
+      || tsan_function == SharedRuntime::tsan_read4
+      || tsan_function == SharedRuntime::tsan_read8) {
+    return SharedRuntime::tsan_acquire;
+  } else if (tsan_function == SharedRuntime::tsan_write1
+      || tsan_function == SharedRuntime::tsan_write2
+      || tsan_function == SharedRuntime::tsan_write4
+      || tsan_function == SharedRuntime::tsan_write8) {
+    return SharedRuntime::tsan_release;
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
+void TemplateTable::tsan_observe_get_or_put(
+    const Address &field,
+    Register flags,
+    TsanMemoryReadWriteFunction tsan_function,
+    TosState tos) {
+  assert(flags == rdx, "flags should be in rdx register");
+  assert(ThreadSanitizer, "ThreadSanitizer should be set");
+
+  TsanMemoryReleaseAcquireFunction releaseAcquireFunction =
+      tsan_release_acquire_method(tsan_function);
+
+  Label done, notAcquireRelease;
+
+  // We could save some instructions by only saving the registers we need.
+  __ pusha();
+  // pusha() doesn't save xmm0, which tsan_function clobbers and the
+  // interpreter still needs.
+  // This really only needs to be done for some of the float/double accesses,
+  // but it's here because it's cleaner.
+  __ push_d(xmm0);
+  DEBUG_ONLY(
+    __ pusha();
+    __ movptr(c_rarg0, field.base());
+    __ leaq(c_rarg1, field);
+    __ subq(c_rarg1, field.base());
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::verify_oop_index),
+                    c_rarg0 /* oop */, c_rarg1 /* index */);
+    __ popa();
+  );
+  // For volatile reads/writes use an acquire/release.
+  // If a reference is annotated to be ignored, assume it's safe to
+  // access the object it's referring to and create a happens-before relation
+  // between the accesses to this reference.
+  int32_t acquire_release_mask = 1 << ConstantPoolCacheEntry::is_volatile_shift |
+      ((tos == atos) ? 1 << ConstantPoolCacheEntry::is_tsan_ignore_shift : 0);
+  __ testl(flags, acquire_release_mask);
+  __ jcc(Assembler::zero, notAcquireRelease);
+
+  __ leaq(c_rarg0, field);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, releaseAcquireFunction), c_rarg0);
+  if (ThreadSanitizerJavaMemory) {
+    __ jmp(done);
+
+    __ bind(notAcquireRelease);
+    // Ignore reads/writes to final fields. They can't be racy.
+    int32_t ignore_mask = 1 << ConstantPoolCacheEntry::is_final_shift |
+        1 << ConstantPoolCacheEntry::is_tsan_ignore_shift;
+    __ testl(flags, ignore_mask);
+    __ jcc(Assembler::notZero, done);
+
+    __ leaq(c_rarg0, field);
+    __ get_method(c_rarg1);
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, tsan_function),
+                    c_rarg0 /* addr */, c_rarg1 /* method */, rbcp /* bcp */);
+
+    __ bind(done);
+  } else {
+    __ bind(notAcquireRelease);
+  }
+  __ pop_d(xmm0);
+  __ popa();
+}
+
+void TemplateTable::tsan_observe_load_or_store(
+    const Address& field, TsanMemoryReadWriteFunction tsan_function) {
+  assert(ThreadSanitizer, "ThreadSanitizer should be set");
+  if (!ThreadSanitizerJavaMemory) {
+    return;
+  }
+  // We could save some instructions by only saving the registers we need.
+  __ pusha();
+  // pusha() doesn't save xmm0, which tsan_function clobbers and the
+  // interpreter still needs.
+  // This really only needs to be done for some of the float/double accesses,
+  // but it's here because it's cleaner.
+  __ push_d(xmm0);
+  DEBUG_ONLY(
+    __ pusha();
+    __ movptr(c_rarg0, field.base());
+    __ leaq(c_rarg1, field);
+    __ subq(c_rarg1, field.base());
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::verify_oop_index),
+                    c_rarg0 /* oop */, c_rarg1 /* index */);
+    __ popa();
+  );
+  __ leaq(c_rarg0, field);
+  __ get_method(c_rarg1);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, tsan_function),
+                  c_rarg0 /* addr */, c_rarg1 /* method */, rbcp /* bcp */);
+  __ pop_d(xmm0);
+  __ popa();
+}
+
+#endif  // INCLUDE_TSAN
+
 void TemplateTable::iaload() {
   transition(itos, itos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, rax,
-                    Address(rdx, rax, Address::times_4,
-                            arrayOopDesc::base_offset_in_bytes(T_INT)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_4,
+               arrayOopDesc::base_offset_in_bytes(T_INT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read4));
+  __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, rax, addr, noreg, noreg);
 }
 
 void TemplateTable::laload() {
   transition(itos, ltos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
   NOT_LP64(__ mov(rbx, rax));
   // rbx,: index
-  __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, noreg /* ltos */,
-                    Address(rdx, rbx, Address::times_8,
-                            arrayOopDesc::base_offset_in_bytes(T_LONG)),
-                    noreg, noreg);
+  Address addr(rdx, rbx, Address::times_8,
+               arrayOopDesc::base_offset_in_bytes(T_LONG));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read8));
+  __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, noreg /* ltos */, addr, noreg,
+                    noreg);
 }
 
 
 
 void TemplateTable::faload() {
   transition(itos, ftos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_FLOAT, IN_HEAP | IS_ARRAY, noreg /* ftos */,
-                    Address(rdx, rax,
-                            Address::times_4,
-                            arrayOopDesc::base_offset_in_bytes(T_FLOAT)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_4,
+               arrayOopDesc::base_offset_in_bytes(T_FLOAT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read4));
+  __ access_load_at(T_FLOAT, IN_HEAP | IS_ARRAY, noreg /* ftos */, addr, noreg,
+                    noreg);
 }
 
 void TemplateTable::daload() {
   transition(itos, dtos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_DOUBLE, IN_HEAP | IS_ARRAY, noreg /* dtos */,
-                    Address(rdx, rax,
-                            Address::times_8,
-                            arrayOopDesc::base_offset_in_bytes(T_DOUBLE)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_8,
+               arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read8));
+  __ access_load_at(T_DOUBLE, IN_HEAP | IS_ARRAY, noreg /* dtos */, addr, noreg,
+                    noreg);
 }
 
 void TemplateTable::aaload() {
   transition(itos, atos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  do_oop_load(_masm,
-              Address(rdx, rax,
-                      UseCompressedOops ? Address::times_4 : Address::times_ptr,
-                      arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
-              rax,
-              IS_ARRAY);
+  Address addr(rdx, rax,
+               UseCompressedOops ? Address::times_4 : Address::times_ptr,
+               arrayOopDesc::base_offset_in_bytes(T_OBJECT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(
+      addr, UseCompressedOops ? SharedRuntime::tsan_read4
+                              : SharedRuntime::tsan_read8));
+  do_oop_load(_masm, addr, rax, IS_ARRAY);
 }
 
 void TemplateTable::baload() {
   transition(itos, itos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, rax,
-                    Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_1,
+               arrayOopDesc::base_offset_in_bytes(T_BYTE));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read1));
+  __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, rax, addr, noreg, noreg);
 }
 
 void TemplateTable::caload() {
   transition(itos, itos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax,
-                    Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_2,
+               arrayOopDesc::base_offset_in_bytes(T_CHAR));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read2));
+  __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax, addr, noreg, noreg);
 }
 
 // iload followed by caload frequent pair
 void TemplateTable::fast_icaload() {
   transition(vtos, itos);
@@ -869,13 +987,14 @@
 void TemplateTable::saload() {
   transition(itos, itos);
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, rax,
-                    Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)),
-                    noreg, noreg);
+  Address addr(rdx, rax, Address::times_2,
+               arrayOopDesc::base_offset_in_bytes(T_SHORT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_read2));
+  __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, rax, addr, noreg, noreg);
 }
 
 void TemplateTable::iload(int n) {
   transition(vtos, itos);
   __ movl(rax, iaddress(n));
@@ -1063,55 +1182,58 @@
   __ pop_i(rbx);
   // rax: value
   // rbx: index
   // rdx: array
   index_check(rdx, rbx); // prefer index in rbx
-  __ access_store_at(T_INT, IN_HEAP | IS_ARRAY,
-                     Address(rdx, rbx, Address::times_4,
-                             arrayOopDesc::base_offset_in_bytes(T_INT)),
-                     rax, noreg, noreg);
+  Address addr(rdx, rbx, Address::times_4,
+               arrayOopDesc::base_offset_in_bytes(T_INT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write4));
+  __ access_store_at(T_INT, IN_HEAP | IS_ARRAY, addr, rax, noreg, noreg);
 }
 
 void TemplateTable::lastore() {
   transition(ltos, vtos);
   __ pop_i(rbx);
   // rax,: low(value)
   // rcx: array
   // rdx: high(value)
   index_check(rcx, rbx);  // prefer index in rbx,
   // rbx,: index
-  __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY,
-                     Address(rcx, rbx, Address::times_8,
-                             arrayOopDesc::base_offset_in_bytes(T_LONG)),
-                     noreg /* ltos */, noreg, noreg);
+  Address addr(rcx, rbx, Address::times_8,
+               arrayOopDesc::base_offset_in_bytes(T_LONG));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write8));
+  __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY, addr, noreg /* ltos */, noreg,
+                     noreg);
 }
 
 
 void TemplateTable::fastore() {
   transition(ftos, vtos);
   __ pop_i(rbx);
   // value is in UseSSE >= 1 ? xmm0 : ST(0)
   // rbx:  index
   // rdx:  array
   index_check(rdx, rbx); // prefer index in rbx
-  __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY,
-                     Address(rdx, rbx, Address::times_4,
-                             arrayOopDesc::base_offset_in_bytes(T_FLOAT)),
-                     noreg /* ftos */, noreg, noreg);
+  Address addr(rdx, rbx, Address::times_4,
+               arrayOopDesc::base_offset_in_bytes(T_FLOAT));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write4));
+  __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY, addr, noreg /* ftos */, noreg,
+                     noreg);
 }
 
 void TemplateTable::dastore() {
   transition(dtos, vtos);
   __ pop_i(rbx);
   // value is in UseSSE >= 2 ? xmm0 : ST(0)
   // rbx:  index
   // rdx:  array
   index_check(rdx, rbx); // prefer index in rbx
-  __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY,
-                     Address(rdx, rbx, Address::times_8,
-                             arrayOopDesc::base_offset_in_bytes(T_DOUBLE)),
-                     noreg /* dtos */, noreg, noreg);
+  Address addr(rdx, rbx, Address::times_8,
+               arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write8));
+  __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY, addr, noreg /* dtos */,
+                     noreg, noreg);
 }
 
 void TemplateTable::aastore() {
   Label is_null, ok_is_subtype, done;
   transition(vtos, vtos);
@@ -1122,10 +1244,14 @@
 
   Address element_address(rdx, rcx,
                           UseCompressedOops? Address::times_4 : Address::times_ptr,
                           arrayOopDesc::base_offset_in_bytes(T_OBJECT));
 
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(
+      element_address, UseCompressedOops ? SharedRuntime::tsan_write4
+                                         : SharedRuntime::tsan_write8));
+
   index_check_without_pop(rdx, rcx);     // kills rbx
   __ testptr(rax, rax);
   __ jcc(Assembler::zero, is_null);
 
   // Move subklass into rbx
@@ -1180,27 +1306,27 @@
   __ testl(rcx, diffbit);
   Label L_skip;
   __ jccb(Assembler::zero, L_skip);
   __ andl(rax, 1);  // if it is a T_BOOLEAN array, mask the stored value to 0/1
   __ bind(L_skip);
-  __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY,
-                     Address(rdx, rbx,Address::times_1,
-                             arrayOopDesc::base_offset_in_bytes(T_BYTE)),
-                     rax, noreg, noreg);
+  Address addr(rdx, rbx, Address::times_1,
+               arrayOopDesc::base_offset_in_bytes(T_BYTE));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write1));
+  __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY, addr, rax, noreg, noreg);
 }
 
 void TemplateTable::castore() {
   transition(itos, vtos);
   __ pop_i(rbx);
   // rax: value
   // rbx: index
   // rdx: array
   index_check(rdx, rbx);  // prefer index in rbx
-  __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY,
-                     Address(rdx, rbx, Address::times_2,
-                             arrayOopDesc::base_offset_in_bytes(T_CHAR)),
-                     rax, noreg, noreg);
+  Address addr(rdx, rbx, Address::times_2,
+               arrayOopDesc::base_offset_in_bytes(T_CHAR));
+  TSAN_RUNTIME_ONLY(tsan_observe_load_or_store(addr, SharedRuntime::tsan_write2));
+  __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY, addr, rax, noreg, noreg);
 }
 
 
 void TemplateTable::sastore() {
   castore();
@@ -2789,10 +2915,30 @@
                            in_bytes(cp_base_offset +
                                     ConstantPoolCacheEntry::f1_offset())));
     const int mirror_offset = in_bytes(Klass::java_mirror_offset());
     __ movptr(obj, Address(obj, mirror_offset));
     __ resolve_oop_handle(obj);
+    TSAN_RUNTIME_ONLY(
+      // Draw a happens-before edge from the class's static initializer to
+      // this lookup.
+
+      // java_lang_Class::_init_lock_offset may not have been initialized
+      // when generating code. It will be initialized at runtime though.
+      // So calculate its address and read from it at runtime.
+      __ pusha();
+      __ movq(c_rarg0, obj);
+      AddressLiteral init_lock_offset_address(
+          (address) java_lang_Class::init_lock_offset_addr(),
+          relocInfo::none);
+      __ lea(rax, init_lock_offset_address);
+      __ movl(rax, Address(rax, 0));
+      __ addq(c_rarg0, rax);
+      __ call_VM_leaf(CAST_FROM_FN_PTR(address,
+                                       SharedRuntime::tsan_acquire),
+                      c_rarg0);
+      __ popa();
+    );
   }
 }
 
 void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
                                                Register method,
@@ -2884,10 +3030,15 @@
 
   if (!is_static) pop_and_check_object(obj);
 
   const Address field(obj, off, Address::times_1, 0*wordSize);
 
+  // During a TSAN instrumented run, move flags into rdx so we can later
+  // examine whether the field is volatile or has been annotated to be ignored
+  // by Tsan.
+  TSAN_RUNTIME_ONLY(__ movl(rdx, flags));
+
   Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj;
 
   __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
   // Make sure we don't need to mask edx after the above shift
   assert(btos == 0, "change code, btos != 0");
@@ -2896,10 +3047,12 @@
 
   __ jcc(Assembler::notZero, notByte);
   // btos
   __ access_load_at(T_BYTE, IN_HEAP, rax, field, noreg, noreg);
   __ push(btos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read1, btos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2909,10 +3062,12 @@
   __ jcc(Assembler::notEqual, notBool);
 
   // ztos (same code as btos)
   __ access_load_at(T_BOOLEAN, IN_HEAP, rax, field, noreg, noreg);
   __ push(ztos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read1, ztos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     // use btos rewriting, no truncating to t/f bit is needed for getfield.
     patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
   }
@@ -2922,10 +3077,14 @@
   __ cmpl(flags, atos);
   __ jcc(Assembler::notEqual, notObj);
   // atos
   do_oop_load(_masm, field, rax);
   __ push(atos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, UseCompressedOops ? SharedRuntime::tsan_read4
+                                    : SharedRuntime::tsan_read8,
+      atos));
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
   }
   __ jmp(Done);
 
@@ -2933,10 +3092,12 @@
   __ cmpl(flags, itos);
   __ jcc(Assembler::notEqual, notInt);
   // itos
   __ access_load_at(T_INT, IN_HEAP, rax, field, noreg, noreg);
   __ push(itos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read4, itos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2945,10 +3106,12 @@
   __ cmpl(flags, ctos);
   __ jcc(Assembler::notEqual, notChar);
   // ctos
   __ access_load_at(T_CHAR, IN_HEAP, rax, field, noreg, noreg);
   __ push(ctos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read2, ctos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2957,10 +3120,12 @@
   __ cmpl(flags, stos);
   __ jcc(Assembler::notEqual, notShort);
   // stos
   __ access_load_at(T_SHORT, IN_HEAP, rax, field, noreg, noreg);
   __ push(stos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read2, stos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2971,10 +3136,12 @@
   // ltos
     // Generate code as if volatile (x86_32).  There just aren't enough registers to
     // save that information and this code is faster than the test.
   __ access_load_at(T_LONG, IN_HEAP | MO_RELAXED, noreg /* ltos */, field, noreg, noreg);
   __ push(ltos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read8, ltos));
   // Rewrite bytecode to be faster
   LP64_ONLY(if (!is_static && rc == may_rewrite) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
   __ jmp(Done);
 
   __ bind(notLong);
@@ -2982,10 +3149,12 @@
   __ jcc(Assembler::notEqual, notFloat);
   // ftos
 
   __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg);
   __ push(ftos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read4, ftos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2998,10 +3167,12 @@
 #endif
   // dtos
   // MO_RELAXED: for the case of volatile field, in fact it adds no extra work for the underlying implementation
   __ access_load_at(T_DOUBLE, IN_HEAP | MO_RELAXED, noreg /* dtos */, field, noreg, noreg);
   __ push(dtos);
+  TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+      field, rdx, SharedRuntime::tsan_read8, dtos));
   // Rewrite bytecode to be faster
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
   }
 #ifdef ASSERT
@@ -3133,12 +3304,10 @@
   // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore |
   //                                              Assembler::StoreStore));
 
   Label notVolatile, Done;
   __ movl(rdx, flags);
-  __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
-  __ andl(rdx, 0x1);
 
   // Check for volatile store
   __ testl(rdx, rdx);
   __ jcc(Assembler::zero, notVolatile);
 
@@ -3174,10 +3343,12 @@
 
   // btos
   {
     __ pop(btos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write1, btos));
     __ access_store_at(T_BYTE, IN_HEAP, field, rax, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3189,10 +3360,12 @@
 
   // ztos
   {
     __ pop(ztos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write1, ztos));
     __ access_store_at(T_BOOLEAN, IN_HEAP, field, rax, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3204,10 +3377,14 @@
 
   // atos
   {
     __ pop(atos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(field, rdx,
+        UseCompressedOops ? SharedRuntime::tsan_write4
+                          : SharedRuntime::tsan_write8,
+        atos));
     // Store into the field
     do_oop_store(_masm, field, rax);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
     }
@@ -3220,10 +3397,12 @@
 
   // itos
   {
     __ pop(itos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write4, itos));
     __ access_store_at(T_INT, IN_HEAP, field, rax, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3235,10 +3414,12 @@
 
   // ctos
   {
     __ pop(ctos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write2, ctos));
     __ access_store_at(T_CHAR, IN_HEAP, field, rax, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3250,10 +3431,12 @@
 
   // stos
   {
     __ pop(stos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write2, stos));
     __ access_store_at(T_SHORT, IN_HEAP, field, rax, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3265,10 +3448,12 @@
 
   // ltos
   {
     __ pop(ltos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write8, ltos));
     // MO_RELAXED: generate atomic store for the case of volatile field (important for x86_32)
     __ access_store_at(T_LONG, IN_HEAP | MO_RELAXED, field, noreg /* ltos*/, noreg, noreg);
 #ifdef _LP64
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
@@ -3283,10 +3468,12 @@
 
   // ftos
   {
     __ pop(ftos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write4, ftos));
     __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos */, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3301,10 +3488,12 @@
 
   // dtos
   {
     __ pop(dtos);
     if (!is_static) pop_and_check_object(obj);
+    TSAN_RUNTIME_ONLY(tsan_observe_get_or_put(
+        field, rdx, SharedRuntime::tsan_write8, dtos));
     // MO_RELAXED: for the case of volatile field, in fact it adds no extra work for the underlying implementation
     __ access_store_at(T_DOUBLE, IN_HEAP | MO_RELAXED, field, noreg /* dtos */, noreg, noreg);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
     }
@@ -4124,10 +4313,18 @@
       __ call_VM_leaf(
            CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax);
       __ pop(atos);
     }
 
+    TSAN_RUNTIME_ONLY(
+      // return value of new oop is in rax.
+      __ push(atos);
+      __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::tsan_track_obj),
+                      rax);
+      __ pop(atos);
+    );
+
     __ jmp(done);
   }
 
   // slow case
   __ bind(slow_case);
