mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
6826736: CMS: core dump with -XX:+UseCompressedOops
Fix deoptimization code and OopMapSet::all_do() to check for oop = narrow_oop_base. Reviewed-by: jcoomes, phh, ysr, never
This commit is contained in:
parent
db41917a7e
commit
b0f75657c5
5 changed files with 111 additions and 2 deletions
|
@ -379,7 +379,15 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
|
||||||
if ( loc != NULL ) {
|
if ( loc != NULL ) {
|
||||||
oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
|
oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
|
||||||
oop *derived_loc = loc;
|
oop *derived_loc = loc;
|
||||||
derived_oop_fn(base_loc, derived_loc);
|
oop val = *base_loc;
|
||||||
|
if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
|
||||||
|
// Ignore NULL oops and decoded NULL narrow oops which
|
||||||
|
// equal to Universe::narrow_oop_base when a narrow oop
|
||||||
|
// implicit null check is used in compiled code.
|
||||||
|
// The narrow_oop_base could be NULL or be the address
|
||||||
|
// of the page below heap depending on compressed oops mode.
|
||||||
|
} else
|
||||||
|
derived_oop_fn(base_loc, derived_loc);
|
||||||
}
|
}
|
||||||
oms.next();
|
oms.next();
|
||||||
} while (!oms.is_done());
|
} while (!oms.is_done());
|
||||||
|
@ -394,6 +402,15 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
|
||||||
oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
|
oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
|
||||||
if ( loc != NULL ) {
|
if ( loc != NULL ) {
|
||||||
if ( omv.type() == OopMapValue::oop_value ) {
|
if ( omv.type() == OopMapValue::oop_value ) {
|
||||||
|
oop val = *loc;
|
||||||
|
if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
|
||||||
|
// Ignore NULL oops and decoded NULL narrow oops which
|
||||||
|
// equal to Universe::narrow_oop_base when a narrow oop
|
||||||
|
// implicit null check is used in compiled code.
|
||||||
|
// The narrow_oop_base could be NULL or be the address
|
||||||
|
// of the page below heap depending on compressed oops mode.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
|
if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
|
||||||
!Universe::heap()->is_in_or_null(*loc)) {
|
!Universe::heap()->is_in_or_null(*loc)) {
|
||||||
|
@ -410,6 +427,8 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
oop_fn->do_oop(loc);
|
oop_fn->do_oop(loc);
|
||||||
} else if ( omv.type() == OopMapValue::value_value ) {
|
} else if ( omv.type() == OopMapValue::value_value ) {
|
||||||
|
assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc),
|
||||||
|
"found invalid value pointer");
|
||||||
value_fn->do_oop(loc);
|
value_fn->do_oop(loc);
|
||||||
} else if ( omv.type() == OopMapValue::narrowoop_value ) {
|
} else if ( omv.type() == OopMapValue::narrowoop_value ) {
|
||||||
narrowOop *nl = (narrowOop*)loc;
|
narrowOop *nl = (narrowOop*)loc;
|
||||||
|
|
|
@ -233,6 +233,10 @@ class OopMapSet : public ResourceObj {
|
||||||
int heap_size() const;
|
int heap_size() const;
|
||||||
void copy_to(address addr);
|
void copy_to(address addr);
|
||||||
|
|
||||||
|
// Methods oops_do() and all_do() filter out NULL oops and
|
||||||
|
// oop == Universe::narrow_oop_base() before passing oops
|
||||||
|
// to closures.
|
||||||
|
|
||||||
// Iterates through frame for a compiled method
|
// Iterates through frame for a compiled method
|
||||||
static void oops_do (const frame* fr,
|
static void oops_do (const frame* fr,
|
||||||
const RegisterMap* reg_map, OopClosure* f);
|
const RegisterMap* reg_map, OopClosure* f);
|
||||||
|
|
|
@ -343,6 +343,7 @@ class Universe: AllStatic {
|
||||||
// For UseCompressedOops
|
// For UseCompressedOops
|
||||||
static address* narrow_oop_base_addr() { return &_narrow_oop._base; }
|
static address* narrow_oop_base_addr() { return &_narrow_oop._base; }
|
||||||
static address narrow_oop_base() { return _narrow_oop._base; }
|
static address narrow_oop_base() { return _narrow_oop._base; }
|
||||||
|
static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); }
|
||||||
static int narrow_oop_shift() { return _narrow_oop._shift; }
|
static int narrow_oop_shift() { return _narrow_oop._shift; }
|
||||||
static void set_narrow_oop_base(address base) { _narrow_oop._base = base; }
|
static void set_narrow_oop_base(address base) { _narrow_oop._base = base; }
|
||||||
static void set_narrow_oop_shift(int shift) { _narrow_oop._shift = shift; }
|
static void set_narrow_oop_shift(int shift) { _narrow_oop._shift = shift; }
|
||||||
|
|
|
@ -104,7 +104,17 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case Location::oop: {
|
case Location::oop: {
|
||||||
Handle h(*(oop *)value_addr); // Wrap a handle around the oop
|
oop val = *(oop *)value_addr;
|
||||||
|
#ifdef _LP64
|
||||||
|
if (Universe::is_narrow_oop_base(val)) {
|
||||||
|
// Compiled code may produce decoded oop = narrow_oop_base
|
||||||
|
// when a narrow oop implicit null check is used.
|
||||||
|
// The narrow_oop_base could be NULL or be the address
|
||||||
|
// of the page below heap. Use NULL value for both cases.
|
||||||
|
val = (oop)NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Handle h(val); // Wrap a handle around the oop
|
||||||
return new StackValue(h);
|
return new StackValue(h);
|
||||||
}
|
}
|
||||||
case Location::addr: {
|
case Location::addr: {
|
||||||
|
|
75
hotspot/test/compiler/6826736/Test.java
Normal file
75
hotspot/test/compiler/6826736/Test.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 6826736
|
||||||
|
* @summary CMS: core dump with -XX:+UseCompressedOops
|
||||||
|
*
|
||||||
|
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:CompileThreshold=100 -XX:CompileOnly=Test.test -XX:-BlockLayoutRotateLoops -XX:LoopUnrollLimit=0 Test
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
int[] arr;
|
||||||
|
int[] arr2;
|
||||||
|
int test(int r) {
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
for (int j = i; j < 100; j++) {
|
||||||
|
int a = 0;
|
||||||
|
for (long k = 0; k < 100; k++) {
|
||||||
|
a += k;
|
||||||
|
}
|
||||||
|
if (arr != null)
|
||||||
|
a = arr[j];
|
||||||
|
r += a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int r = 0;
|
||||||
|
Test t = new Test();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
t.arr = new int[100];
|
||||||
|
r = t.test(r);
|
||||||
|
}
|
||||||
|
System.out.println("Warmup 1 is done.");
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
t.arr = null;
|
||||||
|
r = t.test(r);
|
||||||
|
}
|
||||||
|
System.out.println("Warmup 2 is done.");
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
t.arr = new int[100];
|
||||||
|
r = t.test(r);
|
||||||
|
}
|
||||||
|
System.out.println("Warmup is done.");
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
t.arr = new int[1000000];
|
||||||
|
t.arr = null;
|
||||||
|
r = t.test(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue