--- old/src/share/vm/gc/serial/markSweep.cpp 2017-04-25 11:32:43.560875124 +0200 +++ new/src/share/vm/gc/serial/markSweep.cpp 2017-04-25 11:32:43.412869306 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -224,12 +224,12 @@ mark_and_push_closure.set_ref_processor(_ref_processor); } -MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure; +AdjustPointerClosure MarkSweep::adjust_pointer_closure; template -void MarkSweep::AdjustPointerClosure::do_oop_nv(T* p) { adjust_pointer(p); } -void MarkSweep::AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); } -void MarkSweep::AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); } +void AdjustPointerClosure::do_oop_nv(T* p) { MarkSweep::adjust_pointer(p); } +void AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); } +void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); } void MarkSweep::adjust_marks() { assert( _preserved_oop_stack.size() == _preserved_mark_stack.size(), @@ -280,79 +280,5 @@ MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); } -int InstanceKlass::oop_ms_adjust_pointers(oop obj) { - int size = size_helper(); - oop_oop_iterate_oop_maps(obj, &MarkSweep::adjust_pointer_closure); - return size; -} - -int InstanceMirrorKlass::oop_ms_adjust_pointers(oop obj) { - int size = oop_size(obj); - InstanceKlass::oop_ms_adjust_pointers(obj); - - oop_oop_iterate_statics(obj, &MarkSweep::adjust_pointer_closure); - return size; -} - -int InstanceClassLoaderKlass::oop_ms_adjust_pointers(oop obj) { - return InstanceKlass::oop_ms_adjust_pointers(obj); -} - -#ifdef ASSERT -template static void trace_reference_gc(const char *s, oop obj, - T* referent_addr, - T* next_addr, - T* discovered_addr) { - log_develop_trace(gc, ref)("%s obj " PTR_FORMAT, s, p2i(obj)); - log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(referent_addr), p2i(referent_addr ? (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL)); - log_develop_trace(gc, ref)(" next_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(next_addr), p2i(next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL)); - log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(discovered_addr), p2i(discovered_addr ? (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL)); -} -#endif - -template void static adjust_object_specialized(oop obj) { - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); - MarkSweep::adjust_pointer(referent_addr); - T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - MarkSweep::adjust_pointer(next_addr); - T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); - MarkSweep::adjust_pointer(discovered_addr); - debug_only(trace_reference_gc("InstanceRefKlass::oop_ms_adjust_pointers", obj, - referent_addr, next_addr, discovered_addr);) -} - -int InstanceRefKlass::oop_ms_adjust_pointers(oop obj) { - int size = size_helper(); - InstanceKlass::oop_ms_adjust_pointers(obj); - - if (UseCompressedOops) { - adjust_object_specialized(obj); - } else { - adjust_object_specialized(obj); - } - return size; -} - -int ObjArrayKlass::oop_ms_adjust_pointers(oop obj) { - assert(obj->is_objArray(), "obj must be obj array"); - objArrayOop a = objArrayOop(obj); - // Get size before changing pointers. - // Don't call size() or oop_size() since that is a virtual call. - int size = a->object_size(); - oop_oop_iterate_elements(a, &MarkSweep::adjust_pointer_closure); - return size; -} - -int TypeArrayKlass::oop_ms_adjust_pointers(oop obj) { - assert(obj->is_typeArray(), "must be a type array"); - typeArrayOop t = typeArrayOop(obj); - // Performance tweak: We skip iterating over the klass pointer since we - // know that Universe::TypeArrayKlass never moves. - return t->object_size(); -} - // Generate MS specialized oop_oop_iterate functions. SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(ALL_KLASS_OOP_OOP_ITERATE_DEFN) --- old/src/share/vm/gc/serial/markSweep.hpp 2017-04-25 11:32:44.216900911 +0200 +++ new/src/share/vm/gc/serial/markSweep.hpp 2017-04-25 11:32:44.068895093 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -50,6 +50,7 @@ // declared at end class PreservedMark; class MarkAndPushClosure; +class AdjustPointerClosure; class MarkSweep : AllStatic { // @@ -66,16 +67,6 @@ virtual void do_void(); }; - class AdjustPointerClosure: public OopsInGenClosure { - public: - template void do_oop_nv(T* p); - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); - - // This closure provides its own oop verification code. - debug_only(virtual bool should_verify_oops() { return false; }) - }; - // Used for java/lang/ref handling class IsAliveClosure: public BoolObjectClosure { public: @@ -201,6 +192,17 @@ } }; +class AdjustPointerClosure: public OopsInGenClosure { + public: + template void do_oop_nv(T* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; } + + // This closure provides its own oop verification code. + debug_only(virtual bool should_verify_oops() { return false; }) +}; + class PreservedMark VALUE_OBJ_CLASS_SPEC { private: oop _obj; --- old/src/share/vm/gc/serial/markSweep.inline.hpp 2017-04-25 11:32:44.832925126 +0200 +++ new/src/share/vm/gc/serial/markSweep.inline.hpp 2017-04-25 11:32:44.684919308 +0200 @@ -42,7 +42,7 @@ } inline int MarkSweep::adjust_pointers(oop obj) { - return obj->ms_adjust_pointers(); + return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure); } template inline void MarkSweep::adjust_pointer(T* p) { --- old/src/share/vm/gc/shared/specialized_oop_closures.hpp 2017-04-25 11:32:46.124975914 +0200 +++ new/src/share/vm/gc/shared/specialized_oop_closures.hpp 2017-04-25 11:32:45.980970253 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -44,6 +44,7 @@ class FilteringClosure; // MarkSweep class MarkAndPushClosure; +class AdjustPointerClosure; // ParNew class ParScanWithBarrierClosure; class ParScanWithoutBarrierClosure; @@ -90,7 +91,8 @@ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \ - f(MarkAndPushClosure,_nv) + f(MarkAndPushClosure,_nv) \ + f(AdjustPointerClosure,_nv) #if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \ --- old/src/share/vm/memory/iterator.hpp 2017-04-25 11:32:46.757000758 +0200 +++ new/src/share/vm/memory/iterator.hpp 2017-04-25 11:32:46.612995097 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -65,6 +65,16 @@ public: ReferenceProcessor* ref_processor() const { return _ref_processor; } + // Iteration of InstanceRefKlasses differ depending on the closure, + // the below enum describes the different alternatives. + enum ReferenceIterationMode { + DO_DISCOVERY, // Apply closure and discover references + DO_FIELDS // Apply closure to all fields + }; + + // The default iteration mode is to do discovery. + virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERY; } + // If the do_metadata functions return "true", // we invoke the following when running oop_iterate(): // --- old/src/share/vm/oops/instanceClassLoaderKlass.hpp 2017-04-25 11:32:47.389025601 +0200 +++ new/src/share/vm/oops/instanceClassLoaderKlass.hpp 2017-04-25 11:32:47.249020098 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -48,8 +48,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); --- old/src/share/vm/oops/instanceKlass.hpp 2017-04-25 11:32:48.077052647 +0200 +++ new/src/share/vm/oops/instanceKlass.hpp 2017-04-25 11:32:47.933046986 +0200 @@ -1163,8 +1163,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); --- old/src/share/vm/oops/instanceMirrorKlass.hpp 2017-04-25 11:32:48.805081264 +0200 +++ new/src/share/vm/oops/instanceMirrorKlass.hpp 2017-04-25 11:32:48.661075603 +0200 @@ -89,8 +89,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); --- old/src/share/vm/oops/instanceRefKlass.hpp 2017-04-25 11:32:49.453106737 +0200 +++ new/src/share/vm/oops/instanceRefKlass.hpp 2017-04-25 11:32:49.293100447 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -58,8 +58,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); @@ -107,6 +105,30 @@ template inline void oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure); + // Building blocks for specialized handling. + template + static void do_referent(oop obj, OopClosureType* closure, Contains& contains); + + template + static void do_next(oop obj, OopClosureType* closure, Contains& contains); + + template + static void do_discovered(oop obj, OopClosureType* closure, Contains& contains); + + template + static bool try_discover(oop obj, ReferenceType type, OopClosureType* closure); + + // Do discovery while handling InstanceRefKlasses. Reference discovery + // is only done if the closure provides a ReferenceProcessor. + template + static void oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains); + + // Apply the closure to all fields. No reference discovery is done. + template + static void oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains); + + template + static void trace_reference_gc(const char *s, oop obj, T* referent_addr, T* next_addr, T* discovered_addr) NOT_DEBUG_RETURN; public: --- old/src/share/vm/oops/instanceRefKlass.inline.hpp 2017-04-25 11:32:50.081131423 +0200 +++ new/src/share/vm/oops/instanceRefKlass.inline.hpp 2017-04-25 11:32:49.941125920 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -36,36 +36,96 @@ #include "utilities/macros.hpp" template -void InstanceRefKlass::oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains) { - T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); - if (closure->apply_to_weak_ref_discovered_field()) { - Devirtualizer::do_oop(closure, disc_addr); +void InstanceRefKlass::do_referent(oop obj, OopClosureType* closure, Contains& contains) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + if (contains(referent_addr)) { + Devirtualizer::do_oop(closure, referent_addr); } +} - T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); - T heap_oop = oopDesc::load_heap_oop(referent_addr); +template +void InstanceRefKlass::do_next(oop obj, OopClosureType* closure, Contains& contains) { + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (contains(next_addr)) { + Devirtualizer::do_oop(closure, next_addr); + } +} + +template +void InstanceRefKlass::do_discovered(oop obj, OopClosureType* closure, Contains& contains) { + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + if (contains(discovered_addr)) { + Devirtualizer::do_oop(closure, discovered_addr); + } +} + +template +bool InstanceRefKlass::try_discover(oop obj, ReferenceType type, OopClosureType* closure) { ReferenceProcessor* rp = closure->ref_processor(); - if (!oopDesc::is_null(heap_oop)) { - oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); - if (!referent->is_gc_marked() && (rp != NULL) && - rp->discover_reference(obj, reference_type())) { - return; - } else if (contains(referent_addr)) { - // treat referent as normal oop - Devirtualizer::do_oop(closure, referent_addr); + if (rp != NULL) { + T referent_oop = oopDesc::load_heap_oop((T*)java_lang_ref_Reference::referent_addr(obj)); + if (!oopDesc::is_null(referent_oop)) { + oop referent = oopDesc::decode_heap_oop_not_null(referent_oop); + if (!referent->is_gc_marked()) { + // Only try to discover if not yet marked. + return rp->discover_reference(obj, type); + } } } - T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - T next_oop = oopDesc::load_heap_oop(next_addr); - // Treat discovered as normal oop, if ref is not "active" (next non-NULL) - if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { - // i.e. ref is not "active" - log_develop_trace(gc, ref)(" Process discovered as normal " PTR_FORMAT, p2i(disc_addr)); - Devirtualizer::do_oop(closure, disc_addr); + return false; +} + +template +void InstanceRefKlass::oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains) { + log_develop_trace(gc, ref)("Process reference with discovery " PTR_FORMAT, p2i(obj)); + + // Special case for some closures. + if (closure->apply_to_weak_ref_discovered_field()) { + do_discovered(obj, closure, contains); } - // treat next as normal oop - if (contains(next_addr)) { - Devirtualizer::do_oop(closure, next_addr); + + // Try to discover reference and return if it succeeds. + if (try_discover(obj, type, closure)) { + return; + } + + // Treat referent as normal oop. + do_referent(obj, closure, contains); + + // Treat discovered as normal oop, if ref is not "active" (next non-NULL). + T next_oop = oopDesc::load_heap_oop((T*)java_lang_ref_Reference::next_addr(obj)); + if (!oopDesc::is_null(next_oop)) { + do_discovered(obj, closure, contains); + } + + // Treat next as normal oop. + do_next(obj, closure, contains); +} + +template +void InstanceRefKlass::oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains) { + do_referent(obj, closure, contains); + do_discovered(obj, closure, contains); + do_next(obj, closure, contains); + + trace_reference_gc("InstanceRefKlass::oop_oop_iterate_fields()", + obj, + (T*)java_lang_ref_Reference::referent_addr(obj), + (T*)java_lang_ref_Reference::next_addr(obj), + (T*)java_lang_ref_Reference::discovered_addr(obj)); +} + +template +void InstanceRefKlass::oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains) { + switch (closure->reference_iteration_mode()) { + case ExtendedOopClosure::DO_DISCOVERY: + oop_oop_iterate_discovery(obj, reference_type(), closure, contains); + break; + case ExtendedOopClosure::DO_FIELDS: + oop_oop_iterate_fields(obj, closure, contains); + break; + default: + ShouldNotReachHere(); } } @@ -125,6 +185,19 @@ oop_oop_iterate_ref_processing_bounded(obj, closure, mr); } +#ifdef ASSERT +template +void InstanceRefKlass::trace_reference_gc(const char *s, oop obj, T* referent_addr, T* next_addr, T* discovered_addr) { + log_develop_trace(gc, ref)("%s obj " PTR_FORMAT, s, p2i(obj)); + log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(referent_addr), p2i(referent_addr ? (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL)); + log_develop_trace(gc, ref)(" next_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(next_addr), p2i(next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL)); + log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, + p2i(discovered_addr), p2i(discovered_addr ? (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL)); +} +#endif + // Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for // all closures. Macros calling macros above for each oop size. #define ALL_INSTANCE_REF_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ --- old/src/share/vm/oops/klass.hpp 2017-04-25 11:32:50.769158468 +0200 +++ new/src/share/vm/oops/klass.hpp 2017-04-25 11:32:50.625152808 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -607,8 +607,6 @@ // GC specific object visitors // - // Mark Sweep - virtual int oop_ms_adjust_pointers(oop obj) = 0; #if INCLUDE_ALL_GCS // Parallel Scavenge virtual void oop_ps_push_contents( oop obj, PSPromotionManager* pm) = 0; --- old/src/share/vm/oops/objArrayKlass.hpp 2017-04-25 11:32:51.481186457 +0200 +++ new/src/share/vm/oops/objArrayKlass.hpp 2017-04-25 11:32:51.337180796 +0200 @@ -112,8 +112,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm); --- old/src/share/vm/oops/oop.hpp 2017-04-25 11:32:52.201214760 +0200 +++ new/src/share/vm/oops/oop.hpp 2017-04-25 11:32:52.029207999 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -325,10 +325,6 @@ // Garbage Collection support - // Mark Sweep - // Adjust all pointers in this object to point at it's forwarded location and - // return the size of this oop. This is used by the MarkSweep collector. - inline int ms_adjust_pointers(); #if INCLUDE_ALL_GCS // Parallel Compact inline void pc_follow_contents(ParCompactionManager* cm); --- old/src/share/vm/oops/oop.inline.hpp 2017-04-25 11:32:52.857240547 +0200 +++ new/src/share/vm/oops/oop.inline.hpp 2017-04-25 11:32:52.709234729 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -664,13 +664,6 @@ } } -int oopDesc::ms_adjust_pointers() { - debug_only(int check_size = size()); - int s = klass()->oop_ms_adjust_pointers(this); - assert(s == check_size, "should be the same"); - return s; -} - #if INCLUDE_ALL_GCS void oopDesc::pc_follow_contents(ParCompactionManager* cm) { klass()->oop_pc_follow_contents(this, cm); --- old/src/share/vm/oops/typeArrayKlass.hpp 2017-04-25 11:32:53.565268379 +0200 +++ new/src/share/vm/oops/typeArrayKlass.hpp 2017-04-25 11:32:53.397261774 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -74,8 +74,6 @@ // GC specific object visitors // - // Mark Sweep - int oop_ms_adjust_pointers(oop obj); #if INCLUDE_ALL_GCS // Parallel Scavenge void oop_ps_push_contents( oop obj, PSPromotionManager* pm);