Mercurial > hg > graal-compiler
diff src/share/vm/oops/oop.inline.hpp @ 6948:e522a00b91aa
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/ after NPG - C++ build works
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 12 Nov 2012 23:14:12 +0100 |
parents | 04b9a2566eec 8e47bac5643a |
children | 5fc51c1ecdeb |
line wrap: on
line diff
--- a/src/share/vm/oops/oop.inline.hpp Mon Nov 12 18:11:17 2012 +0100 +++ b/src/share/vm/oops/oop.inline.hpp Mon Nov 12 23:14:12 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,15 +30,12 @@ #include "gc_interface/collectedHeap.inline.hpp" #include "memory/barrierSet.inline.hpp" #include "memory/cardTableModRefBS.hpp" -#include "memory/compactingPermGenGen.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/generation.hpp" -#include "memory/permGen.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/arrayKlass.hpp" #include "oops/arrayOop.hpp" #include "oops/klass.hpp" -#include "oops/klassOop.hpp" #include "oops/markOop.inline.hpp" #include "oops/oop.hpp" #include "runtime/atomic.hpp" @@ -70,48 +67,48 @@ return (markOop) Atomic::cmpxchg_ptr(new_mark, &_mark, old_mark); } -inline klassOop oopDesc::klass() const { - if (UseCompressedOops) { - return (klassOop)decode_heap_oop_not_null(_metadata._compressed_klass); +inline Klass* oopDesc::klass() const { + if (UseCompressedKlassPointers) { + return decode_klass_not_null(_metadata._compressed_klass); } else { return _metadata._klass; } } -inline klassOop oopDesc::klass_or_null() const volatile { +inline Klass* oopDesc::klass_or_null() const volatile { // can be NULL in CMS - if (UseCompressedOops) { - return (klassOop)decode_heap_oop(_metadata._compressed_klass); + if (UseCompressedKlassPointers) { + return decode_klass(_metadata._compressed_klass); } else { return _metadata._klass; } } inline int oopDesc::klass_gap_offset_in_bytes() { - assert(UseCompressedOops, "only applicable to compressed headers"); + assert(UseCompressedKlassPointers, "only applicable to compressed klass pointers"); return oopDesc::klass_offset_in_bytes() + sizeof(narrowOop); } -inline oop* oopDesc::klass_addr() { +inline Klass** oopDesc::klass_addr() { // Only used internally and with CMS and will not work with // UseCompressedOops - assert(!UseCompressedOops, "only supported with uncompressed oops"); - return (oop*) &_metadata._klass; + assert(!UseCompressedKlassPointers, "only supported with uncompressed klass pointers"); + return (Klass**) &_metadata._klass; } inline narrowOop* oopDesc::compressed_klass_addr() { - assert(UseCompressedOops, "only called by compressed oops"); + assert(UseCompressedKlassPointers, "only called by compressed klass pointers"); return (narrowOop*) &_metadata._compressed_klass; } -inline void oopDesc::set_klass(klassOop k) { +inline void oopDesc::set_klass(Klass* k) { // since klasses are promoted no store check is needed - assert(Universe::is_bootstrapping() || k != NULL, "must be a real klassOop"); - assert(Universe::is_bootstrapping() || k->is_klass(), "not a klassOop"); - if (UseCompressedOops) { - oop_store_without_check(compressed_klass_addr(), (oop)k); + assert(Universe::is_bootstrapping() || k != NULL, "must be a real Klass*"); + assert(Universe::is_bootstrapping() || k->is_klass(), "not a Klass*"); + if (UseCompressedKlassPointers) { + *compressed_klass_addr() = encode_klass_not_null(k); } else { - oop_store_without_check(klass_addr(), (oop) k); + *klass_addr() = k; } } @@ -120,7 +117,7 @@ } inline void oopDesc::set_klass_gap(int v) { - if (UseCompressedOops) { + if (UseCompressedKlassPointers) { *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()) = v; } } @@ -128,37 +125,38 @@ inline void oopDesc::set_klass_to_list_ptr(oop k) { // This is only to be used during GC, for from-space objects, so no // barrier is needed. - if (UseCompressedOops) { + if (UseCompressedKlassPointers) { _metadata._compressed_klass = encode_heap_oop(k); // may be null (parnew overflow handling) } else { - _metadata._klass = (klassOop)k; + _metadata._klass = (Klass*)(address)k; + } +} + +inline oop oopDesc::list_ptr_from_klass() { + // This is only to be used during GC, for from-space objects. + if (UseCompressedKlassPointers) { + return decode_heap_oop(_metadata._compressed_klass); + } else { + // Special case for GC + return (oop)(address)_metadata._klass; } } inline void oopDesc::init_mark() { set_mark(markOopDesc::prototype_for_object(this)); } -inline Klass* oopDesc::blueprint() const { return klass()->klass_part(); } -inline bool oopDesc::is_a(klassOop k) const { return blueprint()->is_subtype_of(k); } +inline bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); } -inline bool oopDesc::is_instance() const { return blueprint()->oop_is_instance(); } -inline bool oopDesc::is_instanceMirror() const { return blueprint()->oop_is_instanceMirror(); } -inline bool oopDesc::is_instanceRef() const { return blueprint()->oop_is_instanceRef(); } -inline bool oopDesc::is_array() const { return blueprint()->oop_is_array(); } -inline bool oopDesc::is_objArray() const { return blueprint()->oop_is_objArray(); } -inline bool oopDesc::is_typeArray() const { return blueprint()->oop_is_typeArray(); } -inline bool oopDesc::is_javaArray() const { return blueprint()->oop_is_javaArray(); } -inline bool oopDesc::is_klass() const { return blueprint()->oop_is_klass(); } -inline bool oopDesc::is_thread() const { return blueprint()->oop_is_thread(); } -inline bool oopDesc::is_method() const { return blueprint()->oop_is_method(); } -inline bool oopDesc::is_constMethod() const { return blueprint()->oop_is_constMethod(); } -inline bool oopDesc::is_methodData() const { return blueprint()->oop_is_methodData(); } -inline bool oopDesc::is_constantPool() const { return blueprint()->oop_is_constantPool(); } -inline bool oopDesc::is_constantPoolCache() const { return blueprint()->oop_is_constantPoolCache(); } -inline bool oopDesc::is_compiledICHolder() const { return blueprint()->oop_is_compiledICHolder(); } +inline bool oopDesc::is_instance() const { return klass()->oop_is_instance(); } +inline bool oopDesc::is_instanceMirror() const { return klass()->oop_is_instanceMirror(); } +inline bool oopDesc::is_instanceRef() const { return klass()->oop_is_instanceRef(); } +inline bool oopDesc::is_array() const { return klass()->oop_is_array(); } +inline bool oopDesc::is_objArray() const { return klass()->oop_is_objArray(); } +inline bool oopDesc::is_typeArray() const { return klass()->oop_is_typeArray(); } inline void* oopDesc::field_base(int offset) const { return (void*)&((char*)this)[offset]; } template <class T> inline T* oopDesc::obj_field_addr(int offset) const { return (T*)field_base(offset); } +inline Metadata** oopDesc::metadata_field_addr(int offset) const { return (Metadata**)field_base(offset); } inline jbyte* oopDesc::byte_field_addr(int offset) const { return (jbyte*) field_base(offset); } inline jchar* oopDesc::char_field_addr(int offset) const { return (jchar*) field_base(offset); } inline jboolean* oopDesc::bool_field_addr(int offset) const { return (jboolean*)field_base(offset); } @@ -177,6 +175,7 @@ // the right type and inlines the appopriate code). inline bool oopDesc::is_null(oop obj) { return obj == NULL; } +inline bool oopDesc::is_null(Klass* obj) { return obj == NULL; } inline bool oopDesc::is_null(narrowOop obj) { return obj == 0; } // Algorithm for encoding and decoding oops from 64 bit pointers to 32 bit @@ -186,6 +185,9 @@ inline bool check_obj_alignment(oop obj) { return (intptr_t)obj % MinObjAlignmentInBytes == 0; } +inline bool check_klass_alignment(Klass* obj) { + return (intptr_t)obj % KlassAlignmentInBytes == 0; +} inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { assert(!is_null(v), "oop value can never be zero"); @@ -221,6 +223,39 @@ inline oop oopDesc::decode_heap_oop_not_null(oop v) { return v; } inline oop oopDesc::decode_heap_oop(oop v) { return v; } +// Encoding and decoding for klass field. It is copied code, but someday +// might not be the same as oop. + +inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { + assert(!is_null(v), "oop value can never be zero"); + assert(check_klass_alignment(v), "Address not aligned"); + address base = Universe::narrow_klass_base(); + int shift = Universe::narrow_klass_shift(); + uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); + assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + uint64_t result = pd >> shift; + assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); + assert(decode_klass(result) == v, "reversibility"); + return (narrowOop)result; +} + +inline narrowOop oopDesc::encode_klass(Klass* v) { + return (is_null(v)) ? (narrowOop)0 : encode_klass_not_null(v); +} + +inline Klass* oopDesc::decode_klass_not_null(narrowOop v) { + assert(!is_null(v), "narrow oop value can never be zero"); + address base = Universe::narrow_klass_base(); + int shift = Universe::narrow_klass_shift(); + Klass* result = (Klass*)(void*)((uintptr_t)base + ((uintptr_t)v << shift)); + assert(check_klass_alignment(result), err_msg("address not aligned: " PTR_FORMAT, (void*) result)); + return result; +} + +inline Klass* oopDesc::decode_klass(narrowOop v) { + return is_null(v) ? (Klass*)NULL : decode_klass_not_null(v); +} + // Load an oop out of the Java heap as is without decoding. // Called by GC to check for null before decoding. inline oop oopDesc::load_heap_oop(oop* p) { return *p; } @@ -298,22 +333,6 @@ } } -inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value, - volatile HeapWord *dest, - oop compare_value) { - if (UseCompressedOops) { - // encode exchange and compare value from oop to T - narrowOop val = encode_heap_oop(exchange_value); - narrowOop cmp = encode_heap_oop(compare_value); - - narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp); - // decode old from T to oop - return decode_heap_oop(old); - } else { - return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value); - } -} - // In order to put or get a field out of an instance, must first check // if the field has been compressed and uncompress it. inline oop oopDesc::obj_field(int offset) const { @@ -330,6 +349,15 @@ UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) : oop_store(obj_field_addr<oop>(offset), value); } + +inline Metadata* oopDesc::metadata_field(int offset) const { + return *metadata_field_addr(offset); +} + +inline void oopDesc::metadata_field_put(int offset, Metadata* value) { + *metadata_field_addr(offset) = value; +} + inline void oopDesc::obj_field_put_raw(int offset, oop value) { UseCompressedOops ? encode_store_heap_oop(obj_field_addr<narrowOop>(offset), value) : @@ -495,15 +523,7 @@ inline int oopDesc::size() { - return size_given_klass(blueprint()); -} - -inline bool oopDesc::is_parsable() { - return blueprint()->oop_is_parsable(this); -} - -inline bool oopDesc::is_conc_safe() { - return blueprint()->oop_is_conc_safe(this); + return size_given_klass(klass()); } inline void update_barrier_set(void* p, oop v) { @@ -532,29 +552,6 @@ update_barrier_set((void*)p, v); // cast away type } -template <class T> inline void oop_store_without_check(T* p, oop v) { - // XXX YSR FIX ME!!! - if (always_do_update_barrier) { - oop_store(p, v); - } else { - assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier(p, v), - "oop store without store check failed"); - oopDesc::encode_store_heap_oop(p, v); - } -} - -// When it absolutely has to get there. -template <class T> inline void oop_store_without_check(volatile T* p, oop v) { - // XXX YSR FIX ME!!! - if (always_do_update_barrier) { - oop_store(p, v); - } else { - assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier((T*)p, v), - "oop store without store check failed"); - oopDesc::release_encode_store_heap_oop(p, v); - } -} - // Should replace *addr = oop assignments where addr type depends on UseCompressedOops // (without having to remember the function name this calls). inline void oop_store_raw(HeapWord* addr, oop value) { @@ -565,6 +562,29 @@ } } +inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value, + volatile HeapWord *dest, + oop compare_value, + bool prebarrier) { + if (UseCompressedOops) { + if (prebarrier) { + update_barrier_set_pre((narrowOop*)dest, exchange_value); + } + // encode exchange and compare value from oop to T + narrowOop val = encode_heap_oop(exchange_value); + narrowOop cmp = encode_heap_oop(compare_value); + + narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp); + // decode old from T to oop + return decode_heap_oop(old); + } else { + if (prebarrier) { + update_barrier_set_pre((oop*)dest, exchange_value); + } + return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value); + } +} + // Used only for markSweep, scavenging inline bool oopDesc::is_gc_marked() const { return mark()->is_marked(); @@ -589,21 +609,7 @@ if (!check_obj_alignment(obj)) return false; if (!Universe::heap()->is_in_reserved(obj)) return false; // obj is aligned and accessible in heap - // try to find metaclass cycle safely without seg faulting on bad input - // we should reach klassKlassObj by following klass link at most 3 times - for (int i = 0; i < 3; i++) { - obj = obj->klass_or_null(); - // klass should be aligned and in permspace - if (!check_obj_alignment(obj)) return false; - if (!Universe::heap()->is_in_permanent(obj)) return false; - } - if (obj != Universe::klassKlassObj()) { - // During a dump, the _klassKlassObj moved to a shared space. - if (DumpSharedSpaces && Universe::klassKlassObj()->is_shared()) { - return true; - } - return false; - } + if (Universe::heap()->is_in_reserved(obj->klass_or_null())) return false; // Header verification: the mark is typically non-NULL. If we're // at a safepoint, it must not be null. @@ -632,20 +638,11 @@ } #endif // PRODUCT -inline void oopDesc::follow_header() { - if (UseCompressedOops) { - MarkSweep::mark_and_push(compressed_klass_addr()); - } else { - MarkSweep::mark_and_push(klass_addr()); - } -} - inline void oopDesc::follow_contents(void) { assert (is_gc_marked(), "should be marked"); - blueprint()->oop_follow_contents(this); + klass()->oop_follow_contents(this); } - // Used by scavengers inline bool oopDesc::is_forwarded() const { @@ -696,7 +693,7 @@ } // The following method needs to be MT safe. -inline int oopDesc::age() const { +inline uint oopDesc::age() const { assert(!is_forwarded(), "Attempt to read age from forwarded mark"); if (has_displaced_mark()) { return displaced_mark()->age(); @@ -728,49 +725,36 @@ } } -inline void oopDesc::oop_iterate_header(OopClosure* blk) { - if (UseCompressedOops) { - blk->do_oop(compressed_klass_addr()); - } else { - blk->do_oop(klass_addr()); - } -} - -inline void oopDesc::oop_iterate_header(OopClosure* blk, MemRegion mr) { - if (UseCompressedOops) { - if (mr.contains(compressed_klass_addr())) { - blk->do_oop(compressed_klass_addr()); - } - } else { - if (mr.contains(klass_addr())) blk->do_oop(klass_addr()); - } -} - inline int oopDesc::adjust_pointers() { debug_only(int check_size = size()); - int s = blueprint()->oop_adjust_pointers(this); + int s = klass()->oop_adjust_pointers(this); assert(s == check_size, "should be the same"); return s; } -inline void oopDesc::adjust_header() { - if (UseCompressedOops) { - MarkSweep::adjust_pointer(compressed_klass_addr()); - } else { - MarkSweep::adjust_pointer(klass_addr()); - } -} - #define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ inline int oopDesc::oop_iterate(OopClosureType* blk) { \ SpecializationStats::record_call(); \ - return blueprint()->oop_oop_iterate##nv_suffix(this, blk); \ + return klass()->oop_oop_iterate##nv_suffix(this, blk); \ } \ \ inline int oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) { \ SpecializationStats::record_call(); \ - return blueprint()->oop_oop_iterate##nv_suffix##_m(this, blk, mr); \ + return klass()->oop_oop_iterate##nv_suffix##_m(this, blk, mr); \ +} + + +inline int oopDesc::oop_iterate_no_header(OopClosure* blk) { + // The NoHeaderExtendedOopClosure wraps the OopClosure and proxies all + // the do_oop calls, but turns off all other features in ExtendedOopClosure. + NoHeaderExtendedOopClosure cl(blk); + return oop_iterate(&cl); +} + +inline int oopDesc::oop_iterate_no_header(OopClosure* blk, MemRegion mr) { + NoHeaderExtendedOopClosure cl(blk); + return oop_iterate(&cl, mr); } ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN) @@ -781,23 +765,11 @@ \ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ SpecializationStats::record_call(); \ - return blueprint()->oop_oop_iterate_backwards##nv_suffix(this, blk); \ + return klass()->oop_oop_iterate_backwards##nv_suffix(this, blk); \ } ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN) #endif // !SERIALGC -inline bool oopDesc::is_shared() const { - return CompactingPermGenGen::is_shared(this); -} - -inline bool oopDesc::is_shared_readonly() const { - return CompactingPermGenGen::is_shared_readonly(this); -} - -inline bool oopDesc::is_shared_readwrite() const { - return CompactingPermGenGen::is_shared_readwrite(this); -} - #endif // SHARE_VM_OOPS_OOP_INLINE_HPP