oop.inline.hpp revision 2062:3582bf76420e
168349Sobrien/* 2133359Sobrien * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3133359Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4133359Sobrien * 5133359Sobrien * This code is free software; you can redistribute it and/or modify it 6133359Sobrien * under the terms of the GNU General Public License version 2 only, as 7133359Sobrien * published by the Free Software Foundation. 8133359Sobrien * 9133359Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT 10133359Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11133359Sobrien * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12133359Sobrien * version 2 for more details (a copy is included in the LICENSE file that 13133359Sobrien * accompanied this code). 14133359Sobrien * 15133359Sobrien * You should have received a copy of the GNU General Public License version 16133359Sobrien * 2 along with this work; if not, write to the Free Software Foundation, 17133359Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18133359Sobrien * 19133359Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20133359Sobrien * or visit www.oracle.com if you need additional information or have any 21133359Sobrien * questions. 22133359Sobrien * 23133359Sobrien */ 24133359Sobrien 25133359Sobrien#ifndef SHARE_VM_OOPS_OOP_INLINE_HPP 26133359Sobrien#define SHARE_VM_OOPS_OOP_INLINE_HPP 27133359Sobrien 28133359Sobrien#include "gc_implementation/shared/ageTable.hpp" 2968349Sobrien#include "gc_implementation/shared/markSweep.inline.hpp" 3068349Sobrien#include "gc_interface/collectedHeap.inline.hpp" 3168349Sobrien#include "memory/barrierSet.inline.hpp" 3280588Sobrien#include "memory/cardTableModRefBS.hpp" 33133359Sobrien#include "memory/compactingPermGenGen.hpp" 34175296Sobrien#include "memory/genCollectedHeap.hpp" 3568349Sobrien#include "memory/generation.hpp" 3684685Sobrien#include "memory/permGen.hpp" 3784685Sobrien#include "memory/specialized_oop_closures.hpp" 3884685Sobrien#include "oops/arrayKlass.hpp" 3968349Sobrien#include "oops/arrayOop.hpp" 40169942Sobrien#include "oops/klass.hpp" 4168349Sobrien#include "oops/klassOop.hpp" 42103373Sobrien#include "oops/markOop.inline.hpp" 43133359Sobrien#include "oops/oop.hpp" 44133359Sobrien#include "runtime/atomic.hpp" 4574784Sobrien#include "runtime/os.hpp" 4674784Sobrien#ifdef TARGET_ARCH_x86 4774784Sobrien# include "bytes_x86.hpp" 4868349Sobrien#endif 4968349Sobrien#ifdef TARGET_ARCH_sparc 50175296Sobrien# include "bytes_sparc.hpp" 5168349Sobrien#endif 5268349Sobrien#ifdef TARGET_ARCH_zero 5368349Sobrien# include "bytes_zero.hpp" 5468349Sobrien#endif 5568349Sobrien 5668349Sobrien// Implementation of all inlined member functions defined in oop.hpp 5775937Sobrien// We need a separate file to avoid circular references 5875937Sobrien 5975937Sobrieninline void oopDesc::release_set_mark(markOop m) { 6075937Sobrien OrderAccess::release_store_ptr(&_mark, m); 6175937Sobrien} 6275937Sobrien 6375937Sobrieninline markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) { 6475937Sobrien return (markOop) Atomic::cmpxchg_ptr(new_mark, &_mark, old_mark); 6575937Sobrien} 6668349Sobrien 6775937Sobrieninline klassOop oopDesc::klass() const { 6875937Sobrien if (UseCompressedOops) { 6975937Sobrien return (klassOop)decode_heap_oop_not_null(_metadata._compressed_klass); 7068349Sobrien } else { 7175937Sobrien return _metadata._klass; 7275937Sobrien } 7375937Sobrien} 7475937Sobrien 75133359Sobrieninline klassOop oopDesc::klass_or_null() const volatile { 76133359Sobrien // can be NULL in CMS 7768349Sobrien if (UseCompressedOops) { 7868349Sobrien return (klassOop)decode_heap_oop(_metadata._compressed_klass); 79159764Sobrien } else { 80159764Sobrien return _metadata._klass; 81159764Sobrien } 82159764Sobrien} 83159764Sobrien 84159764Sobrieninline int oopDesc::klass_gap_offset_in_bytes() { 85169962Sobrien assert(UseCompressedOops, "only applicable to compressed headers"); 86169962Sobrien return oopDesc::klass_offset_in_bytes() + sizeof(narrowOop); 87169962Sobrien} 88169962Sobrien 89169942Sobrieninline oop* oopDesc::klass_addr() { 90169962Sobrien // Only used internally and with CMS and will not work with 91133359Sobrien // UseCompressedOops 92159764Sobrien assert(!UseCompressedOops, "only supported with uncompressed oops"); 93169962Sobrien return (oop*) &_metadata._klass; 94159764Sobrien} 95169942Sobrien 96159764Sobrieninline narrowOop* oopDesc::compressed_klass_addr() { 97133359Sobrien assert(UseCompressedOops, "only called by compressed oops"); 98159764Sobrien return (narrowOop*) &_metadata._compressed_klass; 99159764Sobrien} 100133359Sobrien 101133359Sobrieninline void oopDesc::set_klass(klassOop k) { 102133359Sobrien // since klasses are promoted no store check is needed 103133359Sobrien assert(Universe::is_bootstrapping() || k != NULL, "must be a real klassOop"); 104133359Sobrien assert(Universe::is_bootstrapping() || k->is_klass(), "not a klassOop"); 105133359Sobrien if (UseCompressedOops) { 106169942Sobrien oop_store_without_check(compressed_klass_addr(), (oop)k); 107139368Sobrien } else { 108133359Sobrien oop_store_without_check(klass_addr(), (oop) k); 109133359Sobrien } 110133359Sobrien} 111133359Sobrien 112169942Sobrieninline int oopDesc::klass_gap() const { 113139368Sobrien return *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()); 114175296Sobrien} 11568349Sobrien 116133359Sobrieninline void oopDesc::set_klass_gap(int v) { 117133359Sobrien if (UseCompressedOops) { 11868349Sobrien *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()) = v; 119159764Sobrien } 12080588Sobrien} 12174784Sobrien 122103373Sobrieninline void oopDesc::set_klass_to_list_ptr(oop k) { 12380588Sobrien // This is only to be used during GC, for from-space objects, so no 12480588Sobrien // barrier is needed. 125103373Sobrien if (UseCompressedOops) { 12680588Sobrien _metadata._compressed_klass = encode_heap_oop(k); // may be null (parnew overflow handling) 12780588Sobrien } else { 128133359Sobrien _metadata._klass = (klassOop)k; 129133359Sobrien } 13080588Sobrien} 13180588Sobrien 13280588Sobrieninline void oopDesc::init_mark() { set_mark(markOopDesc::prototype_for_object(this)); } 13380588Sobrieninline Klass* oopDesc::blueprint() const { return klass()->klass_part(); } 13480588Sobrien 13580588Sobrieninline bool oopDesc::is_a(klassOop k) const { return blueprint()->is_subtype_of(k); } 13680588Sobrien 137133359Sobrieninline bool oopDesc::is_instance() const { return blueprint()->oop_is_instance(); } 138133359Sobrieninline bool oopDesc::is_instanceRef() const { return blueprint()->oop_is_instanceRef(); } 13980588Sobrieninline bool oopDesc::is_array() const { return blueprint()->oop_is_array(); } 14080588Sobrieninline bool oopDesc::is_objArray() const { return blueprint()->oop_is_objArray(); } 141133359Sobrieninline bool oopDesc::is_typeArray() const { return blueprint()->oop_is_typeArray(); } 142133359Sobrieninline bool oopDesc::is_javaArray() const { return blueprint()->oop_is_javaArray(); } 143133359Sobrieninline bool oopDesc::is_klass() const { return blueprint()->oop_is_klass(); } 144133359Sobrieninline bool oopDesc::is_thread() const { return blueprint()->oop_is_thread(); } 145133359Sobrieninline bool oopDesc::is_method() const { return blueprint()->oop_is_method(); } 146133359Sobrieninline bool oopDesc::is_constMethod() const { return blueprint()->oop_is_constMethod(); } 147133359Sobrieninline bool oopDesc::is_methodData() const { return blueprint()->oop_is_methodData(); } 148133359Sobrieninline bool oopDesc::is_constantPool() const { return blueprint()->oop_is_constantPool(); } 149133359Sobrieninline bool oopDesc::is_constantPoolCache() const { return blueprint()->oop_is_constantPoolCache(); } 15080588Sobrieninline bool oopDesc::is_compiledICHolder() const { return blueprint()->oop_is_compiledICHolder(); } 15180588Sobrien 15280588Sobrieninline void* oopDesc::field_base(int offset) const { return (void*)&((char*)this)[offset]; } 153169962Sobrien 154169962Sobrientemplate <class T> inline T* oopDesc::obj_field_addr(int offset) const { return (T*)field_base(offset); } 155169962Sobrieninline jbyte* oopDesc::byte_field_addr(int offset) const { return (jbyte*) field_base(offset); } 156169962Sobrieninline jchar* oopDesc::char_field_addr(int offset) const { return (jchar*) field_base(offset); } 157169962Sobrieninline jboolean* oopDesc::bool_field_addr(int offset) const { return (jboolean*)field_base(offset); } 158169962Sobrieninline jint* oopDesc::int_field_addr(int offset) const { return (jint*) field_base(offset); } 159169962Sobrieninline jshort* oopDesc::short_field_addr(int offset) const { return (jshort*) field_base(offset); } 160169962Sobrieninline jlong* oopDesc::long_field_addr(int offset) const { return (jlong*) field_base(offset); } 161169962Sobrieninline jfloat* oopDesc::float_field_addr(int offset) const { return (jfloat*) field_base(offset); } 162169962Sobrieninline jdouble* oopDesc::double_field_addr(int offset) const { return (jdouble*) field_base(offset); } 163169962Sobrieninline address* oopDesc::address_field_addr(int offset) const { return (address*) field_base(offset); } 164169962Sobrien 165169962Sobrien 166169962Sobrien// Functions for getting and setting oops within instance objects. 167169962Sobrien// If the oops are compressed, the type passed to these overloaded functions 168169962Sobrien// is narrowOop. All functions are overloaded so they can be called by 169169962Sobrien// template functions without conditionals (the compiler instantiates via 170169962Sobrien// the right type and inlines the appopriate code). 171169962Sobrien 172169962Sobrieninline bool oopDesc::is_null(oop obj) { return obj == NULL; } 173169962Sobrieninline bool oopDesc::is_null(narrowOop obj) { return obj == 0; } 174169962Sobrien 175169962Sobrien// Algorithm for encoding and decoding oops from 64 bit pointers to 32 bit 176169962Sobrien// offset from the heap base. Saving the check for null can save instructions 177169962Sobrien// in inner GC loops so these are separated. 178169962Sobrien 179169962Sobrieninline bool check_obj_alignment(oop obj) { 180169962Sobrien return (intptr_t)obj % MinObjAlignmentInBytes == 0; 181169962Sobrien} 182169962Sobrien 183169962Sobrieninline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { 184169962Sobrien assert(!is_null(v), "oop value can never be zero"); 185169962Sobrien assert(check_obj_alignment(v), "Address not aligned"); 186169962Sobrien assert(Universe::heap()->is_in_reserved(v), "Address not in heap"); 187169962Sobrien address base = Universe::narrow_oop_base(); 188169962Sobrien int shift = Universe::narrow_oop_shift(); 189169962Sobrien uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); 190169962Sobrien assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); 191169962Sobrien uint64_t result = pd >> shift; 192169962Sobrien assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow"); 193175296Sobrien assert(decode_heap_oop(result) == v, "reversibility"); 194175296Sobrien return (narrowOop)result; 195175296Sobrien} 196175296Sobrien 197175296Sobrieninline narrowOop oopDesc::encode_heap_oop(oop v) { 198175296Sobrien return (is_null(v)) ? (narrowOop)0 : encode_heap_oop_not_null(v); 199169962Sobrien} 200169962Sobrien 201169962Sobrieninline oop oopDesc::decode_heap_oop_not_null(narrowOop v) { 202169962Sobrien assert(!is_null(v), "narrow oop value can never be zero"); 20380588Sobrien address base = Universe::narrow_oop_base(); 204169962Sobrien int shift = Universe::narrow_oop_shift(); 205169962Sobrien oop result = (oop)(void*)((uintptr_t)base + ((uintptr_t)v << shift)); 206169962Sobrien assert(check_obj_alignment(result), err_msg("address not aligned: " PTR_FORMAT, (void*) result)); 207169962Sobrien return result; 208169962Sobrien} 209169962Sobrien 210169962Sobrieninline oop oopDesc::decode_heap_oop(narrowOop v) { 211169962Sobrien return is_null(v) ? (oop)NULL : decode_heap_oop_not_null(v); 212169962Sobrien} 213169962Sobrien 214169962Sobrieninline oop oopDesc::decode_heap_oop_not_null(oop v) { return v; } 215169962Sobrieninline oop oopDesc::decode_heap_oop(oop v) { return v; } 216169962Sobrien 217169962Sobrien// Load an oop out of the Java heap as is without decoding. 218169962Sobrien// Called by GC to check for null before decoding. 219169962Sobrieninline oop oopDesc::load_heap_oop(oop* p) { return *p; } 220169962Sobrieninline narrowOop oopDesc::load_heap_oop(narrowOop* p) { return *p; } 221169962Sobrien 222169962Sobrien// Load and decode an oop out of the Java heap into a wide oop. 223169962Sobrieninline oop oopDesc::load_decode_heap_oop_not_null(oop* p) { return *p; } 224169962Sobrieninline oop oopDesc::load_decode_heap_oop_not_null(narrowOop* p) { 225169962Sobrien return decode_heap_oop_not_null(*p); 226169962Sobrien} 227169962Sobrien 228169962Sobrien// Load and decode an oop out of the heap accepting null 229169962Sobrieninline oop oopDesc::load_decode_heap_oop(oop* p) { return *p; } 230169962Sobrieninline oop oopDesc::load_decode_heap_oop(narrowOop* p) { 231169962Sobrien return decode_heap_oop(*p); 232169962Sobrien} 233169962Sobrien 234169962Sobrien// Store already encoded heap oop into the heap. 235169962Sobrieninline void oopDesc::store_heap_oop(oop* p, oop v) { *p = v; } 23674784Sobrieninline void oopDesc::store_heap_oop(narrowOop* p, narrowOop v) { *p = v; } 23774784Sobrien 23874784Sobrien// Encode and store a heap oop. 239133359Sobrieninline void oopDesc::encode_store_heap_oop_not_null(narrowOop* p, oop v) { 240133359Sobrien *p = encode_heap_oop_not_null(v); 241133359Sobrien} 24274784Sobrieninline void oopDesc::encode_store_heap_oop_not_null(oop* p, oop v) { *p = v; } 24374784Sobrien 244103373Sobrien// Encode and store a heap oop allowing for null. 24574784Sobrieninline void oopDesc::encode_store_heap_oop(narrowOop* p, oop v) { 24674784Sobrien *p = encode_heap_oop(v); 247133359Sobrien} 24874784Sobrieninline void oopDesc::encode_store_heap_oop(oop* p, oop v) { *p = v; } 249133359Sobrien 250133359Sobrien// Store heap oop as is for volatile fields. 251133359Sobrieninline void oopDesc::release_store_heap_oop(volatile oop* p, oop v) { 252133359Sobrien OrderAccess::release_store_ptr(p, v); 253133359Sobrien} 25474784Sobrieninline void oopDesc::release_store_heap_oop(volatile narrowOop* p, 255133359Sobrien narrowOop v) { 256133359Sobrien OrderAccess::release_store(p, v); 257133359Sobrien} 258133359Sobrien 259133359Sobrieninline void oopDesc::release_encode_store_heap_oop_not_null( 260133359Sobrien volatile narrowOop* p, oop v) { 261133359Sobrien // heap oop is not pointer sized. 262133359Sobrien OrderAccess::release_store(p, encode_heap_oop_not_null(v)); 263133359Sobrien} 264159764Sobrien 26580588Sobrieninline void oopDesc::release_encode_store_heap_oop_not_null( 266133359Sobrien volatile oop* p, oop v) { 267133359Sobrien OrderAccess::release_store_ptr(p, v); 268139368Sobrien} 269133359Sobrien 270133359Sobrieninline void oopDesc::release_encode_store_heap_oop(volatile oop* p, 271133359Sobrien oop v) { 272133359Sobrien OrderAccess::release_store_ptr(p, v); 27374784Sobrien} 274133359Sobrieninline void oopDesc::release_encode_store_heap_oop( 27574784Sobrien volatile narrowOop* p, oop v) { 276133359Sobrien OrderAccess::release_store(p, encode_heap_oop(v)); 277133359Sobrien} 278133359Sobrien 279133359Sobrien 280133359Sobrien// These functions are only used to exchange oop fields in instances, 28174784Sobrien// not headers. 282133359Sobrieninline oop oopDesc::atomic_exchange_oop(oop exchange_value, volatile HeapWord *dest) { 283169942Sobrien if (UseCompressedOops) { 284133359Sobrien // encode exchange value from oop to T 28574784Sobrien narrowOop val = encode_heap_oop(exchange_value); 28674784Sobrien narrowOop old = (narrowOop)Atomic::xchg(val, (narrowOop*)dest); 28774784Sobrien // decode old from T to oop 28874784Sobrien return decode_heap_oop(old); 289133359Sobrien } else { 29074784Sobrien return (oop)Atomic::xchg_ptr(exchange_value, (oop*)dest); 291133359Sobrien } 292133359Sobrien} 293133359Sobrien 294133359Sobrieninline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value, 29574784Sobrien volatile HeapWord *dest, 296133359Sobrien oop compare_value) { 29780588Sobrien if (UseCompressedOops) { 29874784Sobrien // encode exchange and compare value from oop to T 29974784Sobrien narrowOop val = encode_heap_oop(exchange_value); 300133359Sobrien narrowOop cmp = encode_heap_oop(compare_value); 301133359Sobrien 302133359Sobrien narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp); 303133359Sobrien // decode old from T to oop 304133359Sobrien return decode_heap_oop(old); 305133359Sobrien } else { 306175296Sobrien return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value); 307133359Sobrien } 308133359Sobrien} 309133359Sobrien 310133359Sobrien// In order to put or get a field out of an instance, must first check 311175296Sobrien// if the field has been compressed and uncompress it. 312133359Sobrieninline oop oopDesc::obj_field(int offset) const { 313133359Sobrien return UseCompressedOops ? 314133359Sobrien load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) : 315133359Sobrien load_decode_heap_oop(obj_field_addr<oop>(offset)); 316133359Sobrien} 317133359Sobrieninline void oopDesc::obj_field_put(int offset, oop value) { 318133359Sobrien UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) : 319133359Sobrien oop_store(obj_field_addr<oop>(offset), value); 320133359Sobrien} 321133359Sobrieninline void oopDesc::obj_field_raw_put(int offset, oop value) { 32274784Sobrien UseCompressedOops ? 323103373Sobrien encode_store_heap_oop(obj_field_addr<narrowOop>(offset), value) : 324133359Sobrien encode_store_heap_oop(obj_field_addr<oop>(offset), value); 325133359Sobrien} 32668349Sobrien 327133359Sobrieninline jbyte oopDesc::byte_field(int offset) const { return (jbyte) *byte_field_addr(offset); } 32868349Sobrieninline void oopDesc::byte_field_put(int offset, jbyte contents) { *byte_field_addr(offset) = (jint) contents; } 329133359Sobrien 330169942Sobrieninline jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } 33168349Sobrieninline void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; } 332169962Sobrien 333169962Sobrieninline jchar oopDesc::char_field(int offset) const { return (jchar) *char_field_addr(offset); } 334133359Sobrieninline void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } 335133359Sobrien 336133359Sobrieninline jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); } 337133359Sobrieninline void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; } 338133359Sobrien 339169962Sobrieninline jshort oopDesc::short_field(int offset) const { return (jshort) *short_field_addr(offset); } 340169942Sobrieninline void oopDesc::short_field_put(int offset, jshort contents) { *short_field_addr(offset) = (jint) contents;} 341133359Sobrien 34268349Sobrieninline jlong oopDesc::long_field(int offset) const { return *long_field_addr(offset); } 343169962Sobrieninline void oopDesc::long_field_put(int offset, jlong contents) { *long_field_addr(offset) = contents; } 344133359Sobrien 345133359Sobrieninline jfloat oopDesc::float_field(int offset) const { return *float_field_addr(offset); } 346133359Sobrieninline void oopDesc::float_field_put(int offset, jfloat contents) { *float_field_addr(offset) = contents; } 347169942Sobrien 348133359Sobrieninline jdouble oopDesc::double_field(int offset) const { return *double_field_addr(offset); } 349133359Sobrieninline void oopDesc::double_field_put(int offset, jdouble contents) { *double_field_addr(offset) = contents; } 350133359Sobrien 351133359Sobrieninline address oopDesc::address_field(int offset) const { return *address_field_addr(offset); } 35268349Sobrieninline void oopDesc::address_field_put(int offset, address contents) { *address_field_addr(offset) = contents; } 35368349Sobrien 35468349Sobrieninline oop oopDesc::obj_field_acquire(int offset) const { 35568349Sobrien return UseCompressedOops ? 356133359Sobrien decode_heap_oop((narrowOop) 357133359Sobrien OrderAccess::load_acquire(obj_field_addr<narrowOop>(offset))) 358133359Sobrien : decode_heap_oop((oop) 359169942Sobrien OrderAccess::load_ptr_acquire(obj_field_addr<oop>(offset))); 360169942Sobrien} 361133359Sobrieninline void oopDesc::release_obj_field_put(int offset, oop value) { 362133359Sobrien UseCompressedOops ? 363169942Sobrien oop_store((volatile narrowOop*)obj_field_addr<narrowOop>(offset), value) : 364133359Sobrien oop_store((volatile oop*) obj_field_addr<oop>(offset), value); 365133359Sobrien} 366133359Sobrien 367169942Sobrieninline jbyte oopDesc::byte_field_acquire(int offset) const { return OrderAccess::load_acquire(byte_field_addr(offset)); } 368133359Sobrieninline void oopDesc::release_byte_field_put(int offset, jbyte contents) { OrderAccess::release_store(byte_field_addr(offset), contents); } 369133359Sobrien 370133359Sobrieninline jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } 37168349Sobrieninline void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); } 37268349Sobrien 373133359Sobrieninline jchar oopDesc::char_field_acquire(int offset) const { return OrderAccess::load_acquire(char_field_addr(offset)); } 374133359Sobrieninline void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } 375133359Sobrien 376133359Sobrieninline jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); } 37768349Sobrieninline void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); } 37868349Sobrien 379133359Sobrieninline jshort oopDesc::short_field_acquire(int offset) const { return (jshort)OrderAccess::load_acquire(short_field_addr(offset)); } 380133359Sobrieninline void oopDesc::release_short_field_put(int offset, jshort contents) { OrderAccess::release_store(short_field_addr(offset), contents); } 381133359Sobrien 382133359Sobrieninline jlong oopDesc::long_field_acquire(int offset) const { return OrderAccess::load_acquire(long_field_addr(offset)); } 383133359Sobrieninline void oopDesc::release_long_field_put(int offset, jlong contents) { OrderAccess::release_store(long_field_addr(offset), contents); } 384133359Sobrien 385133359Sobrieninline jfloat oopDesc::float_field_acquire(int offset) const { return OrderAccess::load_acquire(float_field_addr(offset)); } 38668349Sobrieninline void oopDesc::release_float_field_put(int offset, jfloat contents) { OrderAccess::release_store(float_field_addr(offset), contents); } 387133359Sobrien 38868349Sobrieninline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); } 38968349Sobrieninline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); } 390169942Sobrien 391169942Sobrieninline address oopDesc::address_field_acquire(int offset) const { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); } 392169942Sobrieninline void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store_ptr(address_field_addr(offset), contents); } 393159764Sobrien 394159764Sobrieninline int oopDesc::size_given_klass(Klass* klass) { 395159764Sobrien int lh = klass->layout_helper(); 396169942Sobrien int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize 397169942Sobrien 398169942Sobrien // lh is now a value computed at class initialization that may hint 399159764Sobrien // at the size. For instances, this is positive and equal to the 400169962Sobrien // size. For arrays, this is negative and provides log2 of the 401169962Sobrien // array element size. For other oops, it is zero and thus requires 402169962Sobrien // a virtual call. 403159764Sobrien // 404169942Sobrien // We go to all this trouble because the size computation is at the 405169942Sobrien // heart of phase 2 of mark-compaction, and called for every object, 406159764Sobrien // alive or dead. So the speed here is equal in importance to the 407159764Sobrien // speed of allocation. 408159764Sobrien 409159764Sobrien if (lh <= Klass::_lh_neutral_value) { 410169942Sobrien // The most common case is instances; fall through if so. 411169942Sobrien if (lh < Klass::_lh_neutral_value) { 412159764Sobrien // Second most common case is arrays. We have to fetch the 413159764Sobrien // length of the array, shift (multiply) it appropriately, 414159764Sobrien // up to wordSize, add the header, and align to object size. 415159764Sobrien size_t size_in_bytes; 416159764Sobrien#ifdef _M_IA64 417169942Sobrien // The Windows Itanium Aug 2002 SDK hoists this load above 418169942Sobrien // the check for s < 0. An oop at the end of the heap will 419159764Sobrien // cause an access violation if this load is performed on a non 420159764Sobrien // array oop. Making the reference volatile prohibits this. 421159764Sobrien // (%%% please explain by what magic the length is actually fetched!) 422169942Sobrien volatile int *array_length; 423169942Sobrien array_length = (volatile int *)( (intptr_t)this + 424169942Sobrien arrayOopDesc::length_offset_in_bytes() ); 425159764Sobrien assert(array_length > 0, "Integer arithmetic problem somewhere"); 426159764Sobrien // Put into size_t to avoid overflow. 427169942Sobrien size_in_bytes = (size_t) array_length; 428169942Sobrien size_in_bytes = size_in_bytes << Klass::layout_helper_log2_element_size(lh); 429169942Sobrien#else 430159764Sobrien size_t array_length = (size_t) ((arrayOop)this)->length(); 431169942Sobrien size_in_bytes = array_length << Klass::layout_helper_log2_element_size(lh); 432169942Sobrien#endif 433169942Sobrien size_in_bytes += Klass::layout_helper_header_size(lh); 434159764Sobrien 435159764Sobrien // This code could be simplified, but by keeping array_header_in_bytes 436159764Sobrien // in units of bytes and doing it this way we can round up just once, 437159764Sobrien // skipping the intermediate round to HeapWordSize. Cast the result 438159764Sobrien // of round_to to size_t to guarantee unsigned division == right shift. 439159764Sobrien s = (int)((size_t)round_to(size_in_bytes, MinObjAlignmentInBytes) / 440159764Sobrien HeapWordSize); 441159764Sobrien 442159764Sobrien // UseParNewGC, UseParallelGC and UseG1GC can change the length field 443175296Sobrien // of an "old copy" of an object array in the young gen so it indicates 444175296Sobrien // the grey portion of an already copied array. This will cause the first 445175296Sobrien // disjunct below to fail if the two comparands are computed across such 446169942Sobrien // a concurrent change. 447169942Sobrien // UseParNewGC also runs with promotion labs (which look like int 448159764Sobrien // filler arrays) which are subject to changing their declared size 449169942Sobrien // when finally retiring a PLAB; this also can cause the first disjunct 450169942Sobrien // to fail for another worker thread that is concurrently walking the block 451169942Sobrien // offset table. Both these invariant failures are benign for their 452169942Sobrien // current uses; we relax the assertion checking to cover these two cases below: 453169942Sobrien // is_objArray() && is_forwarded() // covers first scenario above 454169942Sobrien // || is_typeArray() // covers second scenario above 455169942Sobrien // If and when UseParallelGC uses the same obj array oop stealing/chunking 456169942Sobrien // technique, we will need to suitably modify the assertion. 457169942Sobrien assert((s == klass->oop_size(this)) || 458175296Sobrien (Universe::heap()->is_gc_active() && 459175296Sobrien ((is_typeArray() && UseParNewGC) || 460175296Sobrien (is_objArray() && is_forwarded() && (UseParNewGC || UseParallelGC || UseG1GC)))), 461169942Sobrien "wrong array object size"); 462169942Sobrien } else { 463169942Sobrien // Must be zero, so bite the bullet and take the virtual call. 464159764Sobrien s = klass->oop_size(this); 465169942Sobrien } 466169942Sobrien } 467169942Sobrien 468159764Sobrien assert(s % MinObjAlignment == 0, "alignment check"); 469169942Sobrien assert(s > 0, "Bad size calculated"); 470169942Sobrien return s; 471169942Sobrien} 472169942Sobrien 473169942Sobrien 474169942Sobrieninline int oopDesc::size() { 475169942Sobrien return size_given_klass(blueprint()); 476169942Sobrien} 477169942Sobrien 478169942Sobrieninline bool oopDesc::is_parsable() { 479169942Sobrien return blueprint()->oop_is_parsable(this); 480169942Sobrien} 481169942Sobrien 482169942Sobrieninline bool oopDesc::is_conc_safe() { 483169942Sobrien return blueprint()->oop_is_conc_safe(this); 484169942Sobrien} 485169942Sobrien 486169942Sobrieninline void update_barrier_set(void* p, oop v) { 487169942Sobrien assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); 488169942Sobrien oopDesc::bs()->write_ref_field(p, v); 489169942Sobrien} 490169942Sobrien 491169942Sobrientemplate <class T> inline void update_barrier_set_pre(T* p, oop v) { 492169942Sobrien oopDesc::bs()->write_ref_field_pre(p, v); 493169942Sobrien} 494169962Sobrien 495169962Sobrientemplate <class T> inline void oop_store(T* p, oop v) { 496169962Sobrien if (always_do_update_barrier) { 497169962Sobrien oop_store((volatile T*)p, v); 498169942Sobrien } else { 499159764Sobrien update_barrier_set_pre(p, v); 500159764Sobrien oopDesc::encode_store_heap_oop(p, v); 501169942Sobrien update_barrier_set((void*)p, v); // cast away type 502169942Sobrien } 503169942Sobrien} 504159764Sobrien 505159764Sobrientemplate <class T> inline void oop_store(volatile T* p, oop v) { 506159764Sobrien update_barrier_set_pre((T*)p, v); // cast away volatile 507159764Sobrien // Used by release_obj_field_put, so use release_store_ptr. 508159764Sobrien oopDesc::release_encode_store_heap_oop(p, v); 509159764Sobrien update_barrier_set((void*)p, v); // cast away type 510159764Sobrien} 511159764Sobrien 512159764Sobrientemplate <class T> inline void oop_store_without_check(T* p, oop v) { 513159764Sobrien // XXX YSR FIX ME!!! 514159764Sobrien if (always_do_update_barrier) { 515159764Sobrien oop_store(p, v); 516159764Sobrien } else { 517159764Sobrien assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier(p, v), 518159764Sobrien "oop store without store check failed"); 51974784Sobrien oopDesc::encode_store_heap_oop(p, v); 52074784Sobrien } 521103373Sobrien} 52274784Sobrien 523133359Sobrien// When it absolutely has to get there. 524133359Sobrientemplate <class T> inline void oop_store_without_check(volatile T* p, oop v) { 525133359Sobrien // XXX YSR FIX ME!!! 52668349Sobrien if (always_do_update_barrier) { 527133359Sobrien oop_store(p, v); 52868349Sobrien } else { 52968349Sobrien assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier((T*)p, v), 530175296Sobrien "oop store without store check failed"); 53168349Sobrien oopDesc::release_encode_store_heap_oop(p, v); 532159764Sobrien } 533169942Sobrien} 534169942Sobrien 53568349Sobrien// Should replace *addr = oop assignments where addr type depends on UseCompressedOops 536169942Sobrien// (without having to remember the function name this calls). 537169942Sobrieninline void oop_store_raw(HeapWord* addr, oop value) { 538139368Sobrien if (UseCompressedOops) { 53974784Sobrien oopDesc::encode_store_heap_oop((narrowOop*)addr, value); 54068349Sobrien } else { 541133359Sobrien oopDesc::encode_store_heap_oop((oop*)addr, value); 542133359Sobrien } 54368349Sobrien} 54468349Sobrien 54568349Sobrien// Used only for markSweep, scavenging 546169942Sobrieninline bool oopDesc::is_gc_marked() const { 547159825Sobrien return mark()->is_marked(); 548133359Sobrien} 549169942Sobrien 550133359Sobrieninline bool oopDesc::is_locked() const { 55174784Sobrien return mark()->is_locked(); 552159764Sobrien} 55374784Sobrien 554133359Sobrieninline bool oopDesc::is_unlocked() const { 555133359Sobrien return mark()->is_unlocked(); 556133359Sobrien} 557133359Sobrien 558169942Sobrieninline bool oopDesc::has_bias_pattern() const { 559175296Sobrien return mark()->has_bias_pattern(); 560139368Sobrien} 561139368Sobrien 562169942Sobrien 56368349Sobrien// used only for asserts 564169942Sobrieninline bool oopDesc::is_oop(bool ignore_mark_word) const { 565169942Sobrien oop obj = (oop) this; 566159764Sobrien if (!check_obj_alignment(obj)) return false; 567169942Sobrien if (!Universe::heap()->is_in_reserved(obj)) return false; 568169942Sobrien // obj is aligned and accessible in heap 569169942Sobrien // try to find metaclass cycle safely without seg faulting on bad input 570169942Sobrien // we should reach klassKlassObj by following klass link at most 3 times 571169942Sobrien for (int i = 0; i < 3; i++) { 572169942Sobrien obj = obj->klass_or_null(); 573159764Sobrien // klass should be aligned and in permspace 57468349Sobrien if (!check_obj_alignment(obj)) return false; 57568349Sobrien if (!Universe::heap()->is_in_permanent(obj)) return false; 576133359Sobrien } 577159764Sobrien if (obj != Universe::klassKlassObj()) { 578159764Sobrien // During a dump, the _klassKlassObj moved to a shared space. 579159764Sobrien if (DumpSharedSpaces && Universe::klassKlassObj()->is_shared()) { 580159764Sobrien return true; 581159764Sobrien } 582169962Sobrien return false; 583169962Sobrien } 584169962Sobrien 585169962Sobrien // Header verification: the mark is typically non-NULL. If we're 586169962Sobrien // at a safepoint, it must not be null. 587169962Sobrien // Outside of a safepoint, the header could be changing (for example, 588169962Sobrien // another thread could be inflating a lock on this object). 589169962Sobrien if (ignore_mark_word) { 590169962Sobrien return true; 591169962Sobrien } 592169962Sobrien if (mark() != NULL) { 593169962Sobrien return true; 594169962Sobrien } 595169962Sobrien return !SafepointSynchronize::is_at_safepoint(); 596169962Sobrien} 597169962Sobrien 598169962Sobrien 599159764Sobrien// used only for asserts 600159764Sobrieninline bool oopDesc::is_oop_or_null(bool ignore_mark_word) const { 601169942Sobrien return this == NULL ? true : is_oop(ignore_mark_word); 602159764Sobrien} 603159764Sobrien 604159764Sobrien#ifndef PRODUCT 605169942Sobrien// used only for asserts 606159764Sobrieninline bool oopDesc::is_unlocked_oop() const { 607159764Sobrien if (!Universe::heap()->is_in_reserved(this)) return false; 608159764Sobrien return mark()->is_unlocked(); 609159764Sobrien} 610159764Sobrien#endif // PRODUCT 611159764Sobrien 612159764Sobrieninline void oopDesc::follow_header() { 613159764Sobrien if (UseCompressedOops) { 614159764Sobrien MarkSweep::mark_and_push(compressed_klass_addr()); 615159764Sobrien } else { 616159764Sobrien MarkSweep::mark_and_push(klass_addr()); 617159764Sobrien } 618159764Sobrien} 619159764Sobrien 62074784Sobrieninline void oopDesc::follow_contents(void) { 62174784Sobrien assert (is_gc_marked(), "should be marked"); 62274784Sobrien blueprint()->oop_follow_contents(this); 623159764Sobrien} 624159764Sobrien 625159764Sobrien 626159764Sobrien// Used by scavengers 62774784Sobrien 628159764Sobrieninline bool oopDesc::is_forwarded() const { 62968349Sobrien // The extra heap check is needed since the obj might be locked, in which case the 63068349Sobrien // mark would point to a stack location and have the sentinel bit cleared 63168349Sobrien return mark()->is_marked(); 63268349Sobrien} 63368349Sobrien 634169942Sobrien// Used by scavengers 635169942Sobrieninline void oopDesc::forward_to(oop p) { 63668349Sobrien assert(check_obj_alignment(p), 637169962Sobrien "forwarding to something not aligned"); 63868349Sobrien assert(Universe::heap()->is_in_reserved(p), 63968349Sobrien "forwarding to something not in heap"); 64068349Sobrien markOop m = markOopDesc::encode_pointer_as_mark(p); 64168349Sobrien assert(m->decode_pointer() == p, "encoding must be reversable"); 64268349Sobrien set_mark(m); 64368349Sobrien} 644133359Sobrien 64568349Sobrien// Used by parallel scavengers 64668349Sobrieninline bool oopDesc::cas_forward_to(oop p, markOop compare) { 647133359Sobrien assert(check_obj_alignment(p), 648133359Sobrien "forwarding to something not aligned"); 649133359Sobrien assert(Universe::heap()->is_in_reserved(p), 65068349Sobrien "forwarding to something not in heap"); 65168349Sobrien markOop m = markOopDesc::encode_pointer_as_mark(p); 652133359Sobrien assert(m->decode_pointer() == p, "encoding must be reversable"); 653133359Sobrien return cas_set_mark(m, compare) == compare; 654133359Sobrien} 655159764Sobrien 656133359Sobrien// Note that the forwardee is not the same thing as the displaced_mark. 657133359Sobrien// The forwardee is used when copying during scavenge and mark-sweep. 658133359Sobrien// It does need to clear the low two locking- and GC-related bits. 659159764Sobrieninline oop oopDesc::forwardee() const { 660133359Sobrien return (oop) mark()->decode_pointer(); 661133359Sobrien} 662133359Sobrien 663159764Sobrieninline bool oopDesc::has_displaced_mark() const { 664175296Sobrien return mark()->has_displaced_mark_helper(); 665175296Sobrien} 666175296Sobrien 667103373Sobrieninline markOop oopDesc::displaced_mark() const { 66868349Sobrien return mark()->displaced_mark_helper(); 669169942Sobrien} 670169942Sobrien 671169942Sobrieninline void oopDesc::set_displaced_mark(markOop m) { 672169942Sobrien mark()->set_displaced_mark_helper(m); 673169942Sobrien} 674169942Sobrien 675169942Sobrien// The following method needs to be MT safe. 676169942Sobrieninline int oopDesc::age() const { 677169942Sobrien assert(!is_forwarded(), "Attempt to read age from forwarded mark"); 678175296Sobrien if (has_displaced_mark()) { 679175296Sobrien return displaced_mark()->age(); 680175296Sobrien } else { 681169942Sobrien return mark()->age(); 682169942Sobrien } 683133359Sobrien} 684133359Sobrien 685139368Sobrieninline void oopDesc::incr_age() { 686139368Sobrien assert(!is_forwarded(), "Attempt to increment age of forwarded mark"); 687133359Sobrien if (has_displaced_mark()) { 688159764Sobrien set_displaced_mark(displaced_mark()->incr_age()); 689169962Sobrien } else { 690103373Sobrien set_mark(mark()->incr_age()); 69168349Sobrien } 692133359Sobrien} 693139368Sobrien 694133359Sobrien 695133359Sobrieninline intptr_t oopDesc::identity_hash() { 69668349Sobrien // Fast case; if the object is unlocked and the hash value is set, no locking is needed 697169962Sobrien // Note: The mark must be read into local variable to avoid concurrent updates. 69868349Sobrien markOop mrk = mark(); 69968349Sobrien if (mrk->is_unlocked() && !mrk->has_no_hash()) { 70068349Sobrien return mrk->hash(); 701169962Sobrien } else if (mrk->is_marked()) { 702169962Sobrien return mrk->hash(); 703169962Sobrien } else { 704169962Sobrien return slow_identity_hash(); 705169962Sobrien } 706169962Sobrien} 707169962Sobrien 708169962Sobrieninline void oopDesc::oop_iterate_header(OopClosure* blk) { 709169962Sobrien if (UseCompressedOops) { 710169962Sobrien blk->do_oop(compressed_klass_addr()); 711169962Sobrien } else { 712169962Sobrien blk->do_oop(klass_addr()); 713169962Sobrien } 714169962Sobrien} 715169962Sobrien 716169962Sobrieninline void oopDesc::oop_iterate_header(OopClosure* blk, MemRegion mr) { 717169962Sobrien if (UseCompressedOops) { 718169962Sobrien if (mr.contains(compressed_klass_addr())) { 719169962Sobrien blk->do_oop(compressed_klass_addr()); 720169962Sobrien } 721169962Sobrien } else { 722169962Sobrien if (mr.contains(klass_addr())) blk->do_oop(klass_addr()); 723169962Sobrien } 724169962Sobrien} 725169962Sobrien 726169962Sobrieninline int oopDesc::adjust_pointers() { 727169962Sobrien debug_only(int check_size = size()); 728169962Sobrien int s = blueprint()->oop_adjust_pointers(this); 729169962Sobrien assert(s == check_size, "should be the same"); 730169962Sobrien return s; 731169962Sobrien} 732169962Sobrien 733169962Sobrieninline void oopDesc::adjust_header() { 734169962Sobrien if (UseCompressedOops) { 735169962Sobrien MarkSweep::adjust_pointer(compressed_klass_addr()); 736169962Sobrien } else { 737169962Sobrien MarkSweep::adjust_pointer(klass_addr()); 738169962Sobrien } 739169962Sobrien} 740169962Sobrien 741169962Sobrien#define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ 742169962Sobrien \ 743169962Sobrieninline int oopDesc::oop_iterate(OopClosureType* blk) { \ 744169962Sobrien SpecializationStats::record_call(); \ 745169962Sobrien return blueprint()->oop_oop_iterate##nv_suffix(this, blk); \ 746169962Sobrien} \ 747169962Sobrien \ 748169962Sobrieninline int oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) { \ 749169962Sobrien SpecializationStats::record_call(); \ 750169962Sobrien return blueprint()->oop_oop_iterate##nv_suffix##_m(this, blk, mr); \ 751169962Sobrien} 752169962Sobrien 753169962SobrienALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN) 754169962SobrienALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN) 755169962Sobrien 756169962Sobrien#ifndef SERIALGC 757169962Sobrien#define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ 758169962Sobrien \ 759169962Sobrieninline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ 760169962Sobrien SpecializationStats::record_call(); \ 761169962Sobrien return blueprint()->oop_oop_iterate_backwards##nv_suffix(this, blk); \ 762169962Sobrien} 763169962Sobrien 764169962SobrienALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN) 765169962SobrienALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN) 766169962Sobrien#endif // !SERIALGC 767169962Sobrien 768169962Sobrieninline bool oopDesc::is_shared() const { 769169962Sobrien return CompactingPermGenGen::is_shared(this); 770169962Sobrien} 771169962Sobrien 772169962Sobrieninline bool oopDesc::is_shared_readonly() const { 773169962Sobrien return CompactingPermGenGen::is_shared_readonly(this); 774169962Sobrien} 775169962Sobrien 776169962Sobrieninline bool oopDesc::is_shared_readwrite() const { 777169962Sobrien return CompactingPermGenGen::is_shared_readwrite(this); 778169962Sobrien} 779169962Sobrien 780169962Sobrien#endif // SHARE_VM_OOPS_OOP_INLINE_HPP 781169962Sobrien