# HG changeset patch # User drwhite # Date 1467747246 14400 # Node ID 946f1321c0751cb494eeebd2e7981f814846920f # Parent e8e42da000c59ce87c75c2ac53cbb11edb35fd68 8158946: btree009 fails with assert(s > 0) failed: Bad size calculated Summary: Set oop_size before setting _klass Reviewed-by: coleenp, dholmes, kbarrett, tschatzl diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Jul 05 15:34:06 2016 -0400 @@ -871,12 +871,17 @@ int java_lang_Class::oop_size(oop java_class) { assert(_oop_size_offset != 0, "must be set"); - return java_class->int_field(_oop_size_offset); -} + int size = java_class->int_field(_oop_size_offset); + assert(size > 0, "Oop size must be greater than zero, not %d", size); + return size; +} + void java_lang_Class::set_oop_size(oop java_class, int size) { assert(_oop_size_offset != 0, "must be set"); + assert(size > 0, "Oop size must be greater than zero, not %d", size); java_class->int_field_put(_oop_size_offset, size); } + int java_lang_Class::static_oop_field_count(oop java_class) { assert(_static_oop_field_count_offset != 0, "must be set"); return java_class->int_field(_static_oop_field_count_offset); diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/classfile/javaClasses.hpp --- a/hotspot/src/share/vm/classfile/javaClasses.hpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Tue Jul 05 15:34:06 2016 -0400 @@ -275,7 +275,6 @@ static int static_oop_field_count(oop java_class); static void set_static_oop_field_count(oop java_class, int size); - static GrowableArray* fixup_mirror_list() { return _fixup_mirror_list; } diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/gc/shared/collectedHeap.hpp --- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Tue Jul 05 15:34:06 2016 -0400 @@ -159,6 +159,8 @@ inline static void post_allocation_setup_array(KlassHandle klass, HeapWord* obj, int length); + inline static void post_allocation_setup_class(KlassHandle klass, HeapWord* obj, int size); + // Clears an allocated object. inline static void init_obj(HeapWord* obj, size_t size); @@ -300,6 +302,7 @@ inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS); + inline static oop class_allocate(KlassHandle klass, int size, TRAPS); inline static void post_allocation_install_obj_klass(KlassHandle klass, oop obj); diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp Tue Jul 05 15:34:06 2016 -0400 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP #define SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP +#include "classfile/javaClasses.hpp" #include "gc/shared/allocTracer.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/threadLocalAllocBuffer.inline.hpp" @@ -96,6 +97,22 @@ post_allocation_notify(klass, (oop)obj, size); } +void CollectedHeap::post_allocation_setup_class(KlassHandle klass, + HeapWord* obj, + int size) { + // Set oop_size field before setting the _klass field + // in post_allocation_setup_common() because the klass field + // indicates that the object is parsable by concurrent GC. + oop new_cls = (oop)obj; + assert(size > 0, "oop_size must be positive."); + java_lang_Class::set_oop_size(new_cls, size); + post_allocation_setup_common(klass, obj); + assert(Universe::is_bootstrapping() || + !new_cls->is_array(), "must not be an array"); + // notify jvmti and dtrace + post_allocation_notify(klass, new_cls, size); +} + void CollectedHeap::post_allocation_setup_array(KlassHandle klass, HeapWord* obj, int length) { @@ -207,6 +224,16 @@ return (oop)obj; } +oop CollectedHeap::class_allocate(KlassHandle klass, int size, TRAPS) { + debug_only(check_for_valid_allocation_state()); + assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); + assert(size >= 0, "int won't convert to size_t"); + HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); + post_allocation_setup_class(klass, obj, size); // set oop_size + NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); + return (oop)obj; +} + oop CollectedHeap::array_allocate(KlassHandle klass, int size, int length, diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/oops/instanceMirrorKlass.cpp --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp Tue Jul 05 15:34:06 2016 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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,13 +50,12 @@ // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, this); - instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); + + assert(size > 0, "total object size must be positive: %d", size); // Since mirrors can be variable sized because of the static fields, store // the size in the mirror itself. - java_lang_Class::set_oop_size(i, size); - - return i; + return (instanceOop)CollectedHeap::class_allocate(h_k, size, CHECK_NULL); } int InstanceMirrorKlass::oop_size(oop obj) const { diff -r e8e42da000c5 -r 946f1321c075 hotspot/src/share/vm/oops/oop.inline.hpp --- a/hotspot/src/share/vm/oops/oop.inline.hpp Tue Jul 05 20:09:21 2016 +0200 +++ b/hotspot/src/share/vm/oops/oop.inline.hpp Tue Jul 05 15:34:06 2016 -0400 @@ -258,8 +258,8 @@ } } - assert(s % MinObjAlignment == 0, "alignment check"); - assert(s > 0, "Bad size calculated"); + assert(s % MinObjAlignment == 0, "Oop size is not properly aligned: %d", s); + assert(s > 0, "Oop size must be greater than zero, not %d", s); return s; }