mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8171392: Move Klass pointers outside of ConstantPool entries so ConstantPool can be read-only
Added _resolved_klasses; moved _resolved_references to ConstantPoolCache, etc. Reviewed-by: coleenp, lfoltan, simonis, aph
This commit is contained in:
parent
0c74ceb12d
commit
c386cec7b1
32 changed files with 527 additions and 231 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -270,7 +270,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
|
|
||||||
get_constant_pool(result);
|
get_constant_pool(result);
|
||||||
// load pointer for resolved_references[] objArray
|
// load pointer for resolved_references[] objArray
|
||||||
ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
|
ldr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
|
||||||
|
ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
|
||||||
// JNIHandles::resolve(obj);
|
// JNIHandles::resolve(obj);
|
||||||
ldr(result, Address(result, 0));
|
ldr(result, Address(result, 0));
|
||||||
// Add in the index
|
// Add in the index
|
||||||
|
@ -278,6 +279,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_offset(
|
||||||
|
Register cpool, Register index, Register klass, Register temp) {
|
||||||
|
add(temp, cpool, index, LSL, LogBytesPerWord);
|
||||||
|
ldrh(temp, Address(temp, sizeof(ConstantPool))); // temp = resolved_klass_index
|
||||||
|
ldr(klass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // klass = cpool->_resolved_klasses
|
||||||
|
add(klass, klass, temp, LSL, LogBytesPerWord);
|
||||||
|
ldr(klass, Address(klass, Array<Klass*>::base_offset_in_bytes()));
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
|
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
|
||||||
// subtype of super_klass.
|
// subtype of super_klass.
|
||||||
//
|
//
|
||||||
|
|
|
@ -123,6 +123,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// load cpool->resolved_references(index);
|
// load cpool->resolved_references(index);
|
||||||
void load_resolved_reference_at_index(Register result, Register index);
|
void load_resolved_reference_at_index(Register result, Register index);
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index);
|
||||||
|
void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp);
|
||||||
|
|
||||||
void pop_ptr(Register r = r0);
|
void pop_ptr(Register r = r0);
|
||||||
void pop_i(Register r = r0);
|
void pop_i(Register r = r0);
|
||||||
void pop_l(Register r = r0);
|
void pop_l(Register r = r0);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -3372,8 +3372,7 @@ void TemplateTable::_new() {
|
||||||
__ br(Assembler::NE, slow_case);
|
__ br(Assembler::NE, slow_case);
|
||||||
|
|
||||||
// get InstanceKlass
|
// get InstanceKlass
|
||||||
__ lea(r4, Address(r4, r3, Address::lsl(3)));
|
__ load_resolved_klass_at_offset(r4, r3, r4, rscratch1);
|
||||||
__ ldr(r4, Address(r4, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
// make sure klass is initialized & doesn't have finalizer
|
// make sure klass is initialized & doesn't have finalizer
|
||||||
// make sure klass is fully initialized
|
// make sure klass is fully initialized
|
||||||
|
@ -3526,8 +3525,7 @@ void TemplateTable::checkcast()
|
||||||
// Get superklass in r0 and subklass in r3
|
// Get superklass in r0 and subklass in r3
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ mov(r3, r0); // Save object in r3; r0 needed for subtype check
|
__ mov(r3, r0); // Save object in r3; r0 needed for subtype check
|
||||||
__ lea(r0, Address(r2, r19, Address::lsl(3)));
|
__ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); // r0 = klass
|
||||||
__ ldr(r0, Address(r0, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(r19, r3);
|
__ load_klass(r19, r3);
|
||||||
|
@ -3583,8 +3581,7 @@ void TemplateTable::instanceof() {
|
||||||
// Get superklass in r0 and subklass in r3
|
// Get superklass in r0 and subklass in r3
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ load_klass(r3, r0);
|
__ load_klass(r3, r0);
|
||||||
__ lea(r0, Address(r2, r19, Address::lsl(3)));
|
__ load_resolved_klass_at_offset(r2, r19, r0, rscratch1);
|
||||||
__ ldr(r0, Address(r0, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
|
|
||||||
Register cache = result;
|
Register cache = result;
|
||||||
// load pointer for resolved_references[] objArray
|
// load pointer for resolved_references[] objArray
|
||||||
ldr(cache, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
|
ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes()));
|
||||||
|
ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
|
||||||
// JNIHandles::resolve(result)
|
// JNIHandles::resolve(result)
|
||||||
ldr(cache, Address(cache, 0));
|
ldr(cache, Address(cache, 0));
|
||||||
// Add in the index
|
// Add in the index
|
||||||
|
@ -308,6 +309,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
load_heap_oop(result, Address(cache, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
load_heap_oop(result, Address(cache, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_offset(
|
||||||
|
Register Rcpool, Register Rindex, Register Rklass) {
|
||||||
|
add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
||||||
|
ldrh(Rtemp, Address(Rtemp, sizeof(ConstantPool))); // Rtemp = resolved_klass_index
|
||||||
|
ldr(Rklass, Address(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes())); // Rklass = cpool->_resolved_klasses
|
||||||
|
add(Rklass, Rklass, AsmOperand(Rtemp, lsl, LogBytesPerWord));
|
||||||
|
ldr(Rklass, Address(Rklass, Array<Klass*>::base_offset_in_bytes()));
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a subtype check: branch to not_subtype if sub_klass is
|
// Generate a subtype check: branch to not_subtype if sub_klass is
|
||||||
// not a subtype of super_klass.
|
// not a subtype of super_klass.
|
||||||
// Profiling code for the subtype check failure (profile_typecheck_failed)
|
// Profiling code for the subtype check failure (profile_typecheck_failed)
|
||||||
|
|
|
@ -141,6 +141,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// Load object from cpool->resolved_references(*bcp+1)
|
// Load object from cpool->resolved_references(*bcp+1)
|
||||||
void load_resolved_reference_at_index(Register result, Register tmp);
|
void load_resolved_reference_at_index(Register result, Register tmp);
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index); Rtemp is corrupted upon return
|
||||||
|
void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass);
|
||||||
|
|
||||||
void store_check_part1(Register card_table_base); // Sets card_table_base register.
|
void store_check_part1(Register card_table_base); // Sets card_table_base register.
|
||||||
void store_check_part2(Register obj, Register card_table_base, Register tmp);
|
void store_check_part2(Register obj, Register card_table_base, Register tmp);
|
||||||
|
|
||||||
|
|
|
@ -4372,10 +4372,9 @@ void TemplateTable::_new() {
|
||||||
#endif // AARCH64
|
#endif // AARCH64
|
||||||
|
|
||||||
// get InstanceKlass
|
// get InstanceKlass
|
||||||
__ add(Rklass, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
|
||||||
__ ldr(Rklass, Address(Rklass, sizeof(ConstantPool)));
|
|
||||||
__ cmp(Rtemp, JVM_CONSTANT_Class);
|
__ cmp(Rtemp, JVM_CONSTANT_Class);
|
||||||
__ b(slow_case, ne);
|
__ b(slow_case, ne);
|
||||||
|
__ load_resolved_klass_at_offset(Rcpool, Rindex, Rklass);
|
||||||
|
|
||||||
// make sure klass is initialized & doesn't have finalizer
|
// make sure klass is initialized & doesn't have finalizer
|
||||||
// make sure klass is fully initialized
|
// make sure klass is fully initialized
|
||||||
|
@ -4647,8 +4646,7 @@ void TemplateTable::checkcast() {
|
||||||
|
|
||||||
// Get superklass in Rsuper and subklass in Rsub
|
// Get superklass in Rsuper and subklass in Rsub
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
__ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper);
|
||||||
__ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(Rsub, Robj);
|
__ load_klass(Rsub, Robj);
|
||||||
|
@ -4721,8 +4719,7 @@ void TemplateTable::instanceof() {
|
||||||
|
|
||||||
// Get superklass in Rsuper and subklass in Rsub
|
// Get superklass in Rsuper and subklass in Rsub
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord));
|
__ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper);
|
||||||
__ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(Rsub, Robj);
|
__ load_klass(Rsub, Robj);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -79,6 +79,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// Load object from cpool->resolved_references(index).
|
// Load object from cpool->resolved_references(index).
|
||||||
void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL);
|
void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL);
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass);
|
||||||
|
|
||||||
void load_receiver(Register Rparam_count, Register Rrecv_dst);
|
void load_receiver(Register Rparam_count, Register Rrecv_dst);
|
||||||
|
|
||||||
// helpers for expression stack
|
// helpers for expression stack
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -454,7 +454,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
|
||||||
Register tmp = index; // reuse
|
Register tmp = index; // reuse
|
||||||
sldi(tmp, index, LogBytesPerHeapOop);
|
sldi(tmp, index, LogBytesPerHeapOop);
|
||||||
// Load pointer for resolved_references[] objArray.
|
// Load pointer for resolved_references[] objArray.
|
||||||
ld(result, ConstantPool::resolved_references_offset_in_bytes(), result);
|
ld(result, ConstantPool::cache_offset_in_bytes(), result);
|
||||||
|
ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
|
||||||
// JNIHandles::resolve(result)
|
// JNIHandles::resolve(result)
|
||||||
ld(result, 0, result);
|
ld(result, 0, result);
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -471,6 +472,25 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
|
||||||
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
|
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass) {
|
||||||
|
// int value = *(Rcpool->int_at_addr(which));
|
||||||
|
// int resolved_klass_index = extract_low_short_from_int(value);
|
||||||
|
add(Roffset, Rcpool, Roffset);
|
||||||
|
#if defined(VM_LITTLE_ENDIAN)
|
||||||
|
lhz(Roffset, sizeof(ConstantPool), Roffset); // Roffset = resolved_klass_index
|
||||||
|
#else
|
||||||
|
lhz(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ld(Rklass, ConstantPool::resolved_klasses_offset_in_bytes(), Rcpool); // Rklass = Rcpool->_resolved_klasses
|
||||||
|
|
||||||
|
sldi(Roffset, Roffset, LogBytesPerWord);
|
||||||
|
addi(Roffset, Roffset, Array<Klass*>::base_offset_in_bytes());
|
||||||
|
isync(); // Order load of instance Klass wrt. tags.
|
||||||
|
ldx(Rklass, Rklass, Roffset);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
|
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
|
||||||
// a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2.
|
// a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2.
|
||||||
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1,
|
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013, 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2013, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -3660,11 +3660,9 @@ void TemplateTable::_new() {
|
||||||
__ cmpdi(CCR0, Rtags, JVM_CONSTANT_Class);
|
__ cmpdi(CCR0, Rtags, JVM_CONSTANT_Class);
|
||||||
__ bne(CCR0, Lslow_case);
|
__ bne(CCR0, Lslow_case);
|
||||||
|
|
||||||
// Get instanceKlass (load from Rcpool + sizeof(ConstantPool) + Rindex*BytesPerWord).
|
// Get instanceKlass
|
||||||
__ sldi(Roffset, Rindex, LogBytesPerWord);
|
__ sldi(Roffset, Rindex, LogBytesPerWord);
|
||||||
__ addi(Rscratch, Rcpool, sizeof(ConstantPool));
|
__ load_resolved_klass_at_offset(Rcpool, Roffset, RinstanceKlass);
|
||||||
__ isync(); // Order load of instance Klass wrt. tags.
|
|
||||||
__ ldx(RinstanceKlass, Roffset, Rscratch);
|
|
||||||
|
|
||||||
// Make sure klass is fully initialized and get instance_size.
|
// Make sure klass is fully initialized and get instance_size.
|
||||||
__ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass);
|
__ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass);
|
||||||
|
@ -3875,9 +3873,7 @@ void TemplateTable::checkcast() {
|
||||||
// Extract target class from constant pool.
|
// Extract target class from constant pool.
|
||||||
__ bind(Lquicked);
|
__ bind(Lquicked);
|
||||||
__ sldi(Roffset, Roffset, LogBytesPerWord);
|
__ sldi(Roffset, Roffset, LogBytesPerWord);
|
||||||
__ addi(Rcpool, Rcpool, sizeof(ConstantPool));
|
__ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass);
|
||||||
__ isync(); // Order load of specified Klass wrt. tags.
|
|
||||||
__ ldx(RspecifiedKlass, Rcpool, Roffset);
|
|
||||||
|
|
||||||
// Do the checkcast.
|
// Do the checkcast.
|
||||||
__ bind(Lresolved);
|
__ bind(Lresolved);
|
||||||
|
@ -3939,9 +3935,7 @@ void TemplateTable::instanceof() {
|
||||||
// Extract target class from constant pool.
|
// Extract target class from constant pool.
|
||||||
__ bind(Lquicked);
|
__ bind(Lquicked);
|
||||||
__ sldi(Roffset, Roffset, LogBytesPerWord);
|
__ sldi(Roffset, Roffset, LogBytesPerWord);
|
||||||
__ addi(Rcpool, Rcpool, sizeof(ConstantPool));
|
__ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass);
|
||||||
__ isync(); // Order load of specified Klass wrt. tags.
|
|
||||||
__ ldx(RspecifiedKlass, Rcpool, Roffset);
|
|
||||||
|
|
||||||
// Do the checkcast.
|
// Do the checkcast.
|
||||||
__ bind(Lresolved);
|
__ bind(Lresolved);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -371,7 +371,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
|
||||||
Register tmp = index; // reuse
|
Register tmp = index; // reuse
|
||||||
z_sllg(index, index, LogBytesPerHeapOop); // Offset into resolved references array.
|
z_sllg(index, index, LogBytesPerHeapOop); // Offset into resolved references array.
|
||||||
// Load pointer for resolved_references[] objArray.
|
// Load pointer for resolved_references[] objArray.
|
||||||
z_lg(result, ConstantPool::resolved_references_offset_in_bytes(), result);
|
z_lg(result, ConstantPool::cache_offset_in_bytes(), result);
|
||||||
|
z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
|
||||||
// JNIHandles::resolve(result)
|
// JNIHandles::resolve(result)
|
||||||
z_lg(result, 0, result); // Load resolved references array itself.
|
z_lg(result, 0, result); // Load resolved references array itself.
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -386,6 +387,16 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
|
||||||
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
|
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass) {
|
||||||
|
// int value = *(Rcpool->int_at_addr(which));
|
||||||
|
// int resolved_klass_index = extract_low_short_from_int(value);
|
||||||
|
z_llgh(offset, Address(cpool, offset, sizeof(ConstantPool) + 2)); // offset = resolved_klass_index (s390 is big-endian)
|
||||||
|
z_sllg(offset, offset, LogBytesPerWord); // Convert 'index' to 'offset'
|
||||||
|
z_lg(iklass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // iklass = cpool->_resolved_klasses
|
||||||
|
z_lg(iklass, Address(iklass, offset, Array<Klass*>::base_offset_in_bytes()));
|
||||||
|
}
|
||||||
|
|
||||||
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
|
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
|
||||||
Register tmp,
|
Register tmp,
|
||||||
int bcp_offset,
|
int bcp_offset,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -115,6 +115,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
|
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
|
||||||
void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
|
void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
|
||||||
void load_resolved_reference_at_index(Register result, Register index);
|
void load_resolved_reference_at_index(Register result, Register index);
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass);
|
||||||
|
|
||||||
// Pop topmost element from stack. It just disappears. Useful if
|
// Pop topmost element from stack. It just disappears. Useful if
|
||||||
// consumed previously by access via stackTop().
|
// consumed previously by access via stackTop().
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -3708,7 +3708,7 @@ void TemplateTable::_new() {
|
||||||
__ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset.
|
__ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset.
|
||||||
// Get InstanceKlass.
|
// Get InstanceKlass.
|
||||||
Register iklass = cpool;
|
Register iklass = cpool;
|
||||||
__ z_lg(iklass, Address(cpool, offset, sizeof(ConstantPool)));
|
__ load_resolved_klass_at_offset(cpool, offset, iklass);
|
||||||
|
|
||||||
// Make sure klass is initialized & doesn't have finalizer.
|
// Make sure klass is initialized & doesn't have finalizer.
|
||||||
// Make sure klass is fully initialized.
|
// Make sure klass is fully initialized.
|
||||||
|
@ -3895,7 +3895,7 @@ void TemplateTable::checkcast() {
|
||||||
|
|
||||||
__ z_lgr(Z_ARG4, Z_tos); // Save receiver.
|
__ z_lgr(Z_ARG4, Z_tos); // Save receiver.
|
||||||
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
|
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
|
||||||
__ mem2reg_opt(klass, Address(cpool, index, sizeof(ConstantPool)));
|
__ load_resolved_klass_at_offset(cpool, index, klass);
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
|
|
||||||
|
@ -3969,8 +3969,7 @@ void TemplateTable::instanceof() {
|
||||||
|
|
||||||
__ load_klass(subklass, Z_tos);
|
__ load_klass(subklass, Z_tos);
|
||||||
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
|
__ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing
|
||||||
__ mem2reg_opt(klass,
|
__ load_resolved_klass_at_offset(cpool, index, klass);
|
||||||
Address(cpool, index, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
|
|
||||||
|
|
|
@ -755,7 +755,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
sll(index, LogBytesPerHeapOop, tmp);
|
sll(index, LogBytesPerHeapOop, tmp);
|
||||||
get_constant_pool(result);
|
get_constant_pool(result);
|
||||||
// load pointer for resolved_references[] objArray
|
// load pointer for resolved_references[] objArray
|
||||||
ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result);
|
ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result);
|
||||||
|
ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
|
||||||
// JNIHandles::resolve(result)
|
// JNIHandles::resolve(result)
|
||||||
ld_ptr(result, 0, result);
|
ld_ptr(result, 0, result);
|
||||||
// Add in the index
|
// Add in the index
|
||||||
|
@ -764,6 +765,24 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool,
|
||||||
|
Register Roffset, Register Rklass) {
|
||||||
|
// int value = *this_cp->int_at_addr(which);
|
||||||
|
// int resolved_klass_index = extract_low_short_from_int(value);
|
||||||
|
//
|
||||||
|
// Because SPARC is big-endian, the low_short is at (cpool->int_at_addr(which) + 2 bytes)
|
||||||
|
add(Roffset, Rcpool, Roffset);
|
||||||
|
lduh(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index
|
||||||
|
|
||||||
|
Register Rresolved_klasses = Rklass;
|
||||||
|
ld_ptr(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes(), Rresolved_klasses);
|
||||||
|
sll(Roffset, LogBytesPerWord, Roffset);
|
||||||
|
add(Roffset, Array<Klass*>::base_offset_in_bytes(), Roffset);
|
||||||
|
ld_ptr(Rresolved_klasses, Roffset, Rklass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
|
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
|
||||||
// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2.
|
// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2.
|
||||||
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
|
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
|
||||||
|
|
|
@ -196,6 +196,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// load cpool->resolved_references(index);
|
// load cpool->resolved_references(index);
|
||||||
void load_resolved_reference_at_index(Register result, Register index);
|
void load_resolved_reference_at_index(Register result, Register index);
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass);
|
||||||
|
|
||||||
// common code
|
// common code
|
||||||
|
|
||||||
void field_offset_at(int n, Register tmp, Register dest, Register base);
|
void field_offset_at(int n, Register tmp, Register dest, Register base);
|
||||||
|
|
|
@ -3241,9 +3241,7 @@ void TemplateTable::_new() {
|
||||||
__ br(Assembler::notEqual, false, Assembler::pn, slow_case);
|
__ br(Assembler::notEqual, false, Assembler::pn, slow_case);
|
||||||
__ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
|
__ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
|
||||||
// get InstanceKlass
|
// get InstanceKlass
|
||||||
//__ sll(Roffset, LogBytesPerWord, Roffset); // executed in delay slot
|
__ load_resolved_klass_at_offset(Rscratch, Roffset, RinstanceKlass);
|
||||||
__ add(Roffset, sizeof(ConstantPool), Roffset);
|
|
||||||
__ ld_ptr(Rscratch, Roffset, RinstanceKlass);
|
|
||||||
|
|
||||||
// make sure klass is fully initialized:
|
// make sure klass is fully initialized:
|
||||||
__ ldub(RinstanceKlass, in_bytes(InstanceKlass::init_state_offset()), G3_scratch);
|
__ ldub(RinstanceKlass, in_bytes(InstanceKlass::init_state_offset()), G3_scratch);
|
||||||
|
@ -3465,8 +3463,9 @@ void TemplateTable::checkcast() {
|
||||||
|
|
||||||
// Extract target class from constant pool
|
// Extract target class from constant pool
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ add(Roffset, sizeof(ConstantPool), Roffset);
|
__ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass);
|
||||||
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(Otos_i, RobjKlass); // get value klass
|
__ load_klass(Otos_i, RobjKlass); // get value klass
|
||||||
|
|
||||||
|
@ -3522,9 +3521,9 @@ void TemplateTable::instanceof() {
|
||||||
|
|
||||||
// Extract target class from constant pool
|
// Extract target class from constant pool
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ add(Roffset, sizeof(ConstantPool), Roffset);
|
|
||||||
__ get_constant_pool(Lscratch);
|
__ get_constant_pool(Lscratch);
|
||||||
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
|
__ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass);
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(Otos_i, RobjKlass); // get value klass
|
__ load_klass(Otos_i, RobjKlass); // get value klass
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -509,7 +509,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
|
|
||||||
get_constant_pool(result);
|
get_constant_pool(result);
|
||||||
// load pointer for resolved_references[] objArray
|
// load pointer for resolved_references[] objArray
|
||||||
movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
|
movptr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
|
||||||
|
movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
|
||||||
// JNIHandles::resolve(obj);
|
// JNIHandles::resolve(obj);
|
||||||
movptr(result, Address(result, 0));
|
movptr(result, Address(result, 0));
|
||||||
// Add in the index
|
// Add in the index
|
||||||
|
@ -517,6 +518,14 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
|
||||||
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void InterpreterMacroAssembler::load_resolved_klass_at_index(Register cpool,
|
||||||
|
Register index, Register klass) {
|
||||||
|
movw(index, Address(cpool, index, Address::times_ptr, sizeof(ConstantPool)));
|
||||||
|
Register resolved_klasses = cpool;
|
||||||
|
movptr(resolved_klasses, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes()));
|
||||||
|
movptr(klass, Address(resolved_klasses, index, Address::times_ptr, Array<Klass*>::base_offset_in_bytes()));
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
|
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
|
||||||
// subtype of super_klass.
|
// subtype of super_klass.
|
||||||
|
|
|
@ -123,6 +123,11 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
// load cpool->resolved_references(index);
|
// load cpool->resolved_references(index);
|
||||||
void load_resolved_reference_at_index(Register result, Register index);
|
void load_resolved_reference_at_index(Register result, Register index);
|
||||||
|
|
||||||
|
// load cpool->resolved_klass_at(index)
|
||||||
|
void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return)
|
||||||
|
Register index, // the constant pool index (corrupted on return)
|
||||||
|
Register klass); // contains the Klass on return
|
||||||
|
|
||||||
NOT_LP64(void f2ieee();) // truncate ftos to 32bits
|
NOT_LP64(void f2ieee();) // truncate ftos to 32bits
|
||||||
NOT_LP64(void d2ieee();) // truncate dtos to 64bits
|
NOT_LP64(void d2ieee();) // truncate dtos to 64bits
|
||||||
|
|
||||||
|
|
|
@ -3846,7 +3846,7 @@ void TemplateTable::_new() {
|
||||||
__ jcc(Assembler::notEqual, slow_case_no_pop);
|
__ jcc(Assembler::notEqual, slow_case_no_pop);
|
||||||
|
|
||||||
// get InstanceKlass
|
// get InstanceKlass
|
||||||
__ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool)));
|
__ load_resolved_klass_at_index(rcx, rdx, rcx);
|
||||||
__ push(rcx); // save the contexts of klass for initializing the header
|
__ push(rcx); // save the contexts of klass for initializing the header
|
||||||
|
|
||||||
// make sure klass is initialized & doesn't have finalizer
|
// make sure klass is initialized & doesn't have finalizer
|
||||||
|
@ -4061,8 +4061,7 @@ void TemplateTable::checkcast() {
|
||||||
// Get superklass in rax and subklass in rbx
|
// Get superklass in rax and subklass in rbx
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ mov(rdx, rax); // Save object in rdx; rax needed for subtype check
|
__ mov(rdx, rax); // Save object in rdx; rax needed for subtype check
|
||||||
__ movptr(rax, Address(rcx, rbx,
|
__ load_resolved_klass_at_index(rcx, rbx, rax);
|
||||||
Address::times_ptr, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ load_klass(rbx, rdx);
|
__ load_klass(rbx, rdx);
|
||||||
|
@ -4128,8 +4127,7 @@ void TemplateTable::instanceof() {
|
||||||
// Get superklass in rax and subklass in rdx
|
// Get superklass in rax and subklass in rdx
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ load_klass(rdx, rax);
|
__ load_klass(rdx, rax);
|
||||||
__ movptr(rax, Address(rcx, rbx,
|
__ load_resolved_klass_at_index(rcx, rbx, rax);
|
||||||
Address::times_ptr, sizeof(ConstantPool)));
|
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -84,8 +84,6 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
||||||
cache = type.getAddressField("_cache");
|
cache = type.getAddressField("_cache");
|
||||||
poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0);
|
poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0);
|
||||||
length = new CIntField(type.getCIntegerField("_length"), 0);
|
length = new CIntField(type.getCIntegerField("_length"), 0);
|
||||||
resolvedReferences = type.getAddressField("_resolved_references");
|
|
||||||
referenceMap = type.getAddressField("_reference_map");
|
|
||||||
headerSize = type.getSize();
|
headerSize = type.getSize();
|
||||||
elementSize = 0;
|
elementSize = 0;
|
||||||
// fetch constants:
|
// fetch constants:
|
||||||
|
@ -105,8 +103,6 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
||||||
private static AddressField cache;
|
private static AddressField cache;
|
||||||
private static MetadataField poolHolder;
|
private static MetadataField poolHolder;
|
||||||
private static CIntField length; // number of elements in oop
|
private static CIntField length; // number of elements in oop
|
||||||
private static AddressField resolvedReferences;
|
|
||||||
private static AddressField referenceMap;
|
|
||||||
|
|
||||||
private static long headerSize;
|
private static long headerSize;
|
||||||
private static long elementSize;
|
private static long elementSize;
|
||||||
|
@ -124,17 +120,11 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
||||||
public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
|
public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
|
||||||
public int getLength() { return (int)length.getValue(getAddress()); }
|
public int getLength() { return (int)length.getValue(getAddress()); }
|
||||||
public Oop getResolvedReferences() {
|
public Oop getResolvedReferences() {
|
||||||
Address handle = resolvedReferences.getValue(getAddress());
|
return getCache().getResolvedReferences();
|
||||||
if (handle != null) {
|
|
||||||
// Load through the handle
|
|
||||||
OopHandle refs = handle.getOopHandleAt(0);
|
|
||||||
return VM.getVM().getObjectHeap().newOop(refs);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public U2Array referenceMap() {
|
public U2Array referenceMap() {
|
||||||
return new U2Array(referenceMap.getValue(getAddress()));
|
return getCache().referenceMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int objectToCPIndex(int index) {
|
public int objectToCPIndex(int index) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -51,6 +51,8 @@ public class ConstantPoolCache extends Metadata {
|
||||||
elementSize = elType.getSize();
|
elementSize = elType.getSize();
|
||||||
length = new CIntField(type.getCIntegerField("_length"), 0);
|
length = new CIntField(type.getCIntegerField("_length"), 0);
|
||||||
intSize = VM.getVM().getObjectHeap().getIntSize();
|
intSize = VM.getVM().getObjectHeap().getIntSize();
|
||||||
|
resolvedReferences = type.getAddressField("_resolved_references");
|
||||||
|
referenceMap = type.getAddressField("_reference_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstantPoolCache(Address addr) {
|
public ConstantPoolCache(Address addr) {
|
||||||
|
@ -65,7 +67,8 @@ public class ConstantPoolCache extends Metadata {
|
||||||
private static long elementSize;
|
private static long elementSize;
|
||||||
private static CIntField length;
|
private static CIntField length;
|
||||||
private static long intSize;
|
private static long intSize;
|
||||||
|
private static AddressField resolvedReferences;
|
||||||
|
private static AddressField referenceMap;
|
||||||
|
|
||||||
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
|
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
|
||||||
|
|
||||||
|
@ -100,4 +103,18 @@ public class ConstantPoolCache extends Metadata {
|
||||||
entry.iterateFields(visitor);
|
entry.iterateFields(visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Oop getResolvedReferences() {
|
||||||
|
Address handle = resolvedReferences.getValue(getAddress());
|
||||||
|
if (handle != null) {
|
||||||
|
// Load through the handle
|
||||||
|
OopHandle refs = handle.getOopHandleAt(0);
|
||||||
|
return VM.getVM().getObjectHeap().newOop(refs);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U2Array referenceMap() {
|
||||||
|
return new U2Array(referenceMap.getValue(getAddress()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -64,8 +64,8 @@ ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
|
||||||
cp->symbol_at_put(idx, entry._u.utf8);
|
cp->symbol_at_put(idx, entry._u.utf8);
|
||||||
break;
|
break;
|
||||||
case BytecodeCPEntry::KLASS:
|
case BytecodeCPEntry::KLASS:
|
||||||
cp->unresolved_klass_at_put(
|
cp->klass_index_at_put(
|
||||||
idx, cp->symbol_at(entry._u.klass));
|
idx, entry._u.klass);
|
||||||
break;
|
break;
|
||||||
case BytecodeCPEntry::STRING:
|
case BytecodeCPEntry::STRING:
|
||||||
cp->unresolved_string_at_put(
|
cp->unresolved_string_at_put(
|
||||||
|
@ -85,6 +85,9 @@ ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cp->initialize_unresolved_klasses(_orig->pool_holder()->class_loader_data(),
|
||||||
|
CHECK_NULL);
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,6 +391,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = 1; // declared outside of loops for portability
|
int index = 1; // declared outside of loops for portability
|
||||||
|
int num_klasses = 0;
|
||||||
|
|
||||||
// first verification pass - validate cross references
|
// first verification pass - validate cross references
|
||||||
// and fixup class and string constants
|
// and fixup class and string constants
|
||||||
|
@ -459,7 +460,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||||
check_property(valid_symbol_at(class_index),
|
check_property(valid_symbol_at(class_index),
|
||||||
"Invalid constant pool index %u in class file %s",
|
"Invalid constant pool index %u in class file %s",
|
||||||
class_index, CHECK);
|
class_index, CHECK);
|
||||||
cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
|
cp->unresolved_klass_at_put(index, class_index, num_klasses++);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JVM_CONSTANT_StringIndex: {
|
case JVM_CONSTANT_StringIndex: {
|
||||||
|
@ -550,8 +551,19 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||||
} // switch(tag)
|
} // switch(tag)
|
||||||
} // end of for
|
} // end of for
|
||||||
|
|
||||||
|
_first_patched_klass_resolved_index = num_klasses;
|
||||||
|
cp->allocate_resolved_klasses(_loader_data, num_klasses + _max_num_patched_klasses, CHECK);
|
||||||
|
|
||||||
if (_cp_patches != NULL) {
|
if (_cp_patches != NULL) {
|
||||||
// need to treat this_class specially...
|
// need to treat this_class specially...
|
||||||
|
|
||||||
|
// Add dummy utf8 entries in the space reserved for names of patched classes. We'll use "*"
|
||||||
|
// for now. These will be replaced with actual names of the patched classes in patch_class().
|
||||||
|
Symbol* s = vmSymbols::star_name();
|
||||||
|
for (int n=_orig_cp_size; n<cp->length(); n++) {
|
||||||
|
cp->symbol_at_put(n, s);
|
||||||
|
}
|
||||||
|
|
||||||
int this_class_index;
|
int this_class_index;
|
||||||
{
|
{
|
||||||
stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len
|
stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len
|
||||||
|
@ -701,6 +713,14 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||||
} // end of for
|
} // end of for
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name) {
|
||||||
|
int name_index = _orig_cp_size + _num_patched_klasses;
|
||||||
|
int resolved_klass_index = _first_patched_klass_resolved_index + _num_patched_klasses;
|
||||||
|
|
||||||
|
cp->klass_at_put(class_index, name_index, resolved_klass_index, k, name);
|
||||||
|
_num_patched_klasses ++;
|
||||||
|
}
|
||||||
|
|
||||||
void ClassFileParser::patch_constant_pool(ConstantPool* cp,
|
void ClassFileParser::patch_constant_pool(ConstantPool* cp,
|
||||||
int index,
|
int index,
|
||||||
Handle patch,
|
Handle patch,
|
||||||
|
@ -718,13 +738,14 @@ void ClassFileParser::patch_constant_pool(ConstantPool* cp,
|
||||||
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
||||||
"Illegal class patch at %d in class file %s",
|
"Illegal class patch at %d in class file %s",
|
||||||
index, CHECK);
|
index, CHECK);
|
||||||
cp->klass_at_put(index, java_lang_Class::as_Klass(patch()));
|
Klass* k = java_lang_Class::as_Klass(patch());
|
||||||
|
patch_class(cp, index, k, k->name());
|
||||||
} else {
|
} else {
|
||||||
guarantee_property(java_lang_String::is_instance(patch()),
|
guarantee_property(java_lang_String::is_instance(patch()),
|
||||||
"Illegal class patch at %d in class file %s",
|
"Illegal class patch at %d in class file %s",
|
||||||
index, CHECK);
|
index, CHECK);
|
||||||
Symbol* const name = java_lang_String::as_symbol(patch(), CHECK);
|
Symbol* const name = java_lang_String::as_symbol(patch(), CHECK);
|
||||||
cp->unresolved_klass_at_put(index, name);
|
patch_class(cp, index, NULL, name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5340,8 +5361,14 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
||||||
ik->set_name(_class_name);
|
ik->set_name(_class_name);
|
||||||
|
|
||||||
if (is_anonymous()) {
|
if (is_anonymous()) {
|
||||||
// I am well known to myself
|
// _this_class_index is a CONSTANT_Class entry that refers to this
|
||||||
ik->constants()->klass_at_put(_this_class_index, ik); // eagerly resolve
|
// anonymous class itself. If this class needs to refer to its own methods or
|
||||||
|
// fields, it would use a CONSTANT_MethodRef, etc, which would reference
|
||||||
|
// _this_class_index. However, because this class is anonymous (it's
|
||||||
|
// not stored in SystemDictionary), _this_class_index cannot be resolved
|
||||||
|
// with ConstantPool::klass_at_impl, which does a SystemDictionary lookup.
|
||||||
|
// Therefore, we must eagerly resolve _this_class_index now.
|
||||||
|
ik->constants()->klass_at_put(_this_class_index, ik);
|
||||||
}
|
}
|
||||||
|
|
||||||
ik->set_minor_version(_minor_version);
|
ik->set_minor_version(_minor_version);
|
||||||
|
@ -5577,6 +5604,10 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||||
_loader_data(loader_data),
|
_loader_data(loader_data),
|
||||||
_host_klass(host_klass),
|
_host_klass(host_klass),
|
||||||
_cp_patches(cp_patches),
|
_cp_patches(cp_patches),
|
||||||
|
_num_patched_klasses(0),
|
||||||
|
_max_num_patched_klasses(0),
|
||||||
|
_orig_cp_size(0),
|
||||||
|
_first_patched_klass_resolved_index(0),
|
||||||
_super_klass(),
|
_super_klass(),
|
||||||
_cp(NULL),
|
_cp(NULL),
|
||||||
_fields(NULL),
|
_fields(NULL),
|
||||||
|
@ -5647,6 +5678,25 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||||
_need_verify = Verifier::should_verify_for(_loader_data->class_loader(),
|
_need_verify = Verifier::should_verify_for(_loader_data->class_loader(),
|
||||||
stream->need_verify());
|
stream->need_verify());
|
||||||
}
|
}
|
||||||
|
if (_cp_patches != NULL) {
|
||||||
|
int len = _cp_patches->length();
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
if (has_cp_patch_at(i)) {
|
||||||
|
Handle patch = cp_patch_at(i);
|
||||||
|
if (java_lang_String::is_instance(patch()) || java_lang_Class::is_instance(patch())) {
|
||||||
|
// We need to append the names of the patched classes to the end of the constant pool,
|
||||||
|
// because a patched class may have a Utf8 name that's not already included in the
|
||||||
|
// original constant pool. These class names are used when patch_constant_pool()
|
||||||
|
// calls patch_class().
|
||||||
|
//
|
||||||
|
// Note that a String in cp_patch_at(i) may be used to patch a Utf8, a String, or a Class.
|
||||||
|
// At this point, we don't know the tag for index i yet, because we haven't parsed the
|
||||||
|
// constant pool. So we can only assume the worst -- every String is used to patch a Class.
|
||||||
|
_max_num_patched_klasses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// synch back verification state to stream
|
// synch back verification state to stream
|
||||||
stream->set_verify(_need_verify);
|
stream->set_verify(_need_verify);
|
||||||
|
@ -5776,19 +5826,25 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->guarantee_more(3, CHECK); // length, first cp tag
|
stream->guarantee_more(3, CHECK); // length, first cp tag
|
||||||
const u2 cp_size = stream->get_u2_fast();
|
u2 cp_size = stream->get_u2_fast();
|
||||||
|
|
||||||
guarantee_property(
|
guarantee_property(
|
||||||
cp_size >= 1, "Illegal constant pool size %u in class file %s",
|
cp_size >= 1, "Illegal constant pool size %u in class file %s",
|
||||||
cp_size, CHECK);
|
cp_size, CHECK);
|
||||||
|
|
||||||
|
_orig_cp_size = cp_size;
|
||||||
|
if (int(cp_size) + _max_num_patched_klasses > 0xffff) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes");
|
||||||
|
}
|
||||||
|
cp_size += _max_num_patched_klasses;
|
||||||
|
|
||||||
_cp = ConstantPool::allocate(_loader_data,
|
_cp = ConstantPool::allocate(_loader_data,
|
||||||
cp_size,
|
cp_size,
|
||||||
CHECK);
|
CHECK);
|
||||||
|
|
||||||
ConstantPool* const cp = _cp;
|
ConstantPool* const cp = _cp;
|
||||||
|
|
||||||
parse_constant_pool(stream, cp, cp_size, CHECK);
|
parse_constant_pool(stream, cp, _orig_cp_size, CHECK);
|
||||||
|
|
||||||
assert(cp_size == (const u2)cp->length(), "invariant");
|
assert(cp_size == (const u2)cp->length(), "invariant");
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
mutable ClassLoaderData* _loader_data;
|
mutable ClassLoaderData* _loader_data;
|
||||||
const InstanceKlass* _host_klass;
|
const InstanceKlass* _host_klass;
|
||||||
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
||||||
|
int _num_patched_klasses;
|
||||||
|
int _max_num_patched_klasses;
|
||||||
|
int _orig_cp_size;
|
||||||
|
int _first_patched_klass_resolved_index;
|
||||||
|
|
||||||
// Metadata created before the instance klass is created. Must be deallocated
|
// Metadata created before the instance klass is created. Must be deallocated
|
||||||
// if not transferred to the InstanceKlass upon successful class loading
|
// if not transferred to the InstanceKlass upon successful class loading
|
||||||
|
@ -434,6 +438,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name);
|
||||||
void patch_constant_pool(ConstantPool* cp,
|
void patch_constant_pool(ConstantPool* cp,
|
||||||
int index,
|
int index,
|
||||||
Handle patch,
|
Handle patch,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2168,7 +2168,7 @@ run:
|
||||||
ConstantPool* constants = istate->method()->constants();
|
ConstantPool* constants = istate->method()->constants();
|
||||||
if (!constants->tag_at(index).is_unresolved_klass()) {
|
if (!constants->tag_at(index).is_unresolved_klass()) {
|
||||||
// Make sure klass is initialized and doesn't have a finalizer
|
// Make sure klass is initialized and doesn't have a finalizer
|
||||||
Klass* entry = constants->slot_at(index).get_klass();
|
Klass* entry = constants->resolved_klass_at(index);
|
||||||
InstanceKlass* ik = InstanceKlass::cast(entry);
|
InstanceKlass* ik = InstanceKlass::cast(entry);
|
||||||
if (ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
|
if (ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
|
||||||
size_t obj_size = ik->size_helper();
|
size_t obj_size = ik->size_helper();
|
||||||
|
@ -2268,7 +2268,7 @@ run:
|
||||||
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
||||||
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
||||||
}
|
}
|
||||||
Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
|
Klass* klassOf = (Klass*) METHOD->constants()->resolved_klass_at(index);
|
||||||
Klass* objKlass = STACK_OBJECT(-1)->klass(); // ebx
|
Klass* objKlass = STACK_OBJECT(-1)->klass(); // ebx
|
||||||
//
|
//
|
||||||
// Check for compatibilty. This check must not GC!!
|
// Check for compatibilty. This check must not GC!!
|
||||||
|
@ -2303,7 +2303,7 @@ run:
|
||||||
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
||||||
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
||||||
}
|
}
|
||||||
Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
|
Klass* klassOf = (Klass*) METHOD->constants()->resolved_klass_at(index);
|
||||||
Klass* objKlass = STACK_OBJECT(-1)->klass();
|
Klass* objKlass = STACK_OBJECT(-1)->klass();
|
||||||
//
|
//
|
||||||
// Check for compatibilty. This check must not GC!!
|
// Check for compatibilty. This check must not GC!!
|
||||||
|
|
|
@ -94,11 +94,14 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
|
||||||
_invokedynamic_references_map, CHECK);
|
_invokedynamic_references_map, CHECK);
|
||||||
|
|
||||||
// initialize object cache in constant pool
|
// initialize object cache in constant pool
|
||||||
|
_pool->set_cache(cache);
|
||||||
|
cache->set_constant_pool(_pool());
|
||||||
|
|
||||||
|
// _resolved_references is stored in pool->cache(), so need to be done after
|
||||||
|
// the above lines.
|
||||||
_pool->initialize_resolved_references(loader_data, _resolved_references_map,
|
_pool->initialize_resolved_references(loader_data, _resolved_references_map,
|
||||||
_resolved_reference_limit,
|
_resolved_reference_limit,
|
||||||
CHECK);
|
CHECK);
|
||||||
_pool->set_cache(cache);
|
|
||||||
cache->set_constant_pool(_pool());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
#define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
#define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
||||||
#define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
#define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
||||||
|
|
||||||
#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M))
|
||||||
#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(6*M) LP64_ONLY(10*M))
|
#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(13*M))
|
||||||
|
|
||||||
// the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on
|
// the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on
|
||||||
// the sizes required for dumping the archive using the default classlist. The sizes
|
// the sizes required for dumping the archive using the default classlist. The sizes
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
|
|
||||||
#define LargeSharedArchiveSize (300*M)
|
#define LargeSharedArchiveSize (300*M)
|
||||||
#define HugeSharedArchiveSize (800*M)
|
#define HugeSharedArchiveSize (800*M)
|
||||||
#define ReadOnlyRegionPercentage 0.4
|
#define ReadOnlyRegionPercentage 0.52
|
||||||
#define ReadWriteRegionPercentage 0.55
|
#define ReadWriteRegionPercentage 0.43
|
||||||
#define MiscDataRegionPercentage 0.03
|
#define MiscDataRegionPercentage 0.03
|
||||||
#define MiscCodeRegionPercentage 0.02
|
#define MiscCodeRegionPercentage 0.02
|
||||||
#define LargeThresholdClassCount 5000
|
#define LargeThresholdClassCount 5000
|
||||||
|
|
|
@ -47,18 +47,9 @@
|
||||||
#include "utilities/copy.hpp"
|
#include "utilities/copy.hpp"
|
||||||
|
|
||||||
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
|
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
|
||||||
// Tags are RW but comment below applies to tags also.
|
|
||||||
Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL);
|
Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL);
|
||||||
|
|
||||||
int size = ConstantPool::size(length);
|
int size = ConstantPool::size(length);
|
||||||
|
return new (loader_data, size, true, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
|
||||||
// CDS considerations:
|
|
||||||
// Allocate read-write but may be able to move to read-only at dumping time
|
|
||||||
// if all the klasses are resolved. The only other field that is writable is
|
|
||||||
// the resolved_references array, which is recreated at startup time.
|
|
||||||
// But that could be moved to InstanceKlass (although a pain to access from
|
|
||||||
// assembly code). Maybe it could be moved to the cpCache which is RW.
|
|
||||||
return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -80,22 +71,26 @@ static bool tag_array_is_zero_initialized(Array<u1>* tags) {
|
||||||
|
|
||||||
ConstantPool::ConstantPool(Array<u1>* tags) :
|
ConstantPool::ConstantPool(Array<u1>* tags) :
|
||||||
_tags(tags),
|
_tags(tags),
|
||||||
_length(tags->length()),
|
_length(tags->length()) {
|
||||||
_flags(0) {
|
|
||||||
|
|
||||||
assert(_tags != NULL, "invariant");
|
assert(_tags != NULL, "invariant");
|
||||||
assert(tags->length() == _length, "invariant");
|
assert(tags->length() == _length, "invariant");
|
||||||
assert(tag_array_is_zero_initialized(tags), "invariant");
|
assert(tag_array_is_zero_initialized(tags), "invariant");
|
||||||
assert(0 == _flags, "invariant");
|
assert(0 == flags(), "invariant");
|
||||||
assert(0 == version(), "invariant");
|
assert(0 == version(), "invariant");
|
||||||
assert(NULL == _pool_holder, "invariant");
|
assert(NULL == _pool_holder, "invariant");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
|
void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
MetadataFactory::free_metadata(loader_data, cache());
|
if (cache() != NULL) {
|
||||||
set_cache(NULL);
|
|
||||||
MetadataFactory::free_array<u2>(loader_data, reference_map());
|
MetadataFactory::free_array<u2>(loader_data, reference_map());
|
||||||
set_reference_map(NULL);
|
set_reference_map(NULL);
|
||||||
|
MetadataFactory::free_metadata(loader_data, cache());
|
||||||
|
set_cache(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataFactory::free_array<Klass*>(loader_data, resolved_klasses());
|
||||||
|
set_resolved_klasses(NULL);
|
||||||
|
|
||||||
MetadataFactory::free_array<jushort>(loader_data, operands());
|
MetadataFactory::free_array<jushort>(loader_data, operands());
|
||||||
set_operands(NULL);
|
set_operands(NULL);
|
||||||
|
@ -113,7 +108,7 @@ void ConstantPool::release_C_heap_structures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
objArrayOop ConstantPool::resolved_references() const {
|
objArrayOop ConstantPool::resolved_references() const {
|
||||||
return (objArrayOop)JNIHandles::resolve(_resolved_references);
|
return (objArrayOop)JNIHandles::resolve(_cache->resolved_references());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create resolved_references array and mapping array for original cp indexes
|
// Create resolved_references array and mapping array for original cp indexes
|
||||||
|
@ -150,9 +145,82 @@ void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstantPool::allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS) {
|
||||||
|
// A ConstantPool can't possibly have 0xffff valid class entries,
|
||||||
|
// because entry #0 must be CONSTANT_Invalid, and each class entry must refer to a UTF8
|
||||||
|
// entry for the class's name. So at most we will have 0xfffe class entries.
|
||||||
|
// This allows us to use 0xffff (ConstantPool::_temp_resolved_klass_index) to indicate
|
||||||
|
// UnresolvedKlass entries that are temporarily created during class redefinition.
|
||||||
|
assert(num_klasses < CPKlassSlot::_temp_resolved_klass_index, "sanity");
|
||||||
|
assert(resolved_klasses() == NULL, "sanity");
|
||||||
|
Array<Klass*>* rk = MetadataFactory::new_writeable_array<Klass*>(loader_data, num_klasses, CHECK);
|
||||||
|
set_resolved_klasses(rk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstantPool::initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS) {
|
||||||
|
int len = length();
|
||||||
|
int num_klasses = 0;
|
||||||
|
for (int i = 1; i <len; i++) {
|
||||||
|
switch (tag_at(i).value()) {
|
||||||
|
case JVM_CONSTANT_ClassIndex:
|
||||||
|
{
|
||||||
|
const int class_index = klass_index_at(i);
|
||||||
|
unresolved_klass_at_put(i, class_index, num_klasses++);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifndef PRODUCT
|
||||||
|
case JVM_CONSTANT_Class:
|
||||||
|
case JVM_CONSTANT_UnresolvedClass:
|
||||||
|
case JVM_CONSTANT_UnresolvedClassInError:
|
||||||
|
// All of these should have been reverted back to ClassIndex before calling
|
||||||
|
// this function.
|
||||||
|
ShouldNotReachHere();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allocate_resolved_klasses(loader_data, num_klasses, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anonymous class support:
|
||||||
|
void ConstantPool::klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name) {
|
||||||
|
assert(is_within_bounds(class_index), "index out of bounds");
|
||||||
|
assert(is_within_bounds(name_index), "index out of bounds");
|
||||||
|
assert((resolved_klass_index & 0xffff0000) == 0, "must be");
|
||||||
|
*int_at_addr(class_index) =
|
||||||
|
build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index);
|
||||||
|
|
||||||
|
symbol_at_put(name_index, name);
|
||||||
|
name->increment_refcount();
|
||||||
|
Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
|
||||||
|
OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
|
||||||
|
|
||||||
|
// The interpreter assumes when the tag is stored, the klass is resolved
|
||||||
|
// and the Klass* non-NULL, so we need hardware store ordering here.
|
||||||
|
if (k != NULL) {
|
||||||
|
release_tag_at_put(class_index, JVM_CONSTANT_Class);
|
||||||
|
} else {
|
||||||
|
release_tag_at_put(class_index, JVM_CONSTANT_UnresolvedClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anonymous class support:
|
||||||
|
void ConstantPool::klass_at_put(int class_index, Klass* k) {
|
||||||
|
assert(k != NULL, "must be valid klass");
|
||||||
|
CPKlassSlot kslot = klass_slot_at(class_index);
|
||||||
|
int resolved_klass_index = kslot.resolved_klass_index();
|
||||||
|
Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
|
||||||
|
OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
|
||||||
|
|
||||||
|
// The interpreter assumes when the tag is stored, the klass is resolved
|
||||||
|
// and the Klass* non-NULL, so we need hardware store ordering here.
|
||||||
|
release_tag_at_put(class_index, JVM_CONSTANT_Class);
|
||||||
|
}
|
||||||
|
|
||||||
// CDS support. Create a new resolved_references array.
|
// CDS support. Create a new resolved_references array.
|
||||||
void ConstantPool::restore_unshareable_info(TRAPS) {
|
void ConstantPool::restore_unshareable_info(TRAPS) {
|
||||||
assert(is_constantPool(), "ensure C++ vtable is restored");
|
assert(is_constantPool(), "ensure C++ vtable is restored");
|
||||||
|
assert(on_stack(), "should always be set for shared constant pools");
|
||||||
|
assert(is_shared(), "should always be set for shared constant pools");
|
||||||
|
|
||||||
// Only create the new resolved references array if it hasn't been attempted before
|
// Only create the new resolved references array if it hasn't been attempted before
|
||||||
if (resolved_references() != NULL) return;
|
if (resolved_references() != NULL) return;
|
||||||
|
@ -180,6 +248,12 @@ void ConstantPool::remove_unshareable_info() {
|
||||||
set_resolved_reference_length(
|
set_resolved_reference_length(
|
||||||
resolved_references() != NULL ? resolved_references()->length() : 0);
|
resolved_references() != NULL ? resolved_references()->length() : 0);
|
||||||
set_resolved_references(NULL);
|
set_resolved_references(NULL);
|
||||||
|
|
||||||
|
// Shared ConstantPools are in the RO region, so the _flags cannot be modified.
|
||||||
|
// The _on_stack flag is used to prevent ConstantPools from deallocation during
|
||||||
|
// class redefinition. Since shared ConstantPools cannot be deallocated anyway,
|
||||||
|
// we always set _on_stack to true to avoid having to change _flags during runtime.
|
||||||
|
_flags |= (_on_stack | _is_shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConstantPool::cp_to_object_index(int cp_index) {
|
int ConstantPool::cp_to_object_index(int cp_index) {
|
||||||
|
@ -229,11 +303,14 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
|
||||||
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
|
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
|
||||||
// It is not safe to rely on the tag bit's here, since we don't have a lock, and
|
// It is not safe to rely on the tag bit's here, since we don't have a lock, and
|
||||||
// the entry and tag is not updated atomicly.
|
// the entry and tag is not updated atomicly.
|
||||||
CPSlot entry = this_cp->slot_at(which);
|
CPKlassSlot kslot = this_cp->klass_slot_at(which);
|
||||||
if (entry.is_resolved()) {
|
int resolved_klass_index = kslot.resolved_klass_index();
|
||||||
assert(entry.get_klass()->is_klass(), "must be");
|
int name_index = kslot.name_index();
|
||||||
// Already resolved - return entry.
|
assert(this_cp->tag_at(name_index).is_symbol(), "sanity");
|
||||||
return entry.get_klass();
|
|
||||||
|
Klass* klass = this_cp->resolved_klasses()->at(resolved_klass_index);
|
||||||
|
if (klass != NULL) {
|
||||||
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This tag doesn't change back to unresolved class unless at a safepoint.
|
// This tag doesn't change back to unresolved class unless at a safepoint.
|
||||||
|
@ -251,7 +328,7 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle mirror_handle;
|
Handle mirror_handle;
|
||||||
Symbol* name = entry.get_symbol();
|
Symbol* name = this_cp->symbol_at(name_index);
|
||||||
Handle loader (THREAD, this_cp->pool_holder()->class_loader());
|
Handle loader (THREAD, this_cp->pool_holder()->class_loader());
|
||||||
Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
|
Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
|
||||||
Klass* k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
|
Klass* k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
|
||||||
|
@ -270,10 +347,9 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
|
||||||
// If CHECK_NULL above doesn't return the exception, that means that
|
// If CHECK_NULL above doesn't return the exception, that means that
|
||||||
// some other thread has beaten us and has resolved the class.
|
// some other thread has beaten us and has resolved the class.
|
||||||
// To preserve old behavior, we return the resolved class.
|
// To preserve old behavior, we return the resolved class.
|
||||||
entry = this_cp->resolved_klass_at(which);
|
klass = this_cp->resolved_klasses()->at(resolved_klass_index);
|
||||||
assert(entry.is_resolved(), "must be resolved if exception was cleared");
|
assert(klass != NULL, "must be resolved if exception was cleared");
|
||||||
assert(entry.get_klass()->is_klass(), "must be resolved to a klass");
|
return klass;
|
||||||
return entry.get_klass();
|
|
||||||
} else {
|
} else {
|
||||||
return NULL; // return the pending exception
|
return NULL; // return the pending exception
|
||||||
}
|
}
|
||||||
|
@ -287,10 +363,13 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
|
||||||
if (log_is_enabled(Debug, class, resolve)){
|
if (log_is_enabled(Debug, class, resolve)){
|
||||||
trace_class_resolution(this_cp, k);
|
trace_class_resolution(this_cp, k);
|
||||||
}
|
}
|
||||||
this_cp->klass_at_put(which, k);
|
Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index);
|
||||||
entry = this_cp->resolved_klass_at(which);
|
OrderAccess::release_store_ptr((Klass* volatile *)adr, k);
|
||||||
assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
|
// The interpreter assumes when the tag is stored, the klass is resolved
|
||||||
return entry.get_klass();
|
// and the Klass* stored in _resolved_klasses is non-NULL, so we need
|
||||||
|
// hardware store ordering here.
|
||||||
|
this_cp->release_tag_at_put(which, JVM_CONSTANT_Class);
|
||||||
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,14 +378,17 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
|
||||||
// instanceof operations. Returns NULL if the class has not been loaded or
|
// instanceof operations. Returns NULL if the class has not been loaded or
|
||||||
// if the verification of constant pool failed
|
// if the verification of constant pool failed
|
||||||
Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) {
|
Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) {
|
||||||
CPSlot entry = this_cp->slot_at(which);
|
CPKlassSlot kslot = this_cp->klass_slot_at(which);
|
||||||
if (entry.is_resolved()) {
|
int resolved_klass_index = kslot.resolved_klass_index();
|
||||||
assert(entry.get_klass()->is_klass(), "must be");
|
int name_index = kslot.name_index();
|
||||||
return entry.get_klass();
|
assert(this_cp->tag_at(name_index).is_symbol(), "sanity");
|
||||||
|
|
||||||
|
Klass* k = this_cp->resolved_klasses()->at(resolved_klass_index);
|
||||||
|
if (k != NULL) {
|
||||||
|
return k;
|
||||||
} else {
|
} else {
|
||||||
assert(entry.is_unresolved(), "must be either symbol or klass");
|
|
||||||
Thread *thread = Thread::current();
|
Thread *thread = Thread::current();
|
||||||
Symbol* name = entry.get_symbol();
|
Symbol* name = this_cp->symbol_at(name_index);
|
||||||
oop loader = this_cp->pool_holder()->class_loader();
|
oop loader = this_cp->pool_holder()->class_loader();
|
||||||
oop protection_domain = this_cp->pool_holder()->protection_domain();
|
oop protection_domain = this_cp->pool_holder()->protection_domain();
|
||||||
Handle h_prot (thread, protection_domain);
|
Handle h_prot (thread, protection_domain);
|
||||||
|
@ -484,22 +566,8 @@ Klass* ConstantPool::klass_ref_at(int which, TRAPS) {
|
||||||
return klass_at(klass_ref_index_at(which), THREAD);
|
return klass_at(klass_ref_index_at(which), THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Symbol* ConstantPool::klass_name_at(int which) const {
|
Symbol* ConstantPool::klass_name_at(int which) const {
|
||||||
assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
|
return symbol_at(klass_slot_at(which).name_index());
|
||||||
"Corrupted constant pool");
|
|
||||||
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
|
|
||||||
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
|
|
||||||
// tag is not updated atomicly.
|
|
||||||
CPSlot entry = slot_at(which);
|
|
||||||
if (entry.is_resolved()) {
|
|
||||||
// Already resolved - return entry's name.
|
|
||||||
assert(entry.get_klass()->is_klass(), "must be");
|
|
||||||
return entry.get_klass()->name();
|
|
||||||
} else {
|
|
||||||
assert(entry.is_unresolved(), "must be either symbol or klass");
|
|
||||||
return entry.get_symbol();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* ConstantPool::klass_ref_at_noresolve(int which) {
|
Symbol* ConstantPool::klass_ref_at_noresolve(int which) {
|
||||||
|
@ -850,7 +918,7 @@ bool ConstantPool::klass_name_at_matches(const InstanceKlass* k, int which) {
|
||||||
|
|
||||||
// Iterate over symbols and decrement ones which are Symbol*s
|
// Iterate over symbols and decrement ones which are Symbol*s
|
||||||
// This is done during GC.
|
// This is done during GC.
|
||||||
// Only decrement the UTF8 symbols. Unresolved classes and strings point to
|
// Only decrement the UTF8 symbols. Strings point to
|
||||||
// these symbols but didn't increment the reference count.
|
// these symbols but didn't increment the reference count.
|
||||||
void ConstantPool::unreference_symbols() {
|
void ConstantPool::unreference_symbols() {
|
||||||
for (int index = 1; index < length(); index++) { // Index 0 is unused
|
for (int index = 1; index < length(); index++) { // Index 0 is unused
|
||||||
|
@ -1231,12 +1299,6 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i,
|
||||||
|
|
||||||
int tag = from_cp->tag_at(from_i).value();
|
int tag = from_cp->tag_at(from_i).value();
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case JVM_CONSTANT_Class:
|
|
||||||
{
|
|
||||||
Klass* k = from_cp->klass_at(from_i, CHECK);
|
|
||||||
to_cp->klass_at_put(to_i, k);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case JVM_CONSTANT_ClassIndex:
|
case JVM_CONSTANT_ClassIndex:
|
||||||
{
|
{
|
||||||
jint ki = from_cp->klass_index_at(from_i);
|
jint ki = from_cp->klass_index_at(from_i);
|
||||||
|
@ -1305,18 +1367,14 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i,
|
||||||
to_cp->string_index_at_put(to_i, si);
|
to_cp->string_index_at_put(to_i, si);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_Class:
|
||||||
case JVM_CONSTANT_UnresolvedClass:
|
case JVM_CONSTANT_UnresolvedClass:
|
||||||
case JVM_CONSTANT_UnresolvedClassInError:
|
case JVM_CONSTANT_UnresolvedClassInError:
|
||||||
{
|
{
|
||||||
// Can be resolved after checking tag, so check the slot first.
|
// Revert to JVM_CONSTANT_ClassIndex
|
||||||
CPSlot entry = from_cp->slot_at(from_i);
|
int name_index = from_cp->klass_slot_at(from_i).name_index();
|
||||||
if (entry.is_resolved()) {
|
assert(from_cp->tag_at(name_index).is_symbol(), "sanity");
|
||||||
assert(entry.get_klass()->is_klass(), "must be");
|
to_cp->klass_index_at_put(to_i, name_index);
|
||||||
// Already resolved
|
|
||||||
to_cp->klass_at_put(to_i, entry.get_klass());
|
|
||||||
} else {
|
|
||||||
to_cp->unresolved_klass_at_put(to_i, entry.get_symbol());
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case JVM_CONSTANT_String:
|
case JVM_CONSTANT_String:
|
||||||
|
@ -1368,7 +1426,6 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i,
|
||||||
}
|
}
|
||||||
} // end copy_entry_to()
|
} // end copy_entry_to()
|
||||||
|
|
||||||
|
|
||||||
// Search constant pool search_cp for an entry that matches this
|
// Search constant pool search_cp for an entry that matches this
|
||||||
// constant pool's entry at pattern_i. Returns the index of a
|
// constant pool's entry at pattern_i. Returns the index of a
|
||||||
// matching entry or zero (0) if there is no matching entry.
|
// matching entry or zero (0) if there is no matching entry.
|
||||||
|
@ -1824,14 +1881,17 @@ void ConstantPool::set_on_stack(const bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
// Only record if it's not already set.
|
// Only record if it's not already set.
|
||||||
if (!on_stack()) {
|
if (!on_stack()) {
|
||||||
|
assert(!is_shared(), "should always be set for shared constant pools");
|
||||||
_flags |= _on_stack;
|
_flags |= _on_stack;
|
||||||
MetadataOnStackMark::record(this);
|
MetadataOnStackMark::record(this);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Clearing is done single-threadedly.
|
// Clearing is done single-threadedly.
|
||||||
|
if (!is_shared()) {
|
||||||
_flags &= ~_on_stack;
|
_flags &= ~_on_stack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// JSR 292 support for patching constant pool oops after the class is linked and
|
// JSR 292 support for patching constant pool oops after the class is linked and
|
||||||
// the oop array for resolved references are created.
|
// the oop array for resolved references are created.
|
||||||
|
@ -1905,6 +1965,7 @@ void ConstantPool::print_on(outputStream* st) const {
|
||||||
st->print_cr(" - cache: " INTPTR_FORMAT, p2i(cache()));
|
st->print_cr(" - cache: " INTPTR_FORMAT, p2i(cache()));
|
||||||
st->print_cr(" - resolved_references: " INTPTR_FORMAT, p2i(resolved_references()));
|
st->print_cr(" - resolved_references: " INTPTR_FORMAT, p2i(resolved_references()));
|
||||||
st->print_cr(" - reference_map: " INTPTR_FORMAT, p2i(reference_map()));
|
st->print_cr(" - reference_map: " INTPTR_FORMAT, p2i(reference_map()));
|
||||||
|
st->print_cr(" - resolved_klasses: " INTPTR_FORMAT, p2i(resolved_klasses()));
|
||||||
|
|
||||||
for (int index = 1; index < length(); index++) { // Index 0 is unused
|
for (int index = 1; index < length(); index++) { // Index 0 is unused
|
||||||
((ConstantPool*)this)->print_entry_on(index, st);
|
((ConstantPool*)this)->print_entry_on(index, st);
|
||||||
|
@ -1966,13 +2027,24 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) {
|
||||||
case JVM_CONSTANT_Utf8 :
|
case JVM_CONSTANT_Utf8 :
|
||||||
symbol_at(index)->print_value_on(st);
|
symbol_at(index)->print_value_on(st);
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_ClassIndex: {
|
||||||
|
int name_index = *int_at_addr(index);
|
||||||
|
st->print("klass_index=%d ", name_index);
|
||||||
|
symbol_at(name_index)->print_value_on(st);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case JVM_CONSTANT_UnresolvedClass : // fall-through
|
case JVM_CONSTANT_UnresolvedClass : // fall-through
|
||||||
case JVM_CONSTANT_UnresolvedClassInError: {
|
case JVM_CONSTANT_UnresolvedClassInError: {
|
||||||
CPSlot entry = slot_at(index);
|
CPKlassSlot kslot = klass_slot_at(index);
|
||||||
if (entry.is_resolved()) {
|
int resolved_klass_index = kslot.resolved_klass_index();
|
||||||
entry.get_klass()->print_value_on(st);
|
int name_index = kslot.name_index();
|
||||||
|
assert(tag_at(name_index).is_symbol(), "sanity");
|
||||||
|
|
||||||
|
Klass* klass = resolved_klasses()->at(resolved_klass_index);
|
||||||
|
if (klass != NULL) {
|
||||||
|
klass->print_value_on(st);
|
||||||
} else {
|
} else {
|
||||||
entry.get_symbol()->print_value_on(st);
|
symbol_at(name_index)->print_value_on(st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2044,18 +2116,13 @@ void ConstantPool::verify_on(outputStream* st) {
|
||||||
guarantee(is_constantPool(), "object must be constant pool");
|
guarantee(is_constantPool(), "object must be constant pool");
|
||||||
for (int i = 0; i< length(); i++) {
|
for (int i = 0; i< length(); i++) {
|
||||||
constantTag tag = tag_at(i);
|
constantTag tag = tag_at(i);
|
||||||
CPSlot entry = slot_at(i);
|
if (tag.is_klass() || tag.is_unresolved_klass()) {
|
||||||
if (tag.is_klass()) {
|
guarantee(klass_name_at(i)->refcount() != 0, "should have nonzero reference count");
|
||||||
if (entry.is_resolved()) {
|
|
||||||
guarantee(entry.get_klass()->is_klass(), "should be klass");
|
|
||||||
}
|
|
||||||
} else if (tag.is_unresolved_klass()) {
|
|
||||||
if (entry.is_resolved()) {
|
|
||||||
guarantee(entry.get_klass()->is_klass(), "should be klass");
|
|
||||||
}
|
|
||||||
} else if (tag.is_symbol()) {
|
} else if (tag.is_symbol()) {
|
||||||
|
CPSlot entry = slot_at(i);
|
||||||
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
|
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
|
||||||
} else if (tag.is_string()) {
|
} else if (tag.is_string()) {
|
||||||
|
CPSlot entry = slot_at(i);
|
||||||
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
|
guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,27 +46,47 @@
|
||||||
class SymbolHashMap;
|
class SymbolHashMap;
|
||||||
|
|
||||||
class CPSlot VALUE_OBJ_CLASS_SPEC {
|
class CPSlot VALUE_OBJ_CLASS_SPEC {
|
||||||
|
friend class ConstantPool;
|
||||||
intptr_t _ptr;
|
intptr_t _ptr;
|
||||||
|
enum TagBits {_pseudo_bit = 1};
|
||||||
public:
|
public:
|
||||||
enum TagBits { _resolved_value = 0, _symbol_bit = 1, _pseudo_bit = 2, _symbol_mask = 3 };
|
|
||||||
|
|
||||||
CPSlot(intptr_t ptr): _ptr(ptr) {}
|
CPSlot(intptr_t ptr): _ptr(ptr) {}
|
||||||
CPSlot(Klass* ptr): _ptr((intptr_t)ptr) {}
|
CPSlot(Symbol* ptr, int tag_bits = 0): _ptr((intptr_t)ptr | tag_bits) {}
|
||||||
CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | _symbol_bit) {}
|
|
||||||
CPSlot(Symbol* ptr, int tag_bits): _ptr((intptr_t)ptr | tag_bits) {}
|
|
||||||
|
|
||||||
intptr_t value() { return _ptr; }
|
intptr_t value() { return _ptr; }
|
||||||
bool is_resolved() { return (_ptr & _symbol_bit ) == _resolved_value; }
|
bool is_pseudo_string() { return (_ptr & _pseudo_bit) != 0; }
|
||||||
bool is_unresolved() { return (_ptr & _symbol_bit ) != _resolved_value; }
|
|
||||||
bool is_pseudo_string() { return (_ptr & _symbol_mask) == _symbol_bit + _pseudo_bit; }
|
|
||||||
|
|
||||||
Symbol* get_symbol() {
|
Symbol* get_symbol() {
|
||||||
assert(is_unresolved(), "bad call");
|
return (Symbol*)(_ptr & ~_pseudo_bit);
|
||||||
return (Symbol*)(_ptr & ~_symbol_mask);
|
|
||||||
}
|
}
|
||||||
Klass* get_klass() {
|
};
|
||||||
assert(is_resolved(), "bad call");
|
|
||||||
return (Klass*)_ptr;
|
// This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or
|
||||||
|
// JVM_CONSTANT_UnresolvedClassInError slot in the constant pool.
|
||||||
|
class CPKlassSlot VALUE_OBJ_CLASS_SPEC {
|
||||||
|
// cp->symbol_at(_name_index) gives the name of the class.
|
||||||
|
int _name_index;
|
||||||
|
|
||||||
|
// cp->_resolved_klasses->at(_resolved_klass_index) gives the Klass* for the class.
|
||||||
|
int _resolved_klass_index;
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
// This is used during constant pool merging where the resolved klass index is
|
||||||
|
// not yet known, and will be computed at a later stage (during a call to
|
||||||
|
// initialize_unresolved_klasses()).
|
||||||
|
_temp_resolved_klass_index = 0xffff
|
||||||
|
};
|
||||||
|
CPKlassSlot(int n, int rk) {
|
||||||
|
_name_index = n;
|
||||||
|
_resolved_klass_index = rk;
|
||||||
|
}
|
||||||
|
int name_index() const {
|
||||||
|
return _name_index;
|
||||||
|
}
|
||||||
|
int resolved_klass_index() const {
|
||||||
|
assert(_resolved_klass_index != _temp_resolved_klass_index, "constant pool merging was incomplete");
|
||||||
|
return _resolved_klass_index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,14 +103,14 @@ class ConstantPool : public Metadata {
|
||||||
InstanceKlass* _pool_holder; // the corresponding class
|
InstanceKlass* _pool_holder; // the corresponding class
|
||||||
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
|
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
|
||||||
|
|
||||||
// Array of resolved objects from the constant pool and map from resolved
|
// Consider using an array of compressed klass pointers to
|
||||||
// object index to original constant pool index
|
// save space on 64-bit platforms.
|
||||||
jobject _resolved_references;
|
Array<Klass*>* _resolved_klasses;
|
||||||
Array<u2>* _reference_map;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_has_preresolution = 1, // Flags
|
_has_preresolution = 1, // Flags
|
||||||
_on_stack = 2
|
_on_stack = 2,
|
||||||
|
_is_shared = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
int _flags; // old fashioned bit twiddling
|
int _flags; // old fashioned bit twiddling
|
||||||
|
@ -119,6 +139,7 @@ class ConstantPool : public Metadata {
|
||||||
|
|
||||||
CPSlot slot_at(int which) const {
|
CPSlot slot_at(int which) const {
|
||||||
assert(is_within_bounds(which), "index out of bounds");
|
assert(is_within_bounds(which), "index out of bounds");
|
||||||
|
assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool");
|
||||||
// Uses volatile because the klass slot changes without a lock.
|
// Uses volatile because the klass slot changes without a lock.
|
||||||
volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
|
volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
|
||||||
assert(adr != 0 || which == 0, "cp entry for klass should not be zero");
|
assert(adr != 0 || which == 0, "cp entry for klass should not be zero");
|
||||||
|
@ -166,7 +187,10 @@ class ConstantPool : public Metadata {
|
||||||
Array<u2>* operands() const { return _operands; }
|
Array<u2>* operands() const { return _operands; }
|
||||||
|
|
||||||
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
|
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
|
||||||
void set_has_preresolution() { _flags |= _has_preresolution; }
|
void set_has_preresolution() {
|
||||||
|
assert(!is_shared(), "should never be called on shared ConstantPools");
|
||||||
|
_flags |= _has_preresolution;
|
||||||
|
}
|
||||||
|
|
||||||
// Redefine classes support. If a method refering to this constant pool
|
// Redefine classes support. If a method refering to this constant pool
|
||||||
// is on the executing stack, or as a handle in vm code, this constant pool
|
// is on the executing stack, or as a handle in vm code, this constant pool
|
||||||
|
@ -175,6 +199,9 @@ class ConstantPool : public Metadata {
|
||||||
bool on_stack() const { return (_flags &_on_stack) != 0; }
|
bool on_stack() const { return (_flags &_on_stack) != 0; }
|
||||||
void set_on_stack(const bool value);
|
void set_on_stack(const bool value);
|
||||||
|
|
||||||
|
// Faster than MetaspaceObj::is_shared() - used by set_on_stack()
|
||||||
|
bool is_shared() const { return (_flags & _is_shared) != 0; }
|
||||||
|
|
||||||
// Klass holding pool
|
// Klass holding pool
|
||||||
InstanceKlass* pool_holder() const { return _pool_holder; }
|
InstanceKlass* pool_holder() const { return _pool_holder; }
|
||||||
void set_pool_holder(InstanceKlass* k) { _pool_holder = k; }
|
void set_pool_holder(InstanceKlass* k) { _pool_holder = k; }
|
||||||
|
@ -193,9 +220,14 @@ class ConstantPool : public Metadata {
|
||||||
// resolved strings, methodHandles and callsite objects from the constant pool
|
// resolved strings, methodHandles and callsite objects from the constant pool
|
||||||
objArrayOop resolved_references() const;
|
objArrayOop resolved_references() const;
|
||||||
// mapping resolved object array indexes to cp indexes and back.
|
// mapping resolved object array indexes to cp indexes and back.
|
||||||
int object_to_cp_index(int index) { return _reference_map->at(index); }
|
int object_to_cp_index(int index) { return reference_map()->at(index); }
|
||||||
int cp_to_object_index(int index);
|
int cp_to_object_index(int index);
|
||||||
|
|
||||||
|
void set_resolved_klasses(Array<Klass*>* rk) { _resolved_klasses = rk; }
|
||||||
|
Array<Klass*>* resolved_klasses() const { return _resolved_klasses; }
|
||||||
|
void allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS);
|
||||||
|
void initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS);
|
||||||
|
|
||||||
// Invokedynamic indexes.
|
// Invokedynamic indexes.
|
||||||
// They must look completely different from normal indexes.
|
// They must look completely different from normal indexes.
|
||||||
// The main reason is that byte swapping is sometimes done on normal indexes.
|
// The main reason is that byte swapping is sometimes done on normal indexes.
|
||||||
|
@ -223,30 +255,27 @@ class ConstantPool : public Metadata {
|
||||||
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
|
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
|
||||||
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
|
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
|
||||||
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
|
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
|
||||||
static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); }
|
static int resolved_klasses_offset_in_bytes() { return offset_of(ConstantPool, _resolved_klasses); }
|
||||||
|
|
||||||
// Storing constants
|
// Storing constants
|
||||||
|
|
||||||
void klass_at_put(int which, Klass* k) {
|
|
||||||
assert(k != NULL, "resolved class shouldn't be null");
|
|
||||||
assert(is_within_bounds(which), "index out of bounds");
|
|
||||||
OrderAccess::release_store_ptr((Klass* volatile *)obj_at_addr_raw(which), k);
|
|
||||||
// The interpreter assumes when the tag is stored, the klass is resolved
|
|
||||||
// and the Klass* is a klass rather than a Symbol*, so we need
|
|
||||||
// hardware store ordering here.
|
|
||||||
release_tag_at_put(which, JVM_CONSTANT_Class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For temporary use while constructing constant pool
|
// For temporary use while constructing constant pool
|
||||||
void klass_index_at_put(int which, int name_index) {
|
void klass_index_at_put(int which, int name_index) {
|
||||||
tag_at_put(which, JVM_CONSTANT_ClassIndex);
|
tag_at_put(which, JVM_CONSTANT_ClassIndex);
|
||||||
*int_at_addr(which) = name_index;
|
*int_at_addr(which) = name_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary until actual use
|
// Anonymous class support:
|
||||||
void unresolved_klass_at_put(int which, Symbol* s) {
|
void klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name);
|
||||||
|
void klass_at_put(int class_index, Klass* k);
|
||||||
|
|
||||||
|
void unresolved_klass_at_put(int which, int name_index, int resolved_klass_index) {
|
||||||
release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
|
release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
|
||||||
slot_at_put(which, s);
|
|
||||||
|
assert((name_index & 0xffff0000) == 0, "must be");
|
||||||
|
assert((resolved_klass_index & 0xffff0000) == 0, "must be");
|
||||||
|
*int_at_addr(which) =
|
||||||
|
build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
|
void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
|
||||||
|
@ -266,7 +295,7 @@ class ConstantPool : public Metadata {
|
||||||
|
|
||||||
void unresolved_string_at_put(int which, Symbol* s) {
|
void unresolved_string_at_put(int which, Symbol* s) {
|
||||||
release_tag_at_put(which, JVM_CONSTANT_String);
|
release_tag_at_put(which, JVM_CONSTANT_String);
|
||||||
slot_at_put(which, CPSlot(s, CPSlot::_symbol_bit));
|
slot_at_put(which, CPSlot(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void int_at_put(int which, jint i) {
|
void int_at_put(int which, jint i) {
|
||||||
|
@ -348,17 +377,38 @@ class ConstantPool : public Metadata {
|
||||||
return klass_at_impl(h_this, which, false, THREAD);
|
return klass_at_impl(h_this, which, false, THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPKlassSlot klass_slot_at(int which) const {
|
||||||
|
assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
|
||||||
|
"Corrupted constant pool");
|
||||||
|
int value = *int_at_addr(which);
|
||||||
|
int name_index = extract_high_short_from_int(value);
|
||||||
|
int resolved_klass_index = extract_low_short_from_int(value);
|
||||||
|
return CPKlassSlot(name_index, resolved_klass_index);
|
||||||
|
}
|
||||||
|
|
||||||
Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving.
|
Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving.
|
||||||
|
int klass_name_index_at(int which) const {
|
||||||
|
return klass_slot_at(which).name_index();
|
||||||
|
}
|
||||||
|
|
||||||
Klass* resolved_klass_at(int which) const { // Used by Compiler
|
Klass* resolved_klass_at(int which) const { // Used by Compiler
|
||||||
guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
|
guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
|
||||||
// Must do an acquire here in case another thread resolved the klass
|
// Must do an acquire here in case another thread resolved the klass
|
||||||
// behind our back, lest we later load stale values thru the oop.
|
// behind our back, lest we later load stale values thru the oop.
|
||||||
return CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass();
|
CPKlassSlot kslot = klass_slot_at(which);
|
||||||
|
assert(tag_at(kslot.name_index()).is_symbol(), "sanity");
|
||||||
|
|
||||||
|
Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index());
|
||||||
|
return (Klass*)OrderAccess::load_ptr_acquire(adr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
|
Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
|
||||||
|
void temp_unresolved_klass_at_put(int which, int name_index) {
|
||||||
|
// Used only during constant pool merging for class redefinition. The resolved klass index
|
||||||
|
// will be initialized later by a call to initialize_unresolved_klasses().
|
||||||
|
unresolved_klass_at_put(which, name_index, CPKlassSlot::_temp_resolved_klass_index);
|
||||||
|
}
|
||||||
|
|
||||||
jint int_at(int which) {
|
jint int_at(int which) {
|
||||||
assert(tag_at(which).is_int(), "Corrupted constant pool");
|
assert(tag_at(which).is_int(), "Corrupted constant pool");
|
||||||
|
@ -428,7 +478,7 @@ class ConstantPool : public Metadata {
|
||||||
void pseudo_string_at_put(int which, int obj_index, oop x) {
|
void pseudo_string_at_put(int which, int obj_index, oop x) {
|
||||||
assert(tag_at(which).is_string(), "Corrupted constant pool");
|
assert(tag_at(which).is_string(), "Corrupted constant pool");
|
||||||
Symbol* sym = unresolved_string_at(which);
|
Symbol* sym = unresolved_string_at(which);
|
||||||
slot_at_put(which, CPSlot(sym, (CPSlot::_symbol_bit | CPSlot::_pseudo_bit)));
|
slot_at_put(which, CPSlot(sym, CPSlot::_pseudo_bit));
|
||||||
string_at_put(which, obj_index, x); // this works just fine
|
string_at_put(which, obj_index, x); // this works just fine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,9 +811,9 @@ class ConstantPool : public Metadata {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void set_resolved_references(jobject s) { _resolved_references = s; }
|
void set_resolved_references(jobject s) { _cache->set_resolved_references(s); }
|
||||||
Array<u2>* reference_map() const { return _reference_map; }
|
Array<u2>* reference_map() const { return (_cache == NULL) ? NULL : _cache->reference_map(); }
|
||||||
void set_reference_map(Array<u2>* o) { _reference_map = o; }
|
void set_reference_map(Array<u2>* o) { _cache->set_reference_map(o); }
|
||||||
|
|
||||||
// patch JSR 292 resolved references after the class is linked.
|
// patch JSR 292 resolved references after the class is linked.
|
||||||
void patch_resolved_references(GrowableArray<Handle>* cp_patches);
|
void patch_resolved_references(GrowableArray<Handle>* cp_patches);
|
||||||
|
|
|
@ -404,6 +404,13 @@ class ConstantPoolCache: public MetaspaceObj {
|
||||||
int _length;
|
int _length;
|
||||||
ConstantPool* _constant_pool; // the corresponding constant pool
|
ConstantPool* _constant_pool; // the corresponding constant pool
|
||||||
|
|
||||||
|
// The following fields need to be modified at runtime, so they cannot be
|
||||||
|
// stored in the ConstantPool, which is read-only.
|
||||||
|
// Array of resolved objects from the constant pool and map from resolved
|
||||||
|
// object index to original constant pool index
|
||||||
|
jobject _resolved_references;
|
||||||
|
Array<u2>* _reference_map;
|
||||||
|
|
||||||
// Sizing
|
// Sizing
|
||||||
debug_only(friend class ClassVerifier;)
|
debug_only(friend class ClassVerifier;)
|
||||||
|
|
||||||
|
@ -433,6 +440,15 @@ class ConstantPoolCache: public MetaspaceObj {
|
||||||
bool is_constantPoolCache() const { return true; }
|
bool is_constantPoolCache() const { return true; }
|
||||||
|
|
||||||
int length() const { return _length; }
|
int length() const { return _length; }
|
||||||
|
|
||||||
|
jobject resolved_references() { return _resolved_references; }
|
||||||
|
void set_resolved_references(jobject s) { _resolved_references = s; }
|
||||||
|
Array<u2>* reference_map() const { return _reference_map; }
|
||||||
|
void set_reference_map(Array<u2>* o) { _reference_map = o; }
|
||||||
|
|
||||||
|
// Assembly code support
|
||||||
|
static int resolved_references_offset_in_bytes() { return offset_of(ConstantPoolCache, _resolved_references); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_length(int length) { _length = length; }
|
void set_length(int length) { _length = length; }
|
||||||
|
|
||||||
|
|
|
@ -292,12 +292,22 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp,
|
||||||
// entries in the input constant pool. We revert the appended copy
|
// entries in the input constant pool. We revert the appended copy
|
||||||
// back to UnresolvedClass so that either verifier will be happy
|
// back to UnresolvedClass so that either verifier will be happy
|
||||||
// with the constant pool entry.
|
// with the constant pool entry.
|
||||||
|
//
|
||||||
|
// this is an indirect CP entry so it needs special handling
|
||||||
case JVM_CONSTANT_Class:
|
case JVM_CONSTANT_Class:
|
||||||
|
case JVM_CONSTANT_UnresolvedClass:
|
||||||
{
|
{
|
||||||
// revert the copy to JVM_CONSTANT_UnresolvedClass
|
int name_i = scratch_cp->klass_name_index_at(scratch_i);
|
||||||
(*merge_cp_p)->unresolved_klass_at_put(*merge_cp_length_p,
|
int new_name_i = find_or_append_indirect_entry(scratch_cp, name_i, merge_cp_p,
|
||||||
scratch_cp->klass_name_at(scratch_i));
|
merge_cp_length_p, THREAD);
|
||||||
|
|
||||||
|
if (new_name_i != name_i) {
|
||||||
|
log_trace(redefine, class, constantpool)
|
||||||
|
("Class entry@%d name_index change: %d to %d",
|
||||||
|
*merge_cp_length_p, name_i, new_name_i);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*merge_cp_p)->temp_unresolved_klass_at_put(*merge_cp_length_p, new_name_i);
|
||||||
if (scratch_i != *merge_cp_length_p) {
|
if (scratch_i != *merge_cp_length_p) {
|
||||||
// The new entry in *merge_cp_p is at a different index than
|
// The new entry in *merge_cp_p is at a different index than
|
||||||
// the new entry in scratch_cp so we need to map the index values.
|
// the new entry in scratch_cp so we need to map the index values.
|
||||||
|
@ -330,10 +340,6 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp,
|
||||||
// This was an indirect CP entry, but it has been changed into
|
// This was an indirect CP entry, but it has been changed into
|
||||||
// Symbol*s so this entry can be directly appended.
|
// Symbol*s so this entry can be directly appended.
|
||||||
case JVM_CONSTANT_String: // fall through
|
case JVM_CONSTANT_String: // fall through
|
||||||
|
|
||||||
// These were indirect CP entries, but they have been changed into
|
|
||||||
// Symbol*s so these entries can be directly appended.
|
|
||||||
case JVM_CONSTANT_UnresolvedClass: // fall through
|
|
||||||
{
|
{
|
||||||
ConstantPool::copy_entry_to(scratch_cp, scratch_i, *merge_cp_p, *merge_cp_length_p,
|
ConstantPool::copy_entry_to(scratch_cp, scratch_i, *merge_cp_p, *merge_cp_length_p,
|
||||||
THREAD);
|
THREAD);
|
||||||
|
@ -504,7 +510,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp,
|
||||||
(*merge_cp_length_p)++;
|
(*merge_cp_length_p)++;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// At this stage, Class or UnresolvedClass could be here, but not
|
// At this stage, Class or UnresolvedClass could be in scratch_cp, but not
|
||||||
// ClassIndex
|
// ClassIndex
|
||||||
case JVM_CONSTANT_ClassIndex: // fall through
|
case JVM_CONSTANT_ClassIndex: // fall through
|
||||||
|
|
||||||
|
@ -1270,8 +1276,8 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp,
|
||||||
// revert the copy to JVM_CONSTANT_UnresolvedClass
|
// revert the copy to JVM_CONSTANT_UnresolvedClass
|
||||||
// May be resolving while calling this so do the same for
|
// May be resolving while calling this so do the same for
|
||||||
// JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition)
|
// JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition)
|
||||||
(*merge_cp_p)->unresolved_klass_at_put(old_i,
|
(*merge_cp_p)->temp_unresolved_klass_at_put(old_i,
|
||||||
old_cp->klass_name_at(old_i));
|
old_cp->klass_name_index_at(old_i));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JVM_CONSTANT_Double:
|
case JVM_CONSTANT_Double:
|
||||||
|
@ -3102,6 +3108,7 @@ void VM_RedefineClasses::set_new_constant_pool(
|
||||||
|
|
||||||
// attach new constant pool to klass
|
// attach new constant pool to klass
|
||||||
scratch_class->set_constants(scratch_cp());
|
scratch_class->set_constants(scratch_cp());
|
||||||
|
scratch_cp->initialize_unresolved_klasses(loader_data, CHECK);
|
||||||
|
|
||||||
int i; // for portability
|
int i; // for portability
|
||||||
|
|
||||||
|
|
|
@ -238,8 +238,8 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||||
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
|
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
|
||||||
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
|
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
|
||||||
nonstatic_field(ConstantPool, _length, int) \
|
nonstatic_field(ConstantPool, _length, int) \
|
||||||
nonstatic_field(ConstantPool, _resolved_references, jobject) \
|
nonstatic_field(ConstantPoolCache, _resolved_references, jobject) \
|
||||||
nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
|
nonstatic_field(ConstantPoolCache, _reference_map, Array<u2>*) \
|
||||||
nonstatic_field(ConstantPoolCache, _length, int) \
|
nonstatic_field(ConstantPoolCache, _length, int) \
|
||||||
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
|
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
|
||||||
volatile_nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
|
volatile_nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class LimitSharedSizes {
|
||||||
|
|
||||||
// test with sizes which just meet the minimum required sizes
|
// test with sizes which just meet the minimum required sizes
|
||||||
// the following tests also attempt to use the shared archive
|
// the following tests also attempt to use the shared archive
|
||||||
new SharedSizeTestData(Region.RO, Platform.is64bit() ? "10M":"9M", Result.VALID_ARCHIVE),
|
new SharedSizeTestData(Region.RO, Platform.is64bit() ? "14M":"9M", Result.VALID_ARCHIVE),
|
||||||
new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE),
|
new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE),
|
||||||
new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE),
|
new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE),
|
||||||
new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),
|
new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue