mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-14 15:39:45 +00:00
Merge
This commit is contained in:
commit
80ba6df9d7
@ -5343,6 +5343,17 @@ operand immI_M1()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Shift values for add/sub extension shift
|
||||
operand immIExt()
|
||||
%{
|
||||
predicate(0 <= n->get_int() && (n->get_int() <= 4));
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immI_le_4()
|
||||
%{
|
||||
predicate(n->get_int() <= 4);
|
||||
@ -12789,7 +12800,7 @@ instruct AddExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (ConvI2L src2)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxtw $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxtw" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12802,7 +12813,7 @@ instruct SubExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (ConvI2L src2)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "sub $dst, $src1, sxtw $src2" %}
|
||||
format %{ "sub $dst, $src1, $src2, sxtw" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12816,7 +12827,7 @@ instruct AddExtI_sxth(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_16 l
|
||||
%{
|
||||
match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxth $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxth" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12829,7 +12840,7 @@ instruct AddExtI_sxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 l
|
||||
%{
|
||||
match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxtb $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxtb" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12842,7 +12853,7 @@ instruct AddExtI_uxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 l
|
||||
%{
|
||||
match(Set dst (AddI src1 (URShiftI (LShiftI src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, uxtb $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, uxtb" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12855,7 +12866,7 @@ instruct AddExtL_sxth(iRegLNoSp dst, iRegL src1, iRegL src2, immI_48 lshift, imm
|
||||
%{
|
||||
match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxth $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxth" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12868,7 +12879,7 @@ instruct AddExtL_sxtw(iRegLNoSp dst, iRegL src1, iRegL src2, immI_32 lshift, imm
|
||||
%{
|
||||
match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxtw $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxtw" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12881,7 +12892,7 @@ instruct AddExtL_sxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, imm
|
||||
%{
|
||||
match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, sxtb $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, sxtb" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -12894,7 +12905,7 @@ instruct AddExtL_uxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, imm
|
||||
%{
|
||||
match(Set dst (AddL src1 (URShiftL (LShiftL src2 lshift) rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src1, uxtb $src2" %}
|
||||
format %{ "add $dst, $src1, $src2, uxtb" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -13034,6 +13045,294 @@ instruct SubExtL_uxtw_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
|
||||
instruct AddExtL_sxtb_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_56 lshift1, immI_56 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, sxtb #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtL_sxth_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_48 lshift1, immI_48 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, sxth #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxth, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtL_sxtw_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_32 lshift1, immI_32 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, sxtw #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtw, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_sxtb_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_56 lshift1, immI_56 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, sxtb #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_sxth_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_48 lshift1, immI_48 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, sxth #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxth, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_sxtw_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_32 lshift1, immI_32 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, sxtw #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtw, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtI_sxtb_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_24 lshift1, immI_24 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "addw $dst, $src1, $src2, sxtb #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ addw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtI_sxth_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_16 lshift1, immI_16 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "addw $dst, $src1, $src2, sxth #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ addw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxth, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtI_sxtb_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_24 lshift1, immI_24 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "subw $dst, $src1, $src2, sxtb #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ subw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtI_sxth_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_16 lshift1, immI_16 rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "subw $dst, $src1, $src2, sxth #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ subw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxth, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
|
||||
instruct AddExtI_shift(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (ConvI2L src2) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, sxtw #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtw, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%};
|
||||
|
||||
instruct SubExtI_shift(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (ConvI2L src2) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, sxtw #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::sxtw, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%};
|
||||
|
||||
|
||||
instruct AddExtL_uxtb_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, uxtb #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtb, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtL_uxth_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, uxth #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxth, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtL_uxtw_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "add $dst, $src1, $src2, uxtw #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtw, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_uxtb_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, uxtb #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtb, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_uxth_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, uxth #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxth, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtL_uxtw_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "sub $dst, $src1, $src2, uxtw #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ sub(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtw, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtI_uxtb_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI src1 (LShiftI (AndI src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "addw $dst, $src1, $src2, uxtb #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ addw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtb, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct AddExtI_uxth_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI src1 (LShiftI (AndI src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "addw $dst, $src1, $src2, uxth #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ addw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxth, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtI_uxtb_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI src1 (LShiftI (AndI src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "subw $dst, $src1, $src2, uxtb #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ subw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxtb, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
|
||||
instruct SubExtI_uxth_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI src1 (LShiftI (AndI src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "subw $dst, $src1, $src2, uxth #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ subw(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::uxth, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}
|
||||
// END This section of the file is automatically generated. Do not edit --------------
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@ -268,21 +268,21 @@ instruct $2$1_rReg(iReg$1NoSp dst, iReg$1 src, iRegI shift, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_reg_vshift);
|
||||
%}')dnl
|
||||
define(ROL_INSN, `
|
||||
instruct $3$1_rReg_Var_C$2(iRegLNoSp dst, iRegL src, iRegI shift, immI$2 c$2, rFlagsReg cr)
|
||||
instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (Or$1 (LShift$1 src shift) (URShift$1 src (SubI c$2 shift))));
|
||||
|
||||
expand %{
|
||||
$3L_rReg(dst, src, shift, cr);
|
||||
$3$1_rReg(dst, src, shift, cr);
|
||||
%}
|
||||
%}')dnl
|
||||
define(ROR_INSN, `
|
||||
instruct $3$1_rReg_Var_C$2(iRegLNoSp dst, iRegL src, iRegI shift, immI$2 c$2, rFlagsReg cr)
|
||||
instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (Or$1 (URShift$1 src shift) (LShift$1 src (SubI c$2 shift))));
|
||||
|
||||
expand %{
|
||||
$3L_rReg(dst, src, shift, cr);
|
||||
$3$1_rReg(dst, src, shift, cr);
|
||||
%}
|
||||
%}')dnl
|
||||
ROL_EXPAND(L, rol, rorv)
|
||||
@ -305,7 +305,7 @@ instruct $3Ext$1(iReg$2NoSp dst, iReg$2`'ORL2I($2) src1, iReg$1`'ORL2I($1) src2,
|
||||
%{
|
||||
match(Set dst ($3$2 src1 (ConvI2L src2)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "$4 $dst, $src1, $5 $src2" %}
|
||||
format %{ "$4 $dst, $src1, $src2, $5" %}
|
||||
|
||||
ins_encode %{
|
||||
__ $4(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -321,7 +321,7 @@ instruct $3Ext$1_$6(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) sr
|
||||
%{
|
||||
match(Set dst ($3$1 src1 EXTEND($1, $4, src2, lshift, rshift)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "$5 $dst, $src1, $6 $src2" %}
|
||||
format %{ "$5 $dst, $src1, $src2, $6" %}
|
||||
|
||||
ins_encode %{
|
||||
__ $5(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
@ -363,5 +363,82 @@ ADD_SUB_ZERO_EXTEND(I,65535,Sub,subw,uxth)
|
||||
ADD_SUB_ZERO_EXTEND(L,255,Sub,sub,uxtb)
|
||||
ADD_SUB_ZERO_EXTEND(L,65535,Sub,sub,uxth)
|
||||
ADD_SUB_ZERO_EXTEND(L,4294967295,Sub,sub,uxtw)
|
||||
dnl
|
||||
dnl ADD_SUB_ZERO_EXTEND_SHIFT(mode, size, add node, insn, ext type)
|
||||
define(`ADD_SUB_EXTENDED_SHIFT', `
|
||||
instruct $3Ext$1_$6_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immIExt lshift2, immI_`'eval($7-$2) lshift1, immI_`'eval($7-$2) rshift1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst ($3$1 src1 (LShift$1 EXTEND($1, $4, src2, lshift1, rshift1) lshift2)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "$5 $dst, $src1, $src2, $6 #lshift2" %}
|
||||
|
||||
ins_encode %{
|
||||
__ $5(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::$6, ($lshift2$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}')
|
||||
dnl $1 $2 $3 $4 $5 $6 $7
|
||||
ADD_SUB_EXTENDED_SHIFT(L,8,Add,RShift,add,sxtb,64)
|
||||
ADD_SUB_EXTENDED_SHIFT(L,16,Add,RShift,add,sxth,64)
|
||||
ADD_SUB_EXTENDED_SHIFT(L,32,Add,RShift,add,sxtw,64)
|
||||
dnl
|
||||
ADD_SUB_EXTENDED_SHIFT(L,8,Sub,RShift,sub,sxtb,64)
|
||||
ADD_SUB_EXTENDED_SHIFT(L,16,Sub,RShift,sub,sxth,64)
|
||||
ADD_SUB_EXTENDED_SHIFT(L,32,Sub,RShift,sub,sxtw,64)
|
||||
dnl
|
||||
ADD_SUB_EXTENDED_SHIFT(I,8,Add,RShift,addw,sxtb,32)
|
||||
ADD_SUB_EXTENDED_SHIFT(I,16,Add,RShift,addw,sxth,32)
|
||||
dnl
|
||||
ADD_SUB_EXTENDED_SHIFT(I,8,Sub,RShift,subw,sxtb,32)
|
||||
ADD_SUB_EXTENDED_SHIFT(I,16,Sub,RShift,subw,sxth,32)
|
||||
dnl
|
||||
dnl ADD_SUB_CONV_SHIFT(mode, add node, insn, ext type)
|
||||
define(`ADD_SUB_CONV_SHIFT', `
|
||||
instruct $2ExtI_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst ($2$1 src1 (LShiftL (ConvI2L src2) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "$3 $dst, $src1, $src2, $4 #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ $3(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::$4, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}')
|
||||
dnl
|
||||
ADD_SUB_CONV_SHIFT(L,Add,add,sxtw);
|
||||
ADD_SUB_CONV_SHIFT(L,Sub,sub,sxtw);
|
||||
dnl
|
||||
dnl ADD_SUB_ZERO_EXTEND(mode, size, add node, insn, ext type)
|
||||
define(`ADD_SUB_ZERO_EXTEND_SHIFT', `
|
||||
instruct $3Ext$1_$5_and_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, imm$1_$2 mask, immIExt lshift, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst ($3$1 src1 (LShift$1 (And$1 src2 mask) lshift)));
|
||||
ins_cost(1.9 * INSN_COST);
|
||||
format %{ "$4 $dst, $src1, $src2, $5 #lshift" %}
|
||||
|
||||
ins_encode %{
|
||||
__ $4(as_Register($dst$$reg), as_Register($src1$$reg),
|
||||
as_Register($src2$$reg), ext::$5, ($lshift$$constant));
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_shift);
|
||||
%}')
|
||||
dnl
|
||||
dnl $1 $2 $3 $4 $5
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,255,Add,add,uxtb)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,65535,Add,add,uxth)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,4294967295,Add,add,uxtw)
|
||||
dnl
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,255,Sub,sub,uxtb)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,65535,Sub,sub,uxth)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(L,4294967295,Sub,sub,uxtw)
|
||||
dnl
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(I,255,Add,addw,uxtb)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(I,65535,Add,addw,uxth)
|
||||
dnl
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(I,255,Sub,subw,uxtb)
|
||||
ADD_SUB_ZERO_EXTEND_SHIFT(I,65535,Sub,subw,uxth)
|
||||
dnl
|
||||
// END This section of the file is automatically generated. Do not edit --------------
|
||||
|
||||
@ -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.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -369,7 +369,7 @@ class SlowSignatureHandler
|
||||
}
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to)
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to)
|
||||
: NativeSignatureIterator(method)
|
||||
{
|
||||
_from = from;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -47,7 +47,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
|
||||
public:
|
||||
// Creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
_num_int_args = (method->is_static() ? 1 : 0);
|
||||
_num_fp_args = 0;
|
||||
|
||||
@ -169,6 +169,7 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
template<class T>
|
||||
inline void cmpw(Register Rd, T imm) { subsw(zr, Rd, imm); }
|
||||
// imm is limited to 12 bits.
|
||||
inline void cmp(Register Rd, unsigned imm) { subs(zr, Rd, imm); }
|
||||
|
||||
inline void cmnw(Register Rd, unsigned imm) { addsw(zr, Rd, imm); }
|
||||
|
||||
@ -1207,7 +1207,7 @@ static void rt_call(MacroAssembler* masm, address dest, int gpargs, int fpargs,
|
||||
}
|
||||
|
||||
static void verify_oop_args(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
Register temp_reg = r19; // not part of any compiled calling seq
|
||||
@ -1229,7 +1229,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -764,7 +764,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// alignment.
|
||||
Label small;
|
||||
int low_limit = MAX2(zva_length * 2, (int)BlockZeroingLowLimit);
|
||||
__ cmp(cnt, low_limit >> 3);
|
||||
__ subs(rscratch1, cnt, low_limit >> 3);
|
||||
__ br(Assembler::LT, small);
|
||||
__ zero_dcache_blocks(base, cnt);
|
||||
__ bind(small);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -422,7 +422,7 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
#endif // !__ABI_HARD__
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to) :
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) :
|
||||
NativeSignatureIterator(method) {
|
||||
_from = from;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -56,7 +56,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
#endif
|
||||
public:
|
||||
// Creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
_abi_offset = 0;
|
||||
_ireg = is_static() ? 2 : 1;
|
||||
|
||||
@ -1024,7 +1024,7 @@ static int reg2offset_out(VMReg r) {
|
||||
|
||||
|
||||
static void verify_oop_args(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
Register temp_reg = Rmethod; // not part of any compiled calling seq
|
||||
@ -1045,7 +1045,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -45,7 +45,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
|
||||
public:
|
||||
// Creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
_num_used_fp_arg_regs = 0;
|
||||
}
|
||||
|
||||
@ -1610,7 +1610,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType
|
||||
}
|
||||
|
||||
static void verify_oop_args(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
Register temp_reg = R19_method; // not part of any compiled calling seq
|
||||
@ -1632,7 +1632,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -1139,14 +1139,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
__ load_const_optimized(Z_R1_scratch, pp);
|
||||
|
||||
// Pop the frame before the safepoint code.
|
||||
int retPC_offset = initial_frame_size_in_bytes() + _z_abi16(return_pc);
|
||||
if (Displacement::is_validDisp(retPC_offset)) {
|
||||
__ z_lg(Z_R14, retPC_offset, Z_SP);
|
||||
__ add2reg(Z_SP, initial_frame_size_in_bytes());
|
||||
} else {
|
||||
__ add2reg(Z_SP, initial_frame_size_in_bytes());
|
||||
__ restore_return_pc();
|
||||
}
|
||||
__ pop_frame_restore_retPC(initial_frame_size_in_bytes());
|
||||
|
||||
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
|
||||
__ reserved_stack_check(Z_R14);
|
||||
|
||||
@ -70,7 +70,7 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by
|
||||
assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
|
||||
generate_stack_overflow_check(bang_size_in_bytes);
|
||||
save_return_pc();
|
||||
push_frame(frame_size_in_bytes); // TODO: Must we add z_abi_160?
|
||||
push_frame(frame_size_in_bytes);
|
||||
}
|
||||
|
||||
void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -51,7 +51,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
|
||||
public:
|
||||
// creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
_fp_arg_nr = 0;
|
||||
}
|
||||
|
||||
@ -2022,17 +2022,41 @@ void MacroAssembler::resize_frame_sub(Register offset, Register fp, bool load_fp
|
||||
z_stg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
// Resize_frame with SP(new) = [addr].
|
||||
void MacroAssembler::resize_frame_absolute(Register addr, Register fp, bool load_fp) {
|
||||
assert_different_registers(addr, fp, Z_SP);
|
||||
if (load_fp) { z_lg(fp, _z_abi(callers_sp), Z_SP); }
|
||||
// Resize_frame with SP(new) = [newSP] + offset.
|
||||
// This emitter is useful if we already have calculated a pointer
|
||||
// into the to-be-allocated stack space, e.g. with special alignment properties,
|
||||
// but need some additional space, e.g. for spilling.
|
||||
// newSP is the pre-calculated pointer. It must not be modified.
|
||||
// fp holds, or is filled with, the frame pointer.
|
||||
// offset is the additional increment which is added to addr to form the new SP.
|
||||
// Note: specify a negative value to reserve more space!
|
||||
// load_fp == true only indicates that fp is not pre-filled with the frame pointer.
|
||||
// It does not guarantee that fp contains the frame pointer at the end.
|
||||
void MacroAssembler::resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp) {
|
||||
assert_different_registers(newSP, fp, Z_SP);
|
||||
|
||||
if (addr != Z_R0) {
|
||||
// Minimize stalls by not using Z_SP immediately after update.
|
||||
z_stg(fp, _z_abi(callers_sp), addr);
|
||||
z_lgr(Z_SP, addr);
|
||||
if (load_fp) {
|
||||
z_lg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
add2reg(Z_SP, offset, newSP);
|
||||
z_stg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
// Resize_frame with SP(new) = [newSP].
|
||||
// load_fp == true only indicates that fp is not pre-filled with the frame pointer.
|
||||
// It does not guarantee that fp contains the frame pointer at the end.
|
||||
void MacroAssembler::resize_frame_absolute(Register newSP, Register fp, bool load_fp) {
|
||||
assert_different_registers(newSP, fp, Z_SP);
|
||||
|
||||
if (load_fp) {
|
||||
z_lg(fp, _z_abi(callers_sp), Z_SP); // need to use load/store.
|
||||
}
|
||||
|
||||
z_lgr(Z_SP, newSP);
|
||||
if (newSP != Z_R0) { // make sure we generate correct code, no matter what register newSP uses.
|
||||
z_stg(fp, _z_abi(callers_sp), newSP);
|
||||
} else {
|
||||
z_lgr(Z_SP, addr);
|
||||
z_stg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
}
|
||||
@ -2040,17 +2064,12 @@ void MacroAssembler::resize_frame_absolute(Register addr, Register fp, bool load
|
||||
// Resize_frame with SP(new) = SP(old) + offset.
|
||||
void MacroAssembler::resize_frame(RegisterOrConstant offset, Register fp, bool load_fp) {
|
||||
assert_different_registers(fp, Z_SP);
|
||||
if (load_fp) z_lg(fp, _z_abi(callers_sp), Z_SP);
|
||||
|
||||
if (Displacement::is_validDisp((int)_z_abi(callers_sp) + offset.constant_or_zero())) {
|
||||
// Minimize stalls by first using, then updating Z_SP.
|
||||
// Do that only if we have a small positive offset or if ExtImm are available.
|
||||
z_stg(fp, Address(Z_SP, offset, _z_abi(callers_sp)));
|
||||
add64(Z_SP, offset);
|
||||
} else {
|
||||
add64(Z_SP, offset);
|
||||
z_stg(fp, _z_abi(callers_sp), Z_SP);
|
||||
if (load_fp) {
|
||||
z_lg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
add64(Z_SP, offset);
|
||||
z_stg(fp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
void MacroAssembler::push_frame(Register bytes, Register old_sp, bool copy_sp, bool bytes_with_inverted_sign) {
|
||||
@ -2063,32 +2082,32 @@ void MacroAssembler::push_frame(Register bytes, Register old_sp, bool copy_sp, b
|
||||
#endif
|
||||
if (copy_sp) { z_lgr(old_sp, Z_SP); }
|
||||
if (bytes_with_inverted_sign) {
|
||||
z_stg(old_sp, 0, bytes, Z_SP);
|
||||
add2reg_with_index(Z_SP, 0, bytes, Z_SP);
|
||||
z_agr(Z_SP, bytes);
|
||||
} else {
|
||||
z_sgr(Z_SP, bytes); // Z_sgfr sufficient, but probably not faster.
|
||||
z_stg(old_sp, 0, Z_SP);
|
||||
}
|
||||
z_stg(old_sp, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
unsigned int MacroAssembler::push_frame(unsigned int bytes, Register scratch) {
|
||||
long offset = Assembler::align(bytes, frame::alignment_in_bytes);
|
||||
assert(offset > 0, "should push a frame with positive size, size = %ld.", offset);
|
||||
assert(Displacement::is_validDisp(-offset), "frame size out of range, size = %ld", offset);
|
||||
|
||||
if (Displacement::is_validDisp(-offset)) {
|
||||
// Minimize stalls by first using, then updating Z_SP.
|
||||
// Do that only if we have ExtImm available.
|
||||
z_stg(Z_SP, -offset, Z_SP);
|
||||
add2reg(Z_SP, -offset);
|
||||
} else {
|
||||
if (scratch != Z_R0 && scratch != Z_R1) {
|
||||
z_stg(Z_SP, -offset, Z_SP);
|
||||
add2reg(Z_SP, -offset);
|
||||
} else { // scratch == Z_R0 || scratch == Z_R1
|
||||
z_lgr(scratch, Z_SP);
|
||||
add2reg(Z_SP, -offset);
|
||||
z_stg(scratch, 0, Z_SP);
|
||||
}
|
||||
// We must not write outside the current stack bounds (given by Z_SP).
|
||||
// Thus, we have to first update Z_SP and then store the previous SP as stack linkage.
|
||||
// We rely on Z_R0 by default to be available as scratch.
|
||||
z_lgr(scratch, Z_SP);
|
||||
add2reg(Z_SP, -offset);
|
||||
z_stg(scratch, _z_abi(callers_sp), Z_SP);
|
||||
#ifdef ASSERT
|
||||
// Just make sure nobody uses the value in the default scratch register.
|
||||
// When another register is used, the caller might rely on it containing the frame pointer.
|
||||
if (scratch == Z_R0) {
|
||||
z_iihf(scratch, 0xbaadbabe);
|
||||
z_iilf(scratch, 0xdeadbeef);
|
||||
}
|
||||
#endif
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -2106,6 +2125,20 @@ void MacroAssembler::pop_frame() {
|
||||
Assembler::z_lg(Z_SP, _z_abi(callers_sp), Z_SP);
|
||||
}
|
||||
|
||||
// Pop current C frame and restore return PC register (Z_R14).
|
||||
void MacroAssembler::pop_frame_restore_retPC(int frame_size_in_bytes) {
|
||||
BLOCK_COMMENT("pop_frame_restore_retPC:");
|
||||
int retPC_offset = _z_abi16(return_pc) + frame_size_in_bytes;
|
||||
// If possible, pop frame by add instead of load (a penny saved is a penny got :-).
|
||||
if (Displacement::is_validDisp(retPC_offset)) {
|
||||
z_lg(Z_R14, retPC_offset, Z_SP);
|
||||
add2reg(Z_SP, frame_size_in_bytes);
|
||||
} else {
|
||||
add2reg(Z_SP, frame_size_in_bytes);
|
||||
restore_return_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::call_VM_leaf_base(address entry_point, bool allow_relocation) {
|
||||
if (allow_relocation) {
|
||||
call_c(entry_point);
|
||||
@ -3485,6 +3518,17 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp
|
||||
// Purpose: record the previous value if it is not null.
|
||||
// All non-tmps are preserved.
|
||||
//------------------------------------------------------
|
||||
// Note: Rpre_val needs special attention.
|
||||
// The flag pre_val_needed indicated that the caller of this emitter function
|
||||
// relies on Rpre_val containing the correct value, that is:
|
||||
// either the value it contained on entry to this code segment
|
||||
// or the value that was loaded into the register from (Robj+offset).
|
||||
//
|
||||
// Independent from this requirement, the contents of Rpre_val must survive
|
||||
// the push_frame() operation. push_frame() uses Z_R0_scratch by default
|
||||
// to temporarily remember the frame pointer.
|
||||
// If Rpre_val is assigned Z_R0_scratch by the caller, code must be emitted to
|
||||
// save it's value.
|
||||
void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
RegisterOrConstant offset,
|
||||
Register Rpre_val, // Ideally, this is a non-volatile register.
|
||||
@ -3498,6 +3542,16 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
const int buffer_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf());
|
||||
const int index_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index());
|
||||
assert_different_registers(Rtmp1, Rtmp2, Z_R0_scratch); // None of the Rtmp<i> must be Z_R0!!
|
||||
assert_different_registers(Robj, Z_R0_scratch); // Used for addressing. Furthermore, push_frame destroys Z_R0!!
|
||||
assert_different_registers(Rval, Z_R0_scratch); // push_frame destroys Z_R0!!
|
||||
|
||||
#ifdef ASSERT
|
||||
// make sure the register is not Z_R0. Used for addressing. Furthermore, would be destroyed by push_frame.
|
||||
if (offset.is_register() && offset.as_register()->encoding() == 0) {
|
||||
tty->print_cr("Roffset(g1_write_barrier_pre) = %%r%d", offset.as_register()->encoding());
|
||||
assert(false, "bad register for offset");
|
||||
}
|
||||
#endif
|
||||
|
||||
BLOCK_COMMENT("g1_write_barrier_pre {");
|
||||
|
||||
@ -3511,7 +3565,10 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
}
|
||||
z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
|
||||
|
||||
// Do we need to load the previous value into Rpre_val?
|
||||
assert(Rpre_val != noreg, "must have a real register");
|
||||
|
||||
|
||||
// If an object is given, we need to load the previous value into Rpre_val.
|
||||
if (Robj != noreg) {
|
||||
// Load the previous value...
|
||||
Register ixReg = offset.is_register() ? offset.register_or_noreg() : Z_R0;
|
||||
@ -3521,9 +3578,9 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
z_lg(Rpre_val, offset.constant_or_zero(), ixReg, Robj);
|
||||
}
|
||||
}
|
||||
assert(Rpre_val != noreg, "must have a real register");
|
||||
|
||||
// Is the previous value NULL?
|
||||
// If so, we don't need to record it and we're done.
|
||||
// Note: pre_val is loaded, decompressed and stored (directly or via runtime call).
|
||||
// Register contents is preserved across runtime call if caller requests to do so.
|
||||
z_ltgr(Rpre_val, Rpre_val);
|
||||
@ -3540,6 +3597,7 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
// only if index > 0. Otherwise, we need runtime to handle.
|
||||
// (The index field is typed as size_t.)
|
||||
Register Rbuffer = Rtmp1, Rindex = Rtmp2;
|
||||
assert_different_registers(Rbuffer, Rindex, Rpre_val);
|
||||
|
||||
z_lg(Rbuffer, buffer_offset, Z_thread);
|
||||
|
||||
@ -3558,16 +3616,8 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
|
||||
bind(callRuntime);
|
||||
|
||||
// Save Rpre_val (result) over runtime call.
|
||||
// Requires Rtmp1, Rtmp2, or Rpre_val to be non-volatile.
|
||||
Register Rpre_save = Rpre_val;
|
||||
if (pre_val_needed && Rpre_val->is_volatile()) {
|
||||
guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!");
|
||||
Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2;
|
||||
}
|
||||
lgr_if_needed(Rpre_save, Rpre_val);
|
||||
|
||||
// Preserve inputs by spilling them into the top frame.
|
||||
// Save some registers (inputs and result) over runtime call
|
||||
// by spilling them into the top frame.
|
||||
if (Robj != noreg && Robj->is_volatile()) {
|
||||
z_stg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
|
||||
}
|
||||
@ -3579,11 +3629,20 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
z_stg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
|
||||
}
|
||||
|
||||
// Save Rpre_val (result) over runtime call.
|
||||
Register Rpre_save = Rpre_val;
|
||||
if ((Rpre_val == Z_R0_scratch) || (pre_val_needed && Rpre_val->is_volatile())) {
|
||||
guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!");
|
||||
Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2;
|
||||
}
|
||||
lgr_if_needed(Rpre_save, Rpre_val);
|
||||
|
||||
// Push frame to protect top frame with return pc and spilled register values.
|
||||
save_return_pc();
|
||||
push_frame_abi160(0); // Will use Z_R0 as tmp on old CPUs.
|
||||
push_frame_abi160(0); // Will use Z_R0 as tmp.
|
||||
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_val, Z_thread);
|
||||
// Rpre_val may be destroyed by push_frame().
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_save, Z_thread);
|
||||
|
||||
pop_frame();
|
||||
restore_return_pc();
|
||||
@ -3599,9 +3658,9 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj,
|
||||
if (Rval != noreg && Rval->is_volatile()) {
|
||||
z_lg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
|
||||
}
|
||||
|
||||
// Restore Rpre_val (result) after runtime call.
|
||||
lgr_if_needed(Rpre_val, Rpre_save);
|
||||
if (pre_val_needed && Rpre_val->is_volatile()) {
|
||||
lgr_if_needed(Rpre_val, Rpre_save);
|
||||
}
|
||||
|
||||
bind(filtered);
|
||||
BLOCK_COMMENT("} g1_write_barrier_pre");
|
||||
@ -3654,7 +3713,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr,
|
||||
// calculate address of card
|
||||
load_const_optimized(Rbase, (address)bs->byte_map_base); // Card table base.
|
||||
z_srlg(Rcard_addr, Rstore_addr, CardTableModRefBS::card_shift); // Index into card table.
|
||||
add2reg_with_index(Rcard_addr, 0, Rcard_addr, Rbase); // Explicit calculation needed for cli.
|
||||
z_algr(Rcard_addr, Rbase); // Explicit calculation needed for cli.
|
||||
Rbase = noreg; // end of lifetime
|
||||
|
||||
// Filter young.
|
||||
@ -3698,6 +3757,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr,
|
||||
|
||||
// TODO: do we need a frame? Introduced to be on the safe side.
|
||||
bool needs_frame = true;
|
||||
lgr_if_needed(Rcard_addr, Rcard_addr_x); // copy back asap. push_frame will destroy Z_R0_scratch!
|
||||
|
||||
// VM call need frame to access(write) O register.
|
||||
if (needs_frame) {
|
||||
@ -3706,7 +3766,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr,
|
||||
}
|
||||
|
||||
// Save the live input values.
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr_x, Z_thread);
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, Z_thread);
|
||||
|
||||
if (needs_frame) {
|
||||
pop_frame();
|
||||
@ -4062,7 +4122,12 @@ void MacroAssembler::store_klass(Register klass, Register dst_oop, Register ck)
|
||||
void MacroAssembler::store_klass_gap(Register s, Register d) {
|
||||
if (UseCompressedClassPointers) {
|
||||
assert(s != d, "not enough registers");
|
||||
z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes()));
|
||||
// Support s = noreg.
|
||||
if (s != noreg) {
|
||||
z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes()));
|
||||
} else {
|
||||
z_mvhi(Address(d, oopDesc::klass_gap_offset_in_bytes()), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6621,11 +6686,12 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) {
|
||||
|
||||
BLOCK_COMMENT("verify_oop {");
|
||||
Register tmp = Z_R0;
|
||||
unsigned int nbytes_save = 6 *8;
|
||||
unsigned int nbytes_save = 5*BytesPerWord;
|
||||
address entry = StubRoutines::verify_oop_subroutine_entry_address();
|
||||
|
||||
save_return_pc();
|
||||
push_frame_abi160(nbytes_save);
|
||||
z_stmg(Z_R0, Z_R5, 160, Z_SP);
|
||||
z_stmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP);
|
||||
|
||||
z_lgr(Z_ARG2, oop);
|
||||
load_const(Z_ARG1, (address) msg);
|
||||
@ -6633,10 +6699,10 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) {
|
||||
z_lg(Z_R1, 0, Z_R1);
|
||||
call_c(Z_R1);
|
||||
|
||||
z_lmg(Z_R0, Z_R5, 160, Z_SP);
|
||||
z_lmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP);
|
||||
pop_frame();
|
||||
|
||||
restore_return_pc();
|
||||
|
||||
BLOCK_COMMENT("} verify_oop ");
|
||||
}
|
||||
|
||||
@ -6658,8 +6724,8 @@ void MacroAssembler::stop(int type, const char* msg, int id) {
|
||||
// Setup arguments.
|
||||
load_const(Z_ARG1, (void*) stop_types[type%stop_end]);
|
||||
load_const(Z_ARG2, (void*) msg);
|
||||
get_PC(Z_R14); // Following code pushes a frame without entering a new function. Use current pc as return address.
|
||||
save_return_pc(); // Saves return pc Z_R14.
|
||||
get_PC(Z_R14); // Following code pushes a frame without entering a new function. Use current pc as return address.
|
||||
save_return_pc(); // Saves return pc Z_R14.
|
||||
push_frame_abi160(0);
|
||||
call_VM_leaf(CAST_FROM_FN_PTR(address, stop_on_request), Z_ARG1, Z_ARG2);
|
||||
// The plain disassembler does not recognize illtrap. It instead displays
|
||||
|
||||
@ -440,9 +440,21 @@ class MacroAssembler: public Assembler {
|
||||
// Get current PC + offset. Offset given in bytes, must be even!
|
||||
address get_PC(Register result, int64_t offset);
|
||||
|
||||
// Accessing, and in particular modifying, a stack location is only safe if
|
||||
// the stack pointer (Z_SP) is set such that the accessed stack location is
|
||||
// in the reserved range.
|
||||
//
|
||||
// From a performance point of view, it is desirable not to change the SP
|
||||
// first and then immediately use it to access the freshly reserved space.
|
||||
// That opens a small gap, though. If, just after storing some value (the
|
||||
// frame pointer) into the to-be-reserved space, an interrupt is caught,
|
||||
// the handler might use the space beyond Z_SP for it's own purpose.
|
||||
// If that happens, the stored value might get altered.
|
||||
|
||||
// Resize current frame either relatively wrt to current SP or absolute.
|
||||
void resize_frame_sub(Register offset, Register fp, bool load_fp=true);
|
||||
void resize_frame_absolute(Register addr, Register fp, bool load_fp=true);
|
||||
void resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp);
|
||||
void resize_frame_absolute(Register addr, Register fp, bool load_fp);
|
||||
void resize_frame(RegisterOrConstant offset, Register fp, bool load_fp=true);
|
||||
|
||||
// Push a frame of size bytes, if copy_sp is false, old_sp must already
|
||||
@ -461,6 +473,8 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
// Pop current C frame.
|
||||
void pop_frame();
|
||||
// Pop current C frame and restore return PC register (Z_R14).
|
||||
void pop_frame_restore_retPC(int frame_size_in_bytes);
|
||||
|
||||
//
|
||||
// Calls
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2016 SAP SE. All rights reserved.
|
||||
// Copyright (c) 2017, SAP SE. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -910,16 +910,8 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
bool need_polling = do_polling() && C->is_method_compilation();
|
||||
|
||||
// Pop frame, restore return_pc, and all stuff needed by interpreter.
|
||||
// Pop frame by add instead of load (a penny saved is a penny got :-).
|
||||
int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
|
||||
int retPC_offset = frame_size_in_bytes + _z_abi16(return_pc);
|
||||
if (Displacement::is_validDisp(retPC_offset)) {
|
||||
__ z_lg(Z_R14, retPC_offset, Z_SP);
|
||||
__ add2reg(Z_SP, frame_size_in_bytes);
|
||||
} else {
|
||||
__ add2reg(Z_SP, frame_size_in_bytes);
|
||||
__ restore_return_pc();
|
||||
}
|
||||
__ pop_frame_restore_retPC(frame_size_in_bytes);
|
||||
|
||||
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
|
||||
__ reserved_stack_check(Z_R14);
|
||||
|
||||
@ -312,7 +312,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg
|
||||
__ save_return_pc(return_pc);
|
||||
|
||||
// Push a new frame (includes stack linkage).
|
||||
__ push_frame(frame_size_in_bytes);
|
||||
// use return_pc as scratch for push_frame. Z_R0_scratch (the default) and Z_R1_scratch are
|
||||
// illegally used to pass parameters (SAPJVM extension) by RangeCheckStub::emit_code().
|
||||
__ push_frame(frame_size_in_bytes, return_pc);
|
||||
// We have to restore return_pc right away.
|
||||
// Nobody else will. Furthermore, return_pc isn't necessarily the default (Z_R14).
|
||||
// Nobody else knows which register we saved.
|
||||
__ z_lg(return_pc, _z_abi16(return_pc) + frame_size_in_bytes, Z_SP);
|
||||
|
||||
// Register save area in new frame starts above z_abi_160 area.
|
||||
int offset = register_save_offset;
|
||||
@ -542,7 +548,6 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
size_t SharedRuntime::trampoline_size() {
|
||||
return MacroAssembler::load_const_size() + 2;
|
||||
}
|
||||
@ -552,7 +557,6 @@ void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destinatio
|
||||
__ load_const(Z_R1_scratch, destination);
|
||||
__ z_br(Z_R1_scratch);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
void SharedRuntime::save_native_result(MacroAssembler * masm,
|
||||
|
||||
@ -291,7 +291,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// Restore frame pointer.
|
||||
__ z_lg(r_entryframe_fp, _z_abi(callers_sp), Z_SP);
|
||||
// Pop frame. Done here to minimize stalls.
|
||||
__ z_lg(Z_SP, _z_abi(callers_sp), Z_SP);
|
||||
__ pop_frame();
|
||||
|
||||
// Reload some volatile registers which we've spilled before the call
|
||||
// to frame manager / native entry.
|
||||
@ -563,6 +563,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address generate_throw_exception(const char* name, address runtime_entry,
|
||||
bool restore_saved_exception_pc,
|
||||
Register arg1 = noreg, Register arg2 = noreg) {
|
||||
assert_different_registers(arg1, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
assert_different_registers(arg2, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
|
||||
int insts_size = 256;
|
||||
int locs_size = 0;
|
||||
CodeBuffer code(name, insts_size, locs_size);
|
||||
@ -693,11 +696,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||
BarrierSet* const bs = Universe::heap()->barrier_set();
|
||||
switch (bs->kind()) {
|
||||
case BarrierSet::G1SATBCTLogging:
|
||||
// With G1, don't generate the call if we statically know that the target in uninitialized.
|
||||
// With G1, don't generate the call if we statically know that the target is uninitialized.
|
||||
if (!dest_uninitialized) {
|
||||
// Is marking active?
|
||||
Label filtered;
|
||||
Register Rtmp1 = Z_R0;
|
||||
assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
Register Rtmp1 = Z_R0_scratch;
|
||||
const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
|
||||
SATBMarkQueue::byte_offset_of_active());
|
||||
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
|
||||
@ -708,11 +713,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
__ z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
|
||||
|
||||
// __ push_frame_abi160(0);
|
||||
// __ push_frame_abi160(0); // implicitly done in save_live_registers()
|
||||
(void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), addr, count);
|
||||
(void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers);
|
||||
// __ pop_frame();
|
||||
// __ pop_frame(); // implicitly done in restore_live_registers()
|
||||
|
||||
__ bind(filtered);
|
||||
}
|
||||
@ -739,16 +744,18 @@ class StubGenerator: public StubCodeGenerator {
|
||||
case BarrierSet::G1SATBCTLogging:
|
||||
{
|
||||
if (branchToEnd) {
|
||||
// __ push_frame_abi160(0);
|
||||
assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
|
||||
// __ push_frame_abi160(0); // implicitly done in save_live_registers()
|
||||
(void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count);
|
||||
(void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers);
|
||||
// __ pop_frame();
|
||||
// __ pop_frame(); // implicitly done in restore_live_registers()
|
||||
} else {
|
||||
// Tail call: call c and return to stub caller.
|
||||
address entry_point = CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post);
|
||||
if (Z_ARG1 != addr) __ z_lgr(Z_ARG1, addr);
|
||||
if (Z_ARG2 != count) __ z_lgr(Z_ARG2, count);
|
||||
__ lgr_if_needed(Z_ARG1, addr);
|
||||
__ lgr_if_needed(Z_ARG2, count);
|
||||
__ load_const(Z_R1, entry_point);
|
||||
__ z_br(Z_R1); // Branch without linking, callee will return to stub caller.
|
||||
}
|
||||
@ -1676,8 +1683,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// src must designate an even/odd register pair, holding the address/length of the original message
|
||||
|
||||
// Helper function which generates code to
|
||||
// - load the function code in register fCode (== Z_R0)
|
||||
// - load the data block length (depends on cipher function) in register srclen if requested.
|
||||
// - load the function code in register fCode (== Z_R0).
|
||||
// - load the data block length (depends on cipher function) into register srclen if requested.
|
||||
// - is_decipher switches between cipher/decipher function codes
|
||||
// - set_len requests (if true) loading the data block length in register srclen
|
||||
void generate_load_AES_fCode(Register keylen, Register fCode, Register srclen, bool is_decipher) {
|
||||
@ -1688,12 +1695,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||
bool identical_dataBlk_len = (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES192_dataBlk)
|
||||
&& (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES256_dataBlk);
|
||||
// Expanded key length is 44/52/60 * 4 bytes for AES-128/AES-192/AES-256.
|
||||
__ z_cghi(keylen, 52);
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
|
||||
__ z_cghi(keylen, 52); // Check only once at the beginning. keylen and fCode may share the same register.
|
||||
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
|
||||
if (!identical_dataBlk_len) {
|
||||
__ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk);
|
||||
__ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk);
|
||||
}
|
||||
__ z_brh(fCode_set); // keyLen > 52: AES256
|
||||
__ z_brl(fCode_set); // keyLen < 52: AES128
|
||||
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES192 + mode);
|
||||
if (!identical_dataBlk_len) {
|
||||
@ -1701,11 +1709,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
__ z_bre(fCode_set); // keyLen == 52: AES192
|
||||
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
|
||||
if (!identical_dataBlk_len) {
|
||||
__ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk);
|
||||
__ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk);
|
||||
}
|
||||
// __ z_brl(fCode_set); // keyLen < 52: AES128 // fallthru
|
||||
// __ z_brh(fCode_set); // keyLen < 52: AES128 // fallthru
|
||||
|
||||
__ bind(fCode_set);
|
||||
if (identical_dataBlk_len) {
|
||||
__ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk);
|
||||
@ -1715,6 +1724,54 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Push a parameter block for the cipher/decipher instruction on the stack.
|
||||
// Layout of the additional stack space allocated for AES_cipherBlockChaining:
|
||||
//
|
||||
// | |
|
||||
// +--------+ <-- SP before expansion
|
||||
// | |
|
||||
// : : alignment loss, 0..(AES_parmBlk_align-8) bytes
|
||||
// | |
|
||||
// +--------+
|
||||
// | |
|
||||
// : : space for parameter block, size VM_Version::Cipher::_AES*_parmBlk_C
|
||||
// | |
|
||||
// +--------+ <-- parmBlk, octoword-aligned, start of parameter block
|
||||
// | |
|
||||
// : : additional stack space for spills etc., size AES_parmBlk_addspace, DW @ Z_SP not usable!!!
|
||||
// | |
|
||||
// +--------+ <-- Z_SP after expansion
|
||||
|
||||
void generate_push_Block(int dataBlk_len, int parmBlk_len, int crypto_fCode,
|
||||
Register parmBlk, Register keylen, Register fCode, Register cv, Register key) {
|
||||
const int AES_parmBlk_align = 32; // octoword alignment.
|
||||
const int AES_parmBlk_addspace = 24; // Must be sufficiently large to hold all spilled registers
|
||||
// (currently 2) PLUS 1 DW for the frame pointer.
|
||||
|
||||
const int cv_len = dataBlk_len;
|
||||
const int key_len = parmBlk_len - cv_len;
|
||||
// This len must be known at JIT compile time. Only then are we able to recalc the SP before resize.
|
||||
// We buy this knowledge by wasting some (up to AES_parmBlk_align) bytes of stack space.
|
||||
const int resize_len = cv_len + key_len + AES_parmBlk_align + AES_parmBlk_addspace;
|
||||
|
||||
// Use parmBlk as temp reg here to hold the frame pointer.
|
||||
__ resize_frame(-resize_len, parmBlk, true);
|
||||
|
||||
// calculate parmBlk address from updated (resized) SP.
|
||||
__ add2reg(parmBlk, resize_len - (cv_len + key_len), Z_SP);
|
||||
__ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block.
|
||||
|
||||
// There is room for stuff in the range [parmBlk-AES_parmBlk_addspace+8, parmBlk).
|
||||
__ z_stg(keylen, -8, parmBlk); // Spill keylen for later use.
|
||||
|
||||
// calculate (SP before resize) from updated SP.
|
||||
__ add2reg(keylen, resize_len, Z_SP); // keylen holds prev SP for now.
|
||||
__ z_stg(keylen, -16, parmBlk); // Spill prev SP for easy revert.
|
||||
|
||||
__ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv.
|
||||
__ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key.
|
||||
__ z_lghi(fCode, crypto_fCode);
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// Before returning, the stub has to copy the chaining value from
|
||||
// the parmBlk, where it was updated by the crypto instruction, back
|
||||
@ -1723,17 +1780,14 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// the key length across the KMC instruction. We do so by spilling it to the stack,
|
||||
// just preceding the parmBlk (at (parmBlk - 8)).
|
||||
void generate_push_parmBlk(Register keylen, Register fCode, Register parmBlk, Register key, Register cv, bool is_decipher) {
|
||||
const int AES_parmBlk_align = 32;
|
||||
const int AES_parmBlk_addspace = AES_parmBlk_align; // Must be multiple of AES_parmblk_align.
|
||||
int cv_len, key_len;
|
||||
int mode = is_decipher ? VM_Version::CipherMode::decipher : VM_Version::CipherMode::cipher;
|
||||
Label parmBlk_128, parmBlk_192, parmBlk_256, parmBlk_set;
|
||||
|
||||
BLOCK_COMMENT("push parmBlk {");
|
||||
if (VM_Version::has_Crypto_AES() ) { __ z_cghi(keylen, 52); }
|
||||
if (VM_Version::has_Crypto_AES256()) { __ z_brh(parmBlk_256); } // keyLen > 52: AES256
|
||||
if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); } // keyLen == 52: AES192
|
||||
if (VM_Version::has_Crypto_AES128()) { __ z_brl(parmBlk_128); } // keyLen < 52: AES128
|
||||
if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); } // keyLen == 52: AES192
|
||||
if (VM_Version::has_Crypto_AES256()) { __ z_brh(parmBlk_256); } // keyLen > 52: AES256
|
||||
|
||||
// Security net: requested AES function not available on this CPU.
|
||||
// NOTE:
|
||||
@ -1742,71 +1796,35 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// at all, we have at least AES-128.
|
||||
__ stop_static("AES key strength not supported by CPU. Use -XX:-UseAES as remedy.", 0);
|
||||
|
||||
if (VM_Version::has_Crypto_AES128()) {
|
||||
__ bind(parmBlk_128);
|
||||
cv_len = VM_Version::Cipher::_AES128_dataBlk;
|
||||
key_len = VM_Version::Cipher::_AES128_parmBlk_C - cv_len;
|
||||
__ z_lay(parmBlk, -(VM_Version::Cipher::_AES128_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
|
||||
__ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // align parameter block
|
||||
|
||||
// Resize the frame to accommodate for the aligned parameter block and other stuff.
|
||||
// There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
|
||||
__ z_stg(keylen, -8, parmBlk); // Spill keylen for later use.
|
||||
__ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert.
|
||||
__ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc..
|
||||
__ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
|
||||
__ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address.
|
||||
|
||||
__ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv.
|
||||
__ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key.
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
|
||||
if (VM_Version::has_Crypto_AES192() || VM_Version::has_Crypto_AES256()) {
|
||||
if (VM_Version::has_Crypto_AES256()) {
|
||||
__ bind(parmBlk_256);
|
||||
generate_push_Block(VM_Version::Cipher::_AES256_dataBlk,
|
||||
VM_Version::Cipher::_AES256_parmBlk_C,
|
||||
VM_Version::Cipher::_AES256 + mode,
|
||||
parmBlk, keylen, fCode, cv, key);
|
||||
if (VM_Version::has_Crypto_AES128() || VM_Version::has_Crypto_AES192()) {
|
||||
__ z_bru(parmBlk_set); // Fallthru otherwise.
|
||||
}
|
||||
}
|
||||
|
||||
if (VM_Version::has_Crypto_AES192()) {
|
||||
__ bind(parmBlk_192);
|
||||
cv_len = VM_Version::Cipher::_AES192_dataBlk;
|
||||
key_len = VM_Version::Cipher::_AES192_parmBlk_C - cv_len;
|
||||
__ z_lay(parmBlk, -(VM_Version::Cipher::_AES192_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
|
||||
__ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block.
|
||||
|
||||
// Resize the frame to accommodate for the aligned parameter block and other stuff.
|
||||
// There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
|
||||
__ z_stg(keylen, -8, parmBlk); // Spill keylen for later use.
|
||||
__ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert.
|
||||
__ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc..
|
||||
__ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
|
||||
__ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address.
|
||||
|
||||
__ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv.
|
||||
__ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key.
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES192 + mode);
|
||||
if (VM_Version::has_Crypto_AES256()) {
|
||||
generate_push_Block(VM_Version::Cipher::_AES192_dataBlk,
|
||||
VM_Version::Cipher::_AES192_parmBlk_C,
|
||||
VM_Version::Cipher::_AES192 + mode,
|
||||
parmBlk, keylen, fCode, cv, key);
|
||||
if (VM_Version::has_Crypto_AES128()) {
|
||||
__ z_bru(parmBlk_set); // Fallthru otherwise.
|
||||
}
|
||||
}
|
||||
|
||||
if (VM_Version::has_Crypto_AES256()) {
|
||||
__ bind(parmBlk_256);
|
||||
cv_len = VM_Version::Cipher::_AES256_dataBlk;
|
||||
key_len = VM_Version::Cipher::_AES256_parmBlk_C - cv_len;
|
||||
__ z_lay(parmBlk, -(VM_Version::Cipher::_AES256_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
|
||||
__ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block.
|
||||
|
||||
// Resize the frame to accommodate for the aligned parameter block and other stuff.
|
||||
// There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
|
||||
__ z_stg(keylen, -8, parmBlk); // Spill keylen for later use.
|
||||
__ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert.
|
||||
__ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc..
|
||||
__ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
|
||||
__ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address.
|
||||
|
||||
__ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv.
|
||||
__ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key.
|
||||
__ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
|
||||
// __ z_bru(parmBlk_set); // fallthru
|
||||
if (VM_Version::has_Crypto_AES128()) {
|
||||
__ bind(parmBlk_128);
|
||||
generate_push_Block(VM_Version::Cipher::_AES128_dataBlk,
|
||||
VM_Version::Cipher::_AES128_parmBlk_C,
|
||||
VM_Version::Cipher::_AES128 + mode,
|
||||
parmBlk, keylen, fCode, cv, key);
|
||||
// Fallthru
|
||||
}
|
||||
|
||||
__ bind(parmBlk_set);
|
||||
@ -1862,41 +1880,49 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
__ bind(parmBlk_set);
|
||||
}
|
||||
__ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute.
|
||||
__ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute. Z_SP saved by push_parmBlk.
|
||||
BLOCK_COMMENT("} pop parmBlk");
|
||||
}
|
||||
|
||||
// Compute AES encrypt function.
|
||||
address generate_AES_encryptBlock(const char* name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
|
||||
// Compute AES encrypt/decrypt function.
|
||||
void generate_AES_cipherBlock(bool is_decipher) {
|
||||
// Incoming arguments.
|
||||
Register from = Z_ARG1; // source byte array
|
||||
Register to = Z_ARG2; // destination byte array
|
||||
Register key = Z_ARG3; // expanded key array
|
||||
|
||||
const Register keylen = Z_R0; // Temporarily (until fCode is set) holds the expanded key array length.
|
||||
|
||||
// Register definitions as required by KM instruction.
|
||||
const Register fCode = Z_R0; // crypto function code
|
||||
const Register parmBlk = Z_R1; // parameter block address (points to crypto key)
|
||||
const Register src = Z_ARG1; // is Z_R2
|
||||
const Register srclen = Z_ARG2; // Overwrites destination address.
|
||||
const Register dst = Z_ARG3; // Overwrites expanded key address.
|
||||
const Register src = Z_ARG1; // Must be even reg (KM requirement).
|
||||
const Register srclen = Z_ARG2; // Must be odd reg and pair with src. Overwrites destination address.
|
||||
const Register dst = Z_ARG3; // Must be even reg (KM requirement). Overwrites expanded key address.
|
||||
|
||||
// Read key len of expanded key (in 4-byte words).
|
||||
__ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Copy arguments to registers as required by crypto instruction.
|
||||
__ z_lgr(parmBlk, key); // crypto key (in T_INT array).
|
||||
// __ z_lgr(src, from); // Copy not needed, src/from are identical.
|
||||
__ z_lgr(dst, to); // Copy destination address to even register.
|
||||
__ lgr_if_needed(src, from); // Copy src address. Will not emit, src/from are identical.
|
||||
__ z_lgr(dst, to); // Copy dst address, even register required.
|
||||
|
||||
// Construct function code in Z_R0, data block length in Z_ARG2.
|
||||
generate_load_AES_fCode(keylen, fCode, srclen, false);
|
||||
// Construct function code into fCode(Z_R0), data block length into srclen(Z_ARG2).
|
||||
generate_load_AES_fCode(keylen, fCode, srclen, is_decipher);
|
||||
|
||||
__ km(dst, src); // Cipher the message.
|
||||
__ km(dst, src); // Cipher the message.
|
||||
|
||||
__ z_br(Z_R14);
|
||||
}
|
||||
|
||||
// Compute AES encrypt function.
|
||||
address generate_AES_encryptBlock(const char* name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
|
||||
generate_AES_cipherBlock(false);
|
||||
|
||||
return __ addr_at(start_off);
|
||||
}
|
||||
@ -1905,33 +1931,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address generate_AES_decryptBlock(const char* name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
|
||||
Register from = Z_ARG1; // source byte array
|
||||
Register to = Z_ARG2; // destination byte array
|
||||
Register key = Z_ARG3; // expanded key array, not preset at entry!!!
|
||||
|
||||
const Register keylen = Z_R0; // Temporarily (until fCode is set) holds the expanded key array length.
|
||||
const Register fCode = Z_R0; // crypto function code
|
||||
const Register parmBlk = Z_R1; // parameter block address (points to crypto key)
|
||||
const Register src = Z_ARG1; // is Z_R2
|
||||
const Register srclen = Z_ARG2; // Overwrites destination address.
|
||||
const Register dst = Z_ARG3; // Overwrites key address.
|
||||
|
||||
// Read key len of expanded key (in 4-byte words).
|
||||
__ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Copy arguments to registers as required by crypto instruction.
|
||||
__ z_lgr(parmBlk, key); // Copy crypto key address.
|
||||
// __ z_lgr(src, from); // Copy not needed, src/from are identical.
|
||||
__ z_lgr(dst, to); // Copy destination address to even register.
|
||||
|
||||
// Construct function code in Z_R0, data block length in Z_ARG2.
|
||||
generate_load_AES_fCode(keylen, fCode, srclen, true);
|
||||
|
||||
__ km(dst, src); // Cipher the message.
|
||||
|
||||
__ z_br(Z_R14);
|
||||
generate_AES_cipherBlock(true);
|
||||
|
||||
return __ addr_at(start_off);
|
||||
}
|
||||
@ -1949,10 +1951,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// We align the parameter block to the next available octoword.
|
||||
//
|
||||
// Compute chained AES encrypt function.
|
||||
address generate_cipherBlockChaining_AES_encrypt(const char* name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
void generate_AES_cipherBlockChaining(bool is_decipher) {
|
||||
|
||||
Register from = Z_ARG1; // source byte array (clear text)
|
||||
Register to = Z_ARG2; // destination byte array (ciphered)
|
||||
@ -1972,20 +1971,29 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block.
|
||||
// Construct function code in Z_R0.
|
||||
generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, false);
|
||||
// Construct function code in fCode (Z_R0).
|
||||
generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, is_decipher);
|
||||
|
||||
// Prepare other registers for instruction.
|
||||
// __ z_lgr(src, from); // Not needed, registers are the same.
|
||||
__ lgr_if_needed(src, from); // Copy src address. Will not emit, src/from are identical.
|
||||
__ z_lgr(dst, to);
|
||||
__ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
__ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
|
||||
__ kmc(dst, src); // Cipher the message.
|
||||
__ kmc(dst, src); // Cipher the message.
|
||||
|
||||
generate_pop_parmBlk(keylen, parmBlk, key, cv);
|
||||
|
||||
__ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
__ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
__ z_br(Z_R14);
|
||||
}
|
||||
|
||||
// Compute chained AES encrypt function.
|
||||
address generate_cipherBlockChaining_AES_encrypt(const char* name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
|
||||
generate_AES_cipherBlockChaining(false);
|
||||
|
||||
return __ addr_at(start_off);
|
||||
}
|
||||
@ -1996,38 +2004,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
|
||||
|
||||
Register from = Z_ARG1; // source byte array (ciphered)
|
||||
Register to = Z_ARG2; // destination byte array (clear text)
|
||||
Register key = Z_ARG3; // expanded key array, not preset at entry!!!
|
||||
Register cv = Z_ARG4; // chaining value
|
||||
const Register msglen = Z_ARG5; // Total length of the msg to be encrypted. Value must be returned
|
||||
// in Z_RET upon completion of this stub.
|
||||
|
||||
const Register keylen = Z_R0; // Expanded key length, as read from key array. Temp only.
|
||||
const Register fCode = Z_R0; // crypto function code
|
||||
const Register parmBlk = Z_R1; // parameter block address (points to crypto key)
|
||||
const Register src = Z_ARG1; // is Z_R2
|
||||
const Register srclen = Z_ARG2; // Overwrites destination address.
|
||||
const Register dst = Z_ARG3; // Overwrites key address.
|
||||
|
||||
// Read key len of expanded key (in 4-byte words).
|
||||
__ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block.
|
||||
// Construct function code in Z_R0.
|
||||
generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, true);
|
||||
|
||||
// Prepare other registers for instruction.
|
||||
// __ z_lgr(src, from); // Not needed, registers are the same.
|
||||
__ z_lgr(dst, to);
|
||||
__ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
|
||||
__ kmc(dst, src); // Decipher the message.
|
||||
|
||||
generate_pop_parmBlk(keylen, parmBlk, key, cv);
|
||||
|
||||
__ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
__ z_br(Z_R14);
|
||||
generate_AES_cipherBlockChaining(true);
|
||||
|
||||
return __ addr_at(start_off);
|
||||
}
|
||||
|
||||
@ -121,9 +121,8 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() {
|
||||
|
||||
// We use target_sp for storing arguments in the C frame.
|
||||
__ save_return_pc();
|
||||
|
||||
__ z_stmg(Z_R10,Z_R13,-32,Z_SP);
|
||||
__ push_frame_abi160(32);
|
||||
__ push_frame_abi160(4*BytesPerWord); // Reserve space to save the tmp_[1..4] registers.
|
||||
__ z_stmg(Z_R10, Z_R13, frame::z_abi_160_size, Z_SP); // Save registers only after frame is pushed.
|
||||
|
||||
__ z_lgr(arg_java, Z_ARG1);
|
||||
|
||||
@ -341,9 +340,9 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() {
|
||||
|
||||
// Method exit, all arguments proocessed.
|
||||
__ bind(loop_end);
|
||||
__ z_lmg(Z_R10, Z_R13, frame::z_abi_160_size, Z_SP); // restore registers before frame is popped.
|
||||
__ pop_frame();
|
||||
__ restore_return_pc();
|
||||
__ z_lmg(Z_R10,Z_R13,-32,Z_SP);
|
||||
__ z_br(Z_R14);
|
||||
|
||||
// Copy int arguments.
|
||||
@ -1232,13 +1231,9 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
|
||||
// Advance local_addr to point behind locals (creates positive incr. in loop).
|
||||
__ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
|
||||
__ z_llgh(Z_R0_scratch,
|
||||
Address(Z_R1_scratch, ConstMethod::size_of_locals_offset()));
|
||||
if (Z_R0_scratch == Z_R0) {
|
||||
__ z_aghi(Z_R0_scratch, -1);
|
||||
} else {
|
||||
__ add2reg(Z_R0_scratch, -1);
|
||||
}
|
||||
__ z_llgh(Z_R0_scratch, Address(Z_R1_scratch, ConstMethod::size_of_locals_offset()));
|
||||
__ add2reg(Z_R0_scratch, -1);
|
||||
|
||||
__ z_lgr(local_addr/*locals*/, Z_locals);
|
||||
__ z_sllg(Z_R0_scratch, Z_R0_scratch, LogBytesPerWord);
|
||||
__ z_sllg(local_count, local_count, LogBytesPerWord); // Local_count are non param locals.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -153,6 +153,10 @@ void VM_Version::initialize() {
|
||||
warning("AES intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
if (UseAESIntrinsics && !UseAES) {
|
||||
warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
|
||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
|
||||
// TODO: implement AES/CTR intrinsics
|
||||
if (UseAESCTRIntrinsics) {
|
||||
|
||||
@ -176,7 +176,7 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to, intptr_t *RegArgSig) : NativeSignatureIterator(method) {
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to, intptr_t *RegArgSig) : NativeSignatureIterator(method) {
|
||||
_from = from;
|
||||
_to = to;
|
||||
_RegArgSignature = RegArgSig;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,7 +52,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
|
||||
public:
|
||||
// Creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
}
|
||||
|
||||
|
||||
@ -1633,7 +1633,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType
|
||||
}
|
||||
|
||||
static void verify_oop_args(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
Register temp_reg = G5_method; // not part of any compiled calling seq
|
||||
@ -1657,7 +1657,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -55,7 +55,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator {
|
||||
|
||||
public:
|
||||
// Creation
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
|
||||
_masm = new MacroAssembler(buffer);
|
||||
#ifdef AMD64
|
||||
#ifdef _WIN64
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -124,7 +124,7 @@ class SlowSignatureHandler: public NativeSignatureIterator {
|
||||
}
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to) :
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) :
|
||||
NativeSignatureIterator(method) {
|
||||
_from = from;
|
||||
_to = to + (is_static() ? 2 : 1);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -369,7 +369,7 @@ class SlowSignatureHandler
|
||||
}
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to)
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to)
|
||||
: NativeSignatureIterator(method)
|
||||
{
|
||||
_from = from;
|
||||
@ -461,7 +461,7 @@ class SlowSignatureHandler
|
||||
}
|
||||
|
||||
public:
|
||||
SlowSignatureHandler(methodHandle method, address from, intptr_t* to)
|
||||
SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to)
|
||||
: NativeSignatureIterator(method)
|
||||
{
|
||||
_from = from;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,7 +39,7 @@
|
||||
// Since hashCode is usually polymorphic at call sites we can't do this
|
||||
// optimization at the call site without a lot of work.
|
||||
void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
Register obj_reg,
|
||||
Register result) {
|
||||
Label slowCase;
|
||||
|
||||
@ -1407,7 +1407,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType
|
||||
}
|
||||
|
||||
static void verify_oop_args(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
Register temp_reg = rbx; // not part of any compiled calling seq
|
||||
@ -1429,7 +1429,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -1740,7 +1740,7 @@ static void verify_oop_args(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
static void gen_special_dispatch(MacroAssembler* masm,
|
||||
methodHandle method,
|
||||
const methodHandle& method,
|
||||
const BasicType* sig_bt,
|
||||
const VMRegPair* regs) {
|
||||
verify_oop_args(masm, method, sig_bt, regs);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2007, 2008 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -67,7 +67,7 @@ class SignatureHandlerGeneratorBase : public NativeSignatureIterator {
|
||||
ffi_cif* _cif;
|
||||
|
||||
protected:
|
||||
SignatureHandlerGeneratorBase(methodHandle method, ffi_cif *cif)
|
||||
SignatureHandlerGeneratorBase(const methodHandle& method, ffi_cif *cif)
|
||||
: NativeSignatureIterator(method), _cif(cif) {
|
||||
_cif->nargs = 0;
|
||||
}
|
||||
@ -96,7 +96,7 @@ class SignatureHandlerGenerator : public SignatureHandlerGeneratorBase {
|
||||
CodeBuffer* _cb;
|
||||
|
||||
public:
|
||||
SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer)
|
||||
SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer)
|
||||
: SignatureHandlerGeneratorBase(method, (ffi_cif *) buffer->insts_end()),
|
||||
_cb(buffer) {
|
||||
_cb->set_insts_end((address) (cif() + 1));
|
||||
@ -115,7 +115,7 @@ class SlowSignatureHandlerGenerator : public SignatureHandlerGeneratorBase {
|
||||
intptr_t *_dst;
|
||||
|
||||
public:
|
||||
SlowSignatureHandlerGenerator(methodHandle method, intptr_t* buf)
|
||||
SlowSignatureHandlerGenerator(const methodHandle& method, intptr_t* buf)
|
||||
: SignatureHandlerGeneratorBase(method, (ffi_cif *) buf) {
|
||||
_dst = (intptr_t *) (cif() + 1);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
* Copyright 2009, 2010, 2011 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -147,8 +147,8 @@ int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UN
|
||||
Klass* clazz = recv->klass();
|
||||
Klass* klass_part = InstanceKlass::cast(clazz);
|
||||
ResourceMark rm(THREAD);
|
||||
klassVtable* vtable = klass_part->vtable();
|
||||
Method* vmtarget = vtable->method_at(vmindex);
|
||||
klassVtable vtable = klass_part->vtable();
|
||||
Method* vmtarget = vtable.method_at(vmindex);
|
||||
|
||||
invoke_target(vmtarget, THREAD);
|
||||
|
||||
|
||||
@ -1108,11 +1108,6 @@ or not.
|
||||
calls callback with Klass and initiating loader (Oop) for System dictionary
|
||||
entry.
|
||||
</dd>
|
||||
<dt>forEachPrimArrayKlass(callback)</dt>
|
||||
<dd>
|
||||
calls callback with Klass and initiating loader (Oop) for each
|
||||
primitive array Klass in the system.
|
||||
</dd>
|
||||
<dt>findInstanceKlass(name)</dt>
|
||||
<dd>
|
||||
finds the first instance klass with given name from System dictionary
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,6 +48,7 @@ import sun.jvm.hotspot.code.CodeCacheVisitor;
|
||||
import sun.jvm.hotspot.code.NMethod;
|
||||
import sun.jvm.hotspot.debugger.Address;
|
||||
import sun.jvm.hotspot.debugger.OopHandle;
|
||||
import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
|
||||
import sun.jvm.hotspot.memory.SymbolTable;
|
||||
import sun.jvm.hotspot.memory.SystemDictionary;
|
||||
import sun.jvm.hotspot.memory.Universe;
|
||||
@ -853,8 +854,8 @@ public class CommandProcessor {
|
||||
} else {
|
||||
String s = t.nextToken();
|
||||
if (s.equals("-a")) {
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
if (k instanceof InstanceKlass) {
|
||||
MethodArray methods = ((InstanceKlass)k).getMethods();
|
||||
@ -887,8 +888,8 @@ public class CommandProcessor {
|
||||
if (t.countTokens() != 0) {
|
||||
usage();
|
||||
} else {
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {
|
||||
MethodArray methods = ((InstanceKlass)k).getMethods();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,16 +25,16 @@
|
||||
package sun.jvm.hotspot.classfile;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
public class ClassLoaderData extends VMObject {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
VM.registerVMInitializedObserver(new java.util.Observer() {
|
||||
public void update(java.util.Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
@ -44,19 +44,26 @@ public class ClassLoaderData extends VMObject {
|
||||
Type type = db.lookupType("ClassLoaderData");
|
||||
classLoaderField = type.getOopField("_class_loader");
|
||||
nextField = type.getAddressField("_next");
|
||||
klassesField = type.getAddressField("_klasses");
|
||||
klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
|
||||
isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
|
||||
dictionaryField = type.getAddressField("_dictionary");
|
||||
}
|
||||
|
||||
private static sun.jvm.hotspot.types.OopField classLoaderField;
|
||||
private static AddressField nextField;
|
||||
private static AddressField klassesField;
|
||||
private static MetadataField klassesField;
|
||||
private static CIntField isAnonymousField;
|
||||
private static AddressField dictionaryField;
|
||||
|
||||
public ClassLoaderData(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Dictionary dictionary() {
|
||||
Address tmp = dictionaryField.getValue();
|
||||
return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
|
||||
}
|
||||
|
||||
public static ClassLoaderData instantiateWrapperFor(Address addr) {
|
||||
if (addr == null) {
|
||||
return null;
|
||||
@ -76,7 +83,30 @@ public class ClassLoaderData extends VMObject {
|
||||
return instantiateWrapperFor(nextField.getValue(getAddress()));
|
||||
}
|
||||
|
||||
public Klass getKlasses() {
|
||||
return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress()));
|
||||
public Klass getKlasses() { return (Klass)klassesField.getValue(this); }
|
||||
|
||||
/** Lookup an already loaded class. If not found null is returned. */
|
||||
public Klass find(Symbol className) {
|
||||
for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
|
||||
if (className.equals(l.getName())) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Iterate over all klasses - including object, primitive
|
||||
array klasses */
|
||||
public void classesDo(ClassLoaderDataGraph.ClassVisitor v) {
|
||||
for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
|
||||
v.visit(l);
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterate over all klasses in the dictionary, including initiating loader. */
|
||||
public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v) {
|
||||
for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
|
||||
dictionary().allEntriesDo(v, getClassLoader());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.classfile;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
@ -52,21 +53,43 @@ public class ClassLoaderDataGraph {
|
||||
return ClassLoaderData.instantiateWrapperFor(headField.getValue());
|
||||
}
|
||||
|
||||
public static interface KlassVisitor {
|
||||
/** Lookup an already loaded class in any class loader. */
|
||||
public Klass find(String className) {
|
||||
Symbol sym = VM.getVM().getSymbolTable().probe(className);
|
||||
if (sym == null) return null;
|
||||
for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
|
||||
Klass k = cld.find(sym);
|
||||
if (k != null) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Interface for iterating through all classes. */
|
||||
public static interface ClassVisitor {
|
||||
public void visit(Klass k);
|
||||
}
|
||||
|
||||
/** Iterate over all anonymous class loaders and the klasses in those */
|
||||
public void allAnonymousKlassesDo(final KlassVisitor v) {
|
||||
for (ClassLoaderData cl = getClassLoaderGraphHead();
|
||||
cl != null;
|
||||
cl = cl.next()) {
|
||||
if (cl.getIsAnonymous() == true) {
|
||||
for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) {
|
||||
v.visit(k);
|
||||
}
|
||||
}
|
||||
/** Interface for iterating through all classes and their class
|
||||
loaders in dictionary */
|
||||
public static interface ClassAndLoaderVisitor {
|
||||
public void visit(Klass k, Oop loader);
|
||||
}
|
||||
|
||||
/** Iterate over all klasses - including object, primitive
|
||||
array klasses */
|
||||
public void classesDo(ClassVisitor v) {
|
||||
for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
|
||||
cld.classesDo(v);
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterate over all klasses - including object, primitive
|
||||
array klasses, pass initiating loader. */
|
||||
public void allEntriesDo(ClassAndLoaderVisitor v) {
|
||||
for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
|
||||
cld.allEntriesDo(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,12 +26,13 @@ package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class Dictionary extends TwoOopHashtable {
|
||||
public class Dictionary extends sun.jvm.hotspot.utilities.Hashtable {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
@ -55,56 +56,32 @@ public class Dictionary extends TwoOopHashtable {
|
||||
return DictionaryEntry.class;
|
||||
}
|
||||
|
||||
/** Iterate over all klasses in dictionary; just the classes from
|
||||
declaring class loaders */
|
||||
public void classesDo(SystemDictionary.ClassVisitor v) {
|
||||
ObjectHeap heap = VM.getVM().getObjectHeap();
|
||||
/** All classes, and their initiating class loader, passed in. */
|
||||
public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v, Oop loader) {
|
||||
int tblSize = tableSize();
|
||||
for (int index = 0; index < tblSize; index++) {
|
||||
for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
|
||||
probe = (DictionaryEntry) probe.next()) {
|
||||
probe = (DictionaryEntry) probe.next()) {
|
||||
Klass k = probe.klass();
|
||||
if (heap.equal(probe.loader(), ((InstanceKlass) k).getClassLoader())) {
|
||||
v.visit(k);
|
||||
}
|
||||
v.visit(k, loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** All classes, and their class loaders */
|
||||
public void classesDo(SystemDictionary.ClassAndLoaderVisitor v) {
|
||||
int tblSize = tableSize();
|
||||
for (int index = 0; index < tblSize; index++) {
|
||||
for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
|
||||
probe = (DictionaryEntry) probe.next()) {
|
||||
Klass k = probe.klass();
|
||||
v.visit(k, probe.loader());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Klass find(int index, long hash, Symbol className, Oop classLoader, Oop protectionDomain) {
|
||||
DictionaryEntry entry = getEntry(index, hash, className, classLoader);
|
||||
if (entry != null && entry.isValidProtectionDomain(protectionDomain)) {
|
||||
return entry.klass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// - Internals only below this point
|
||||
|
||||
private DictionaryEntry getEntry(int index, long hash, Symbol className, Oop classLoader) {
|
||||
private DictionaryEntry getEntry(int index, long hash, Symbol className) {
|
||||
for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
|
||||
entry = (DictionaryEntry) entry.next()) {
|
||||
if (entry.hash() == hash && entry.equals(className, classLoader)) {
|
||||
if (entry.hash() == hash && entry.equals(className)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean contains(Klass c, Oop classLoader) {
|
||||
long hash = computeHash(c.getName(), classLoader);
|
||||
public boolean contains(Klass c) {
|
||||
long hash = computeHash(c.getName());
|
||||
int index = hashToIndex(hash);
|
||||
|
||||
for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,28 +43,6 @@ public class DictionaryEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("DictionaryEntry");
|
||||
pdSetField = type.getAddressField("_pd_set");
|
||||
loaderDataField = type.getAddressField("_loader_data");
|
||||
}
|
||||
|
||||
// Fields
|
||||
private static AddressField pdSetField;
|
||||
private static AddressField loaderDataField;
|
||||
|
||||
// Accessors
|
||||
|
||||
public ProtectionDomainEntry pdSet() {
|
||||
Address tmp = pdSetField.getValue(addr);
|
||||
return (ProtectionDomainEntry) VMObjectFactory.newObject(
|
||||
ProtectionDomainEntry.class, tmp);
|
||||
}
|
||||
|
||||
public Oop loader() {
|
||||
return loaderData().getClassLoader();
|
||||
}
|
||||
|
||||
public ClassLoaderData loaderData() {
|
||||
return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
|
||||
}
|
||||
|
||||
public Klass klass() {
|
||||
@ -75,38 +53,9 @@ public class DictionaryEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public boolean equals(Symbol className, Oop classLoader) {
|
||||
public boolean equals(Symbol className) {
|
||||
InstanceKlass ik = (InstanceKlass) klass();
|
||||
Oop loader = loader();
|
||||
if (! ik.getName().equals(className)) {
|
||||
return false;
|
||||
} else {
|
||||
return (loader == null)? (classLoader == null) :
|
||||
(loader.equals(classLoader));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValidProtectionDomain(Oop protectionDomain) {
|
||||
if (protectionDomain == null) {
|
||||
return true;
|
||||
} else {
|
||||
return containsProtectionDomain(protectionDomain);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsProtectionDomain(Oop protectionDomain) {
|
||||
InstanceKlass ik = (InstanceKlass) klass();
|
||||
// Currently unimplemented and not used.
|
||||
// if (protectionDomain.equals(ik.getJavaMirror().getProtectionDomain())) {
|
||||
// return true; // Succeeds trivially
|
||||
// }
|
||||
for (ProtectionDomainEntry current = pdSet(); current != null;
|
||||
current = current.next()) {
|
||||
if (protectionDomain.equals(current.protectionDomain())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ik.getName().equals(className);
|
||||
}
|
||||
|
||||
/* covariant return type :-(
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class LoaderConstraintEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("LoaderConstraintEntry");
|
||||
nameField = type.getAddressField("_name");
|
||||
numLoadersField = type.getCIntegerField("_num_loaders");
|
||||
maxLoadersField = type.getCIntegerField("_max_loaders");
|
||||
loadersField = type.getAddressField("_loaders");
|
||||
}
|
||||
|
||||
// Fields
|
||||
private static AddressField nameField;
|
||||
private static CIntegerField numLoadersField;
|
||||
private static CIntegerField maxLoadersField;
|
||||
private static AddressField loadersField;
|
||||
|
||||
// Accessors
|
||||
|
||||
public Symbol name() {
|
||||
return Symbol.create(nameField.getValue(addr));
|
||||
}
|
||||
|
||||
public int numLoaders() {
|
||||
return (int) numLoadersField.getValue(addr);
|
||||
}
|
||||
|
||||
public int maxLoaders() {
|
||||
return (int) maxLoadersField.getValue(addr);
|
||||
}
|
||||
|
||||
public Oop initiatingLoader(int i) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(i >= 0 && i < numLoaders(), "invalid index");
|
||||
}
|
||||
Address loaders = loadersField.getValue(addr);
|
||||
OopHandle loader = loaders.addOffsetToAsOopHandle(i * VM.getVM().getOopSize());
|
||||
return VM.getVM().getObjectHeap().newOop(loader);
|
||||
}
|
||||
|
||||
public LoaderConstraintEntry(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
/* covariant return type :-(
|
||||
public LoaderConstraintEntry next() {
|
||||
return (LoaderConstraintEntry) super.next();
|
||||
}
|
||||
For now, let the caller cast it ..
|
||||
*/
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class LoaderConstraintTable extends TwoOopHashtable {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("LoaderConstraintTable");
|
||||
}
|
||||
|
||||
public LoaderConstraintTable(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
// this is overriden here so that Hashtable.bucket will return
|
||||
// object of LoaderConstraintEntry.class
|
||||
protected Class getHashtableEntryClass() {
|
||||
return LoaderConstraintEntry.class;
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.classfile.ClassLoaderData;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class PlaceholderEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("PlaceholderEntry");
|
||||
loaderDataField = type.getAddressField("_loader_data");
|
||||
}
|
||||
|
||||
// Field
|
||||
private static AddressField loaderDataField;
|
||||
|
||||
// Accessor
|
||||
public Oop loader() {
|
||||
return loaderData().getClassLoader();
|
||||
}
|
||||
|
||||
public ClassLoaderData loaderData() {
|
||||
return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
|
||||
}
|
||||
|
||||
public PlaceholderEntry(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Symbol klass() {
|
||||
return Symbol.create(literalValue());
|
||||
}
|
||||
|
||||
/* covariant return type :-(
|
||||
public PlaceholderEntry next() {
|
||||
return (PlaceholderEntry) super.next();
|
||||
}
|
||||
For now, let the caller cast it ..
|
||||
*/
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class PlaceholderTable extends TwoOopHashtable {
|
||||
public PlaceholderTable(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
// this is overriden here so that Hashtable.bucket will return
|
||||
// object of PlacholderEntry.class
|
||||
protected Class getHashtableEntryClass() {
|
||||
return PlaceholderEntry.class;
|
||||
}
|
||||
|
||||
/** All array classes of primitive type, and their class loaders */
|
||||
public void primArrayClassesDo(SystemDictionary.ClassAndLoaderVisitor v) {
|
||||
ObjectHeap heap = VM.getVM().getObjectHeap();
|
||||
int tblSize = tableSize();
|
||||
for (int index = 0; index < tblSize; index++) {
|
||||
for (PlaceholderEntry probe = (PlaceholderEntry) bucket(index); probe != null;
|
||||
probe = (PlaceholderEntry) probe.next()) {
|
||||
Symbol sym = probe.klass();
|
||||
// array of primitive arrays are stored in system dictionary as placeholders
|
||||
FieldType ft = new FieldType(sym);
|
||||
if (ft.isArray()) {
|
||||
FieldType.ArrayInfo info = ft.getArrayInfo();
|
||||
if (info.elementBasicType() != BasicType.getTObject()) {
|
||||
Klass arrayKlass = heap.typeArrayKlassObj(info.elementBasicType());
|
||||
arrayKlass = arrayKlass.arrayKlassOrNull(info.dimension());
|
||||
v.visit(arrayKlass, probe.loader());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
public class ProtectionDomainCacheEntry extends VMObject {
|
||||
private static sun.jvm.hotspot.types.OopField protectionDomainField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("ProtectionDomainCacheEntry");
|
||||
protectionDomainField = type.getOopField("_literal");
|
||||
}
|
||||
|
||||
public ProtectionDomainCacheEntry(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Oop protectionDomain() {
|
||||
return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr));
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
public class ProtectionDomainEntry extends VMObject {
|
||||
private static AddressField nextField;
|
||||
private static AddressField pdCacheField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("ProtectionDomainEntry");
|
||||
|
||||
nextField = type.getAddressField("_next");
|
||||
pdCacheField = type.getAddressField("_pd_cache");
|
||||
}
|
||||
|
||||
public ProtectionDomainEntry(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public ProtectionDomainEntry next() {
|
||||
return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr));
|
||||
}
|
||||
|
||||
public Oop protectionDomain() {
|
||||
ProtectionDomainCacheEntry pd_cache = (ProtectionDomainCacheEntry)
|
||||
VMObjectFactory.newObject(ProtectionDomainCacheEntry.class, pdCacheField.getValue(addr));
|
||||
return pd_cache.protectionDomain();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,15 +26,13 @@ package sun.jvm.hotspot.memory;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
public class SystemDictionary {
|
||||
private static AddressField dictionaryField;
|
||||
private static AddressField sharedDictionaryField;
|
||||
private static AddressField placeholdersField;
|
||||
private static AddressField loaderConstraintTableField;
|
||||
private static sun.jvm.hotspot.types.OopField javaSystemLoaderField;
|
||||
|
||||
private static AddressField objectKlassField;
|
||||
@ -56,10 +54,7 @@ public class SystemDictionary {
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("SystemDictionary");
|
||||
|
||||
dictionaryField = type.getAddressField("_dictionary");
|
||||
sharedDictionaryField = type.getAddressField("_shared_dictionary");
|
||||
placeholdersField = type.getAddressField("_placeholders");
|
||||
loaderConstraintTableField = type.getAddressField("_loader_constraints");
|
||||
javaSystemLoaderField = type.getOopField("_java_system_loader");
|
||||
|
||||
objectKlassField = type.getAddressField(WK_KLASS("Object_klass"));
|
||||
@ -81,26 +76,11 @@ public class SystemDictionary {
|
||||
return (kname+"_knum");
|
||||
}
|
||||
|
||||
public Dictionary dictionary() {
|
||||
Address tmp = dictionaryField.getValue();
|
||||
return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
|
||||
}
|
||||
|
||||
public Dictionary sharedDictionary() {
|
||||
Address tmp = sharedDictionaryField.getValue();
|
||||
return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
|
||||
}
|
||||
|
||||
public PlaceholderTable placeholders() {
|
||||
Address tmp = placeholdersField.getValue();
|
||||
return (PlaceholderTable) VMObjectFactory.newObject(PlaceholderTable.class, tmp);
|
||||
}
|
||||
|
||||
public LoaderConstraintTable constraints() {
|
||||
Address tmp = placeholdersField.getValue();
|
||||
return (LoaderConstraintTable) VMObjectFactory.newObject(LoaderConstraintTable.class, tmp);
|
||||
}
|
||||
|
||||
// few well known classes -- not all are added here.
|
||||
// add more if needed.
|
||||
public static InstanceKlass getThreadKlass() {
|
||||
@ -132,8 +112,8 @@ public class SystemDictionary {
|
||||
}
|
||||
|
||||
public InstanceKlass getAbstractOwnableSynchronizerKlass() {
|
||||
return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer",
|
||||
null, null);
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
return (InstanceKlass) cldg.find("java/util/concurrent/locks/AbstractOwnableSynchronizer");
|
||||
}
|
||||
|
||||
public static Oop javaSystemLoader() {
|
||||
@ -143,60 +123,4 @@ public class SystemDictionary {
|
||||
private static Oop newOop(OopHandle handle) {
|
||||
return VM.getVM().getObjectHeap().newOop(handle);
|
||||
}
|
||||
|
||||
/** Lookup an already loaded class. If not found null is returned. */
|
||||
public Klass find(String className, Oop classLoader, Oop protectionDomain) {
|
||||
Symbol sym = VM.getVM().getSymbolTable().probe(className);
|
||||
if (sym == null) return null;
|
||||
return find(sym, classLoader, protectionDomain);
|
||||
}
|
||||
|
||||
/** Lookup an already loaded class. If not found null is returned. */
|
||||
public Klass find(Symbol className, Oop classLoader, Oop protectionDomain) {
|
||||
Dictionary dict = dictionary();
|
||||
long hash = dict.computeHash(className, classLoader);
|
||||
int index = dict.hashToIndex(hash);
|
||||
return dict.find(index, hash, className, classLoader, protectionDomain);
|
||||
}
|
||||
|
||||
/** Interface for iterating through all classes in dictionary */
|
||||
public static interface ClassVisitor {
|
||||
public void visit(Klass k);
|
||||
}
|
||||
|
||||
/** Interface for iterating through all classes and their class
|
||||
loaders in dictionary */
|
||||
public static interface ClassAndLoaderVisitor {
|
||||
public void visit(Klass k, Oop loader);
|
||||
}
|
||||
|
||||
/** Iterate over all klasses - including object, primitive
|
||||
array klasses */
|
||||
public void allClassesDo(final ClassVisitor v) {
|
||||
ClassVisitor visitor = new ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
for (Klass l = k; l != null; l = l.arrayKlassOrNull()) {
|
||||
v.visit(l);
|
||||
}
|
||||
}
|
||||
};
|
||||
classesDo(visitor);
|
||||
VM.getVM().getUniverse().basicTypeClassesDo(visitor);
|
||||
}
|
||||
|
||||
/** Iterate over all klasses in dictionary; just the classes from
|
||||
declaring class loaders */
|
||||
public void classesDo(ClassVisitor v) {
|
||||
dictionary().classesDo(v);
|
||||
}
|
||||
|
||||
/** All classes, and their class loaders */
|
||||
public void classesDo(ClassAndLoaderVisitor v) {
|
||||
dictionary().classesDo(v);
|
||||
}
|
||||
|
||||
/** All array classes of primitive type, and their class loaders */
|
||||
public void primArrayClassesDo(ClassAndLoaderVisitor v) {
|
||||
placeholders().primArrayClassesDo(v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -164,18 +164,6 @@ public class Universe {
|
||||
return newOop(systemThreadGroupField.getValue());
|
||||
}
|
||||
|
||||
// iterate through the single dimensional primitive array klasses
|
||||
// refer to basic_type_classes_do(void f(Klass*)) in universe.cpp
|
||||
public void basicTypeClassesDo(SystemDictionary.ClassVisitor visitor) {
|
||||
visitor.visit(new TypeArrayKlass(boolArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(byteArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(charArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(intArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(shortArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(longArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(singleArrayKlassField.getValue()));
|
||||
visitor.visit(new TypeArrayKlass(doubleArrayKlassField.getValue()));
|
||||
}
|
||||
|
||||
public void print() { printOn(System.out); }
|
||||
public void printOn(PrintStream tty) {
|
||||
|
||||
@ -91,7 +91,6 @@ public class InstanceKlass extends Klass {
|
||||
fields = type.getAddressField("_fields");
|
||||
javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
|
||||
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
||||
classLoaderData = type.getAddressField("_class_loader_data");
|
||||
sourceDebugExtension = type.getAddressField("_source_debug_extension");
|
||||
innerClasses = type.getAddressField("_inner_classes");
|
||||
sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
|
||||
@ -166,7 +165,6 @@ public class InstanceKlass extends Klass {
|
||||
private static AddressField fields;
|
||||
private static CIntField javaFieldsCount;
|
||||
private static MetadataField constants;
|
||||
private static AddressField classLoaderData;
|
||||
private static AddressField sourceDebugExtension;
|
||||
private static AddressField innerClasses;
|
||||
private static CIntField sourceFileNameIndex;
|
||||
@ -328,7 +326,7 @@ public class InstanceKlass extends Klass {
|
||||
// MetaspaceObj in the CDS shared archive.
|
||||
Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary();
|
||||
if (sharedDictionary != null) {
|
||||
if (sharedDictionary.contains(this, null)) {
|
||||
if (sharedDictionary.contains(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -448,8 +446,6 @@ public class InstanceKlass extends Klass {
|
||||
return allFieldsCount;
|
||||
}
|
||||
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
|
||||
public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
|
||||
public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); }
|
||||
public Symbol getSourceFileName() { return getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); }
|
||||
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
|
||||
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.oops;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
@ -63,6 +64,7 @@ public class Klass extends Metadata implements ClassConstants {
|
||||
nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0);
|
||||
nextLink = new MetadataField(type.getAddressField("_next_link"), 0);
|
||||
vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0);
|
||||
classLoaderData = type.getAddressField("_class_loader_data");
|
||||
|
||||
LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue();
|
||||
LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue();
|
||||
@ -96,6 +98,7 @@ public class Klass extends Metadata implements ClassConstants {
|
||||
private static MetadataField nextLink;
|
||||
private static sun.jvm.hotspot.types.Field traceIDField;
|
||||
private static CIntField vtableLen;
|
||||
private static AddressField classLoaderData;
|
||||
|
||||
private Address getValue(AddressField field) {
|
||||
return addr.getAddressAt(field.getOffset());
|
||||
@ -110,7 +113,7 @@ public class Klass extends Metadata implements ClassConstants {
|
||||
public Klass getSuper() { return (Klass) superField.getValue(this); }
|
||||
public Klass getJavaSuper() { return null; }
|
||||
public int getLayoutHelper() { return (int) layoutHelper.getValue(this); }
|
||||
public Symbol getName() { return getSymbol(name); }
|
||||
public Symbol getName() { return getSymbol(name); }
|
||||
public long getAccessFlags() { return accessFlags.getValue(this); }
|
||||
// Convenience routine
|
||||
public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); }
|
||||
@ -119,6 +122,9 @@ public class Klass extends Metadata implements ClassConstants {
|
||||
public Klass getNextLinkKlass() { return (Klass) nextLink.getValue(this); }
|
||||
public long getVtableLen() { return vtableLen.getValue(this); }
|
||||
|
||||
public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
|
||||
public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); }
|
||||
|
||||
public long traceID() {
|
||||
if (traceIDField == null) return 0;
|
||||
return traceIDField.getJLong(addr);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,7 @@ import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
@ -106,8 +107,8 @@ public class ClassLoaderStats extends Tool {
|
||||
err.print("computing per loader stat ..");
|
||||
}
|
||||
|
||||
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
||||
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
if (! (k instanceof InstanceKlass)) {
|
||||
return;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2013, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,6 +29,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.Manifest;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
@ -100,9 +101,9 @@ public class ClassDump extends Tool {
|
||||
setOutputDirectory(dirName);
|
||||
}
|
||||
|
||||
// walk through the system dictionary
|
||||
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
||||
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||
// walk through the loaded classes
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
if (k instanceof InstanceKlass) {
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
|
||||
public class Hashtable extends BasicHashtable {
|
||||
@ -48,6 +49,10 @@ public class Hashtable extends BasicHashtable {
|
||||
return HashtableEntry.class;
|
||||
}
|
||||
|
||||
public int computeHash(Symbol name) {
|
||||
return (int) name.identityHash();
|
||||
}
|
||||
|
||||
public int hashToIndex(long fullHash) {
|
||||
return (int) (fullHash % tableSize());
|
||||
}
|
||||
|
||||
@ -586,23 +586,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
}
|
||||
|
||||
private void writeClassDumpRecords() throws IOException {
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
|
||||
try {
|
||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
try {
|
||||
writeHeapRecordPrologue();
|
||||
writeClassDumpRecord(k);
|
||||
writeHeapRecordEpilogue();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Add the anonymous classes also which are not present in the
|
||||
// System Dictionary
|
||||
cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
|
||||
cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
try {
|
||||
writeHeapRecordPrologue();
|
||||
@ -1088,26 +1074,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
|
||||
private void writeClasses() throws IOException {
|
||||
// write class list (id, name) association
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
|
||||
try {
|
||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
try {
|
||||
Instance clazz = k.getJavaMirror();
|
||||
writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
|
||||
out.writeInt(serialNum);
|
||||
writeObjectID(clazz);
|
||||
KlassMap.add(serialNum - 1, k);
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
writeSymbolID(k.getName());
|
||||
serialNum++;
|
||||
} catch (IOException exp) {
|
||||
throw new RuntimeException(exp);
|
||||
}
|
||||
}
|
||||
});
|
||||
cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
|
||||
cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
try {
|
||||
Instance clazz = k.getJavaMirror();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2015, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.gc.shared.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
@ -113,8 +114,8 @@ public class ReversePtrsAnalysis {
|
||||
new RootVisitor("Weak global JNI handle root"));
|
||||
|
||||
// Do Java-level static fields
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
|
||||
public void visit(Klass k) {
|
||||
if (k instanceof InstanceKlass) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
package sun.jvm.hotspot.utilities;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
@ -52,8 +53,8 @@ public class SystemDictionaryHelper {
|
||||
}
|
||||
|
||||
final Vector tmp = new Vector();
|
||||
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
||||
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass k) {
|
||||
if (k instanceof InstanceKlass) {
|
||||
InstanceKlass ik = (InstanceKlass) k;
|
||||
@ -100,42 +101,15 @@ public class SystemDictionaryHelper {
|
||||
public static InstanceKlass findInstanceKlass(String className) {
|
||||
// convert to internal name
|
||||
className = className.replace('.', '/');
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
|
||||
// check whether we have a bootstrap class of given name
|
||||
Klass klass = sysDict.find(className, null, null);
|
||||
if (klass != null) {
|
||||
// check whether we have a class of given name
|
||||
Klass klass = cldg.find(className);
|
||||
if (klass != null && klass instanceof InstanceKlass) {
|
||||
return (InstanceKlass) klass;
|
||||
} else {
|
||||
// no match ..
|
||||
return null;
|
||||
}
|
||||
|
||||
// check whether we have a system class of given name
|
||||
klass = sysDict.find(className, sysDict.javaSystemLoader(), null);
|
||||
if (klass != null) {
|
||||
return (InstanceKlass) klass;
|
||||
}
|
||||
|
||||
// didn't find bootstrap or system class of given name.
|
||||
// search through the entire dictionary..
|
||||
InstanceKlass[] tmpKlasses = getAllInstanceKlasses();
|
||||
// instance klass array is sorted by name. do binary search
|
||||
int low = 0;
|
||||
int high = tmpKlasses.length-1;
|
||||
|
||||
int mid = -1;
|
||||
while (low <= high) {
|
||||
mid = (low + high) >> 1;
|
||||
InstanceKlass midVal = tmpKlasses[mid];
|
||||
int cmp = midVal.getName().asString().compareTo(className);
|
||||
|
||||
if (cmp < 0) {
|
||||
low = mid + 1;
|
||||
} else if (cmp > 0) {
|
||||
high = mid - 1;
|
||||
} else { // match found
|
||||
return tmpKlasses[mid];
|
||||
}
|
||||
}
|
||||
// no match ..
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.utilities;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
|
||||
public class TwoOopHashtable extends Hashtable {
|
||||
public TwoOopHashtable(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public long computeHash(Symbol name, Oop loader) {
|
||||
return ((int) name.identityHash()
|
||||
^ (int) (loader == null ? 0 : loader.identityHash())) & 0xFFFFFFFFL;
|
||||
}
|
||||
|
||||
public int indexFor(Symbol name, Oop loader) {
|
||||
return hashToIndex(computeHash(name, loader));
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities.soql;
|
||||
import java.util.*;
|
||||
import javax.script.ScriptException;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
import sun.jvm.hotspot.memory.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
@ -166,11 +167,12 @@ public class JSJavaHeap extends DefaultScriptObject {
|
||||
}
|
||||
|
||||
final Callable finalFunc = func;
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
|
||||
if (withLoader) {
|
||||
sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
|
||||
public void visit(Klass kls, Oop loader) {
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass kls) {
|
||||
JSJavaKlass jk = factory.newJSJavaKlass(kls);
|
||||
Oop loader = kls.getClassLoader();
|
||||
if (jk == null) {
|
||||
return;
|
||||
}
|
||||
@ -189,7 +191,7 @@ public class JSJavaHeap extends DefaultScriptObject {
|
||||
});
|
||||
|
||||
} else {
|
||||
sysDict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
|
||||
public void visit(Klass kls) {
|
||||
JSJavaKlass jk = factory.newJSJavaKlass(kls);
|
||||
if (jk == null) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -513,24 +513,18 @@ function systemLoader() {
|
||||
return sa.sysDict.javaSystemLoader();
|
||||
}
|
||||
|
||||
// iterate system dictionary for each 'Klass'
|
||||
// iterate class loader data for each 'Klass'
|
||||
function forEachKlass(callback) {
|
||||
var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor;
|
||||
var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassVisitor;
|
||||
var visitor = new VisitorClass() { visit: callback };
|
||||
sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor);
|
||||
sa.sysDict["classesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassVisitor)"](visitor);
|
||||
}
|
||||
|
||||
// iterate system dictionary for each 'Klass' and initiating loader
|
||||
function forEachKlassAndLoader(callback) {
|
||||
var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
|
||||
var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor;
|
||||
var visitor = new VisitorClass() { visit: callback };
|
||||
sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor);
|
||||
}
|
||||
|
||||
// iterate system dictionary for each primitive array klass
|
||||
function forEachPrimArrayKlass(callback) {
|
||||
var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
|
||||
sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback });
|
||||
sa.sysDict["allEntriesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor)"](visitor);
|
||||
}
|
||||
|
||||
// 'oop' to higher-level java object wrapper in which for(i in o)
|
||||
|
||||
@ -743,7 +743,7 @@ JRT_END
|
||||
|
||||
#ifndef DEOPTIMIZE_WHEN_PATCHING
|
||||
|
||||
static Klass* resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
|
||||
static Klass* resolve_field_return_klass(const methodHandle& caller, int bci, TRAPS) {
|
||||
Bytecode_field field_access(caller, bci);
|
||||
// This can be static or non-static field access
|
||||
Bytecodes::Code code = field_access.code();
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
// ciMethod::ciMethod
|
||||
//
|
||||
// Loaded method.
|
||||
ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
|
||||
ciMethod::ciMethod(const methodHandle& h_m, ciInstanceKlass* holder) :
|
||||
ciMetadata(h_m()),
|
||||
_holder(holder)
|
||||
{
|
||||
@ -979,7 +979,7 @@ bool ciMethod::has_member_arg() const {
|
||||
//
|
||||
// Generate new MethodData* objects at compile time.
|
||||
// Return true if allocation was successful or no MDO is required.
|
||||
bool ciMethod::ensure_method_data(methodHandle h_m) {
|
||||
bool ciMethod::ensure_method_data(const methodHandle& h_m) {
|
||||
EXCEPTION_CONTEXT;
|
||||
if (is_native() || is_abstract() || h_m()->is_accessor()) {
|
||||
return true;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -101,7 +101,7 @@ class ciMethod : public ciMetadata {
|
||||
BCEscapeAnalyzer* _bcea;
|
||||
#endif
|
||||
|
||||
ciMethod(methodHandle h_m, ciInstanceKlass* holder);
|
||||
ciMethod(const methodHandle& h_m, ciInstanceKlass* holder);
|
||||
ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor);
|
||||
|
||||
oop loader() const { return _holder->loader(); }
|
||||
@ -112,7 +112,7 @@ class ciMethod : public ciMetadata {
|
||||
|
||||
void load_code();
|
||||
|
||||
bool ensure_method_data(methodHandle h_m);
|
||||
bool ensure_method_data(const methodHandle& h_m);
|
||||
|
||||
void code_at_put(int bci, Bytecodes::Code code) {
|
||||
Bytecodes::check(code);
|
||||
|
||||
@ -1060,7 +1060,7 @@ public:
|
||||
class MethodAnnotationCollector : public AnnotationCollector{
|
||||
public:
|
||||
MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
|
||||
void apply_to(methodHandle m);
|
||||
void apply_to(const methodHandle& m);
|
||||
};
|
||||
|
||||
class ClassFileParser::ClassAnnotationCollector : public AnnotationCollector{
|
||||
@ -2095,7 +2095,7 @@ ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
|
||||
MetadataFactory::free_array<u1>(_loader_data, _field_type_annotations);
|
||||
}
|
||||
|
||||
void MethodAnnotationCollector::apply_to(methodHandle m) {
|
||||
void MethodAnnotationCollector::apply_to(const methodHandle& m) {
|
||||
if (has_annotation(_method_CallerSensitive))
|
||||
m->set_caller_sensitive(true);
|
||||
if (has_annotation(_method_ForceInline))
|
||||
@ -3632,7 +3632,7 @@ static unsigned int compute_oop_map_count(const InstanceKlass* super,
|
||||
#ifndef PRODUCT
|
||||
static void print_field_layout(const Symbol* name,
|
||||
Array<u2>* fields,
|
||||
constantPoolHandle cp,
|
||||
const constantPoolHandle& cp,
|
||||
int instance_size,
|
||||
int instance_fields_start,
|
||||
int instance_fields_end,
|
||||
|
||||
@ -1887,7 +1887,7 @@ static void clear_pending_exception_if_not_oom(TRAPS) {
|
||||
*
|
||||
* TODO: This should be a private method in a CompileTheWorld class.
|
||||
*/
|
||||
static bool can_be_compiled(methodHandle m, int comp_level) {
|
||||
static bool can_be_compiled(const methodHandle& m, int comp_level) {
|
||||
assert(CompileTheWorld, "must be");
|
||||
|
||||
// It's not valid to compile a native wrapper for MethodHandle methods
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -49,6 +49,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
@ -114,6 +115,12 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
|
||||
} else {
|
||||
_unnamed_module = NULL;
|
||||
}
|
||||
|
||||
if (!is_anonymous) {
|
||||
_dictionary = create_dictionary();
|
||||
} else {
|
||||
_dictionary = NULL;
|
||||
}
|
||||
TRACE_INIT_ID(this);
|
||||
}
|
||||
|
||||
@ -450,10 +457,82 @@ void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) {
|
||||
}
|
||||
}
|
||||
|
||||
// Class iterator used by the compiler. It gets some number of classes at
|
||||
// a safepoint to decay invocation counters on the methods.
|
||||
class ClassLoaderDataGraphKlassIteratorStatic {
|
||||
ClassLoaderData* _current_loader_data;
|
||||
Klass* _current_class_entry;
|
||||
public:
|
||||
|
||||
ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {}
|
||||
|
||||
InstanceKlass* try_get_next_class() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
int max_classes = InstanceKlass::number_of_instance_classes();
|
||||
for (int i = 0; i < max_classes; i++) {
|
||||
|
||||
if (_current_class_entry != NULL) {
|
||||
Klass* k = _current_class_entry;
|
||||
_current_class_entry = _current_class_entry->next_link();
|
||||
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
// Only return loaded classes
|
||||
if (ik->is_loaded()) {
|
||||
return ik;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Go to next CLD
|
||||
if (_current_loader_data != NULL) {
|
||||
_current_loader_data = _current_loader_data->next();
|
||||
}
|
||||
// Start at the beginning
|
||||
if (_current_loader_data == NULL) {
|
||||
_current_loader_data = ClassLoaderDataGraph::_head;
|
||||
}
|
||||
|
||||
_current_class_entry = _current_loader_data->klasses();
|
||||
}
|
||||
}
|
||||
// should never be reached: an InstanceKlass should be returned above
|
||||
ShouldNotReachHere();
|
||||
return NULL; // Object_klass not even loaded?
|
||||
}
|
||||
|
||||
// If the current class for the static iterator is a class being unloaded or
|
||||
// deallocated, adjust the current class.
|
||||
void adjust_saved_class(ClassLoaderData* cld) {
|
||||
if (_current_loader_data == cld) {
|
||||
_current_loader_data = cld->next();
|
||||
if (_current_loader_data != NULL) {
|
||||
_current_class_entry = _current_loader_data->klasses();
|
||||
} // else try_get_next_class will start at the head
|
||||
}
|
||||
}
|
||||
|
||||
void adjust_saved_class(Klass* klass) {
|
||||
if (_current_class_entry == klass) {
|
||||
_current_class_entry = klass->next_link();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
|
||||
|
||||
InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
|
||||
return static_klass_iterator.try_get_next_class();
|
||||
}
|
||||
|
||||
|
||||
// Remove a klass from the _klasses list for scratch_class during redefinition
|
||||
// or parsed class in the case of an error.
|
||||
void ClassLoaderData::remove_class(Klass* scratch_class) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
|
||||
// Adjust global class iterator.
|
||||
static_klass_iterator.adjust_saved_class(scratch_class);
|
||||
|
||||
Klass* prev = NULL;
|
||||
for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
|
||||
if (k == scratch_class) {
|
||||
@ -493,6 +572,9 @@ void ClassLoaderData::unload() {
|
||||
// In some rare cases items added to this list will not be freed elsewhere.
|
||||
// To keep it simple, just free everything in it here.
|
||||
free_deallocate_list();
|
||||
|
||||
// Clean up global class iterator for compiler
|
||||
static_klass_iterator.adjust_saved_class(this);
|
||||
}
|
||||
|
||||
ModuleEntryTable* ClassLoaderData::modules() {
|
||||
@ -515,6 +597,45 @@ ModuleEntryTable* ClassLoaderData::modules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
const int _boot_loader_dictionary_size = 1009;
|
||||
const int _default_loader_dictionary_size = 107;
|
||||
const int _prime_array_size = 8; // array of primes for system dictionary size
|
||||
const int _average_depth_goal = 3; // goal for lookup length
|
||||
const int _primelist[_prime_array_size] = {107, 1009, 2017, 4049, 5051, 10103, 20201, 40423};
|
||||
|
||||
// Calculate a "good" dictionary size based
|
||||
// on predicted or current loaded classes count.
|
||||
static int calculate_dictionary_size(int classcount) {
|
||||
int newsize = _primelist[0];
|
||||
if (classcount > 0 && !DumpSharedSpaces) {
|
||||
int index = 0;
|
||||
int desiredsize = classcount/_average_depth_goal;
|
||||
for (newsize = _primelist[index]; index < _prime_array_size -1;
|
||||
newsize = _primelist[++index]) {
|
||||
if (desiredsize <= newsize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newsize;
|
||||
}
|
||||
|
||||
Dictionary* ClassLoaderData::create_dictionary() {
|
||||
assert(!is_anonymous(), "anonymous class loader data do not have a dictionary");
|
||||
int size;
|
||||
if (_the_null_class_loader_data == NULL) {
|
||||
size = _boot_loader_dictionary_size;
|
||||
} else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
|
||||
size = 1; // there's only one class in relection class loader and no initiated classes
|
||||
} else if (is_system_class_loader_data()) {
|
||||
size = calculate_dictionary_size(PredictedLoadedClassCount);
|
||||
} else {
|
||||
size = _default_loader_dictionary_size;
|
||||
}
|
||||
return new Dictionary(this, size);
|
||||
}
|
||||
|
||||
// Unloading support
|
||||
oop ClassLoaderData::keep_alive_object() const {
|
||||
assert_locked_or_safepoint(_metaspace_lock);
|
||||
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
|
||||
@ -546,6 +667,13 @@ ClassLoaderData::~ClassLoaderData() {
|
||||
_modules = NULL;
|
||||
}
|
||||
|
||||
// Release C heap allocated hashtable for the dictionary
|
||||
if (_dictionary != NULL) {
|
||||
// Destroy the table itself
|
||||
delete _dictionary;
|
||||
_dictionary = NULL;
|
||||
}
|
||||
|
||||
if (_unnamed_module != NULL) {
|
||||
_unnamed_module->delete_unnamed_module();
|
||||
_unnamed_module = NULL;
|
||||
@ -974,6 +1102,46 @@ void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
|
||||
}
|
||||
}
|
||||
|
||||
#define FOR_ALL_DICTIONARY(X) for (ClassLoaderData* X = _head; X != NULL; X = X->next()) \
|
||||
if (X->dictionary() != NULL)
|
||||
|
||||
// Walk classes in the loaded class dictionaries in various forms.
|
||||
// Only walks the classes defined in this class loader.
|
||||
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->classes_do(f);
|
||||
}
|
||||
}
|
||||
|
||||
// Only walks the classes defined in this class loader.
|
||||
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->classes_do(f, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
// Walks all entries in the dictionary including entries initiated by this class loader.
|
||||
void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->all_entries_do(f);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderDataGraph::verify_dictionary() {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
cld->dictionary()->verify();
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderDataGraph::print_dictionary(bool details) {
|
||||
FOR_ALL_DICTIONARY(cld) {
|
||||
tty->print("Dictionary for class loader ");
|
||||
cld->print_value();
|
||||
tty->cr();
|
||||
cld->dictionary()->print(details);
|
||||
}
|
||||
}
|
||||
|
||||
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
|
||||
assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
|
||||
|
||||
@ -1074,14 +1242,19 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
|
||||
}
|
||||
|
||||
if (seen_dead_loader) {
|
||||
// Walk a ModuleEntry's reads and a PackageEntry's exports lists
|
||||
// to determine if there are modules on those lists that are now
|
||||
// dead and should be removed. A module's life cycle is equivalent
|
||||
// to its defining class loader's life cycle. Since a module is
|
||||
// considered dead if its class loader is dead, these walks must
|
||||
// occur after each class loader's aliveness is determined.
|
||||
data = _head;
|
||||
while (data != NULL) {
|
||||
// Remove entries in the dictionary of live class loader that have
|
||||
// initiated loading classes in a dead class loader.
|
||||
if (data->dictionary() != NULL) {
|
||||
data->dictionary()->do_unloading();
|
||||
}
|
||||
// Walk a ModuleEntry's reads, and a PackageEntry's exports
|
||||
// lists to determine if there are modules on those lists that are now
|
||||
// dead and should be removed. A module's life cycle is equivalent
|
||||
// to its defining class loader's life cycle. Since a module is
|
||||
// considered dead if its class loader is dead, these walks must
|
||||
// occur after each class loader's aliveness is determined.
|
||||
if (data->packages() != NULL) {
|
||||
data->packages()->purge_all_package_exports();
|
||||
}
|
||||
@ -1253,6 +1426,15 @@ void ClassLoaderData::print_value_on(outputStream* out) const {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderData::print_on(outputStream* out) const {
|
||||
if (class_loader() == NULL) {
|
||||
out->print("NULL class_loader");
|
||||
} else {
|
||||
out->print("class loader " INTPTR_FORMAT " ", p2i(this));
|
||||
class_loader()->print_on(out);
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_TRACE
|
||||
|
||||
Ticks ClassLoaderDataGraph::_class_unload_time;
|
||||
|
||||
@ -46,9 +46,8 @@
|
||||
// used by the dynamic linker to allocate the runtime representation of all
|
||||
// the types it defines.
|
||||
//
|
||||
// ClassLoaderData are stored in the runtime representation of classes and the
|
||||
// system dictionary, are roots of garbage collection, and provides iterators
|
||||
// for root tracing and other GC operations.
|
||||
// ClassLoaderData are stored in the runtime representation of classes,
|
||||
// and provides iterators for root tracing and other GC operations.
|
||||
|
||||
class ClassLoaderData;
|
||||
class JNIMethodBlock;
|
||||
@ -57,6 +56,8 @@ class ModuleEntry;
|
||||
class PackageEntry;
|
||||
class ModuleEntryTable;
|
||||
class PackageEntryTable;
|
||||
class DictionaryEntry;
|
||||
class Dictionary;
|
||||
|
||||
// GC root for walking class loader data created
|
||||
|
||||
@ -64,6 +65,7 @@ class ClassLoaderDataGraph : public AllStatic {
|
||||
friend class ClassLoaderData;
|
||||
friend class ClassLoaderDataGraphMetaspaceIterator;
|
||||
friend class ClassLoaderDataGraphKlassIteratorAtomic;
|
||||
friend class ClassLoaderDataGraphKlassIteratorStatic;
|
||||
friend class VMStructs;
|
||||
private:
|
||||
// All CLDs (except the null CLD) can be reached by walking _head->_next->...
|
||||
@ -109,6 +111,22 @@ class ClassLoaderDataGraph : public AllStatic {
|
||||
static void classes_unloading_do(void f(Klass* const));
|
||||
static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
|
||||
|
||||
// dictionary do
|
||||
// Iterate over all klasses in dictionary, but
|
||||
// just the classes from defining class loaders.
|
||||
static void dictionary_classes_do(void f(InstanceKlass*));
|
||||
// Added for initialize_itable_for_klass to handle exceptions.
|
||||
static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
|
||||
|
||||
// Iterate all classes and their class loaders, including initiating class loaders.
|
||||
static void dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
|
||||
|
||||
// VM_CounterDecay iteration support
|
||||
static InstanceKlass* try_get_next_class();
|
||||
|
||||
static void verify_dictionary();
|
||||
static void print_dictionary(bool details);
|
||||
|
||||
// CMS support.
|
||||
static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
|
||||
static GrowableArray<ClassLoaderData*>* new_clds();
|
||||
@ -193,6 +211,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
|
||||
friend class ClassLoaderDataGraph;
|
||||
friend class ClassLoaderDataGraphKlassIteratorAtomic;
|
||||
friend class ClassLoaderDataGraphKlassIteratorStatic;
|
||||
friend class ClassLoaderDataGraphMetaspaceIterator;
|
||||
friend class MetaDataFactory;
|
||||
friend class Method;
|
||||
@ -221,8 +240,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
|
||||
Klass* volatile _klasses; // The classes defined by the class loader.
|
||||
PackageEntryTable* volatile _packages; // The packages defined by the class loader.
|
||||
ModuleEntryTable* volatile _modules; // The modules defined by the class loader.
|
||||
ModuleEntry* _unnamed_module; // This class loader's unnamed module.
|
||||
ModuleEntryTable* volatile _modules; // The modules defined by the class loader.
|
||||
Dictionary* _dictionary; // The loaded InstanceKlasses, including initiated by this class loader
|
||||
|
||||
// These method IDs are created for the class loader and set to NULL when the
|
||||
// class loader is unloaded. They are rarely freed, only for redefine classes
|
||||
@ -269,6 +289,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
// Allocate out of this class loader data
|
||||
MetaWord* allocate(size_t size);
|
||||
|
||||
Dictionary* create_dictionary();
|
||||
public:
|
||||
|
||||
bool is_alive(BoolObjectClosure* is_alive_closure) const;
|
||||
@ -324,17 +345,20 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
void inc_keep_alive();
|
||||
void dec_keep_alive();
|
||||
|
||||
inline unsigned int identity_hash() const;
|
||||
inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); }
|
||||
|
||||
// Used when tracing from klasses.
|
||||
void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
|
||||
|
||||
void classes_do(KlassClosure* klass_closure);
|
||||
Klass* klasses() { return _klasses; }
|
||||
|
||||
JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; }
|
||||
void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; }
|
||||
|
||||
void print_value() { print_value_on(tty); }
|
||||
void print() { print_on(tty); }
|
||||
void print_on(outputStream* out) const;
|
||||
void print_value() { print_value_on(tty); }
|
||||
void print_value_on(outputStream* out) const;
|
||||
void dump(outputStream * const out) PRODUCT_RETURN;
|
||||
void verify();
|
||||
@ -352,6 +376,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
ModuleEntryTable* modules();
|
||||
bool modules_defined() { return (_modules != NULL); }
|
||||
|
||||
// Loaded class dictionary
|
||||
Dictionary* dictionary() const { return _dictionary; }
|
||||
|
||||
void add_to_deallocate_list(Metadata* m);
|
||||
|
||||
static ClassLoaderData* class_loader_data(oop loader);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,10 +26,6 @@
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
|
||||
unsigned int ClassLoaderData::identity_hash() const {
|
||||
return _class_loader == NULL ? 0 : _class_loader->identity_hash();
|
||||
}
|
||||
|
||||
inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
|
||||
if (loader == NULL) {
|
||||
return ClassLoaderData::the_null_class_loader_data();
|
||||
|
||||
@ -34,12 +34,10 @@
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/orderAccess.inline.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
|
||||
DictionaryEntry* Dictionary::_current_class_entry = NULL;
|
||||
int Dictionary::_current_class_index = 0;
|
||||
|
||||
size_t Dictionary::entry_size() {
|
||||
if (DumpSharedSpaces) {
|
||||
return SystemDictionaryShared::dictionary_entry_size();
|
||||
@ -48,30 +46,33 @@ size_t Dictionary::entry_size() {
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(int table_size)
|
||||
: TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
|
||||
_current_class_index = 0;
|
||||
_current_class_entry = NULL;
|
||||
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||
Dictionary::Dictionary(ClassLoaderData* loader_data, int table_size)
|
||||
: _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
|
||||
};
|
||||
|
||||
|
||||
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
|
||||
Dictionary::Dictionary(ClassLoaderData* loader_data,
|
||||
int table_size, HashtableBucket<mtClass>* t,
|
||||
int number_of_entries)
|
||||
: TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
|
||||
_current_class_index = 0;
|
||||
_current_class_entry = NULL;
|
||||
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||
: _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
|
||||
};
|
||||
|
||||
ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) {
|
||||
return _pd_cache_table->get(protection_domain);
|
||||
Dictionary::~Dictionary() {
|
||||
DictionaryEntry* probe = NULL;
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
|
||||
probe = *p;
|
||||
*p = probe->next();
|
||||
free_entry(probe);
|
||||
}
|
||||
}
|
||||
assert(number_of_entries() == 0, "should have removed all entries");
|
||||
assert(new_entry_free_list() == NULL, "entry present on Dictionary's free list");
|
||||
free_buckets();
|
||||
}
|
||||
|
||||
DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass,
|
||||
ClassLoaderData* loader_data) {
|
||||
DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
|
||||
entry->set_loader_data(loader_data);
|
||||
DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) {
|
||||
DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::allocate_new_entry(hash, klass);
|
||||
entry->set_pd_set(NULL);
|
||||
assert(klass->is_instance_klass(), "Must be");
|
||||
if (DumpSharedSpaces) {
|
||||
@ -88,13 +89,15 @@ void Dictionary::free_entry(DictionaryEntry* entry) {
|
||||
entry->set_pd_set(to_delete->next());
|
||||
delete to_delete;
|
||||
}
|
||||
Hashtable<InstanceKlass*, mtClass>::free_entry(entry);
|
||||
// Unlink from the Hashtable prior to freeing
|
||||
unlink_entry(entry);
|
||||
FREE_C_HEAP_ARRAY(char, entry);
|
||||
}
|
||||
|
||||
|
||||
bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||
#ifdef ASSERT
|
||||
if (protection_domain == klass()->protection_domain()) {
|
||||
if (protection_domain == instance_klass()->protection_domain()) {
|
||||
// Ensure this doesn't show up in the pd_set (invariant)
|
||||
bool in_pd_set = false;
|
||||
for (ProtectionDomainEntry* current = _pd_set;
|
||||
@ -112,7 +115,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||
}
|
||||
#endif /* ASSERT */
|
||||
|
||||
if (protection_domain == klass()->protection_domain()) {
|
||||
if (protection_domain == instance_klass()->protection_domain()) {
|
||||
// Succeeds trivially
|
||||
return true;
|
||||
}
|
||||
@ -129,7 +132,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||
void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
if (!contains_protection_domain(protection_domain())) {
|
||||
ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
|
||||
ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
|
||||
ProtectionDomainEntry* new_head =
|
||||
new ProtectionDomainEntry(entry, _pd_set);
|
||||
// Warning: Preserve store ordering. The SystemDictionary is read
|
||||
@ -149,86 +152,43 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_
|
||||
void Dictionary::do_unloading() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
|
||||
// Remove unloadable entries and classes from system dictionary
|
||||
// The NULL class loader doesn't initiate loading classes from other class loaders
|
||||
if (loader_data() == ClassLoaderData::the_null_class_loader_data()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove unloaded entries and classes from this dictionary
|
||||
DictionaryEntry* probe = NULL;
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
|
||||
probe = *p;
|
||||
Klass* e = probe->klass();
|
||||
ClassLoaderData* loader_data = probe->loader_data();
|
||||
InstanceKlass* ik = probe->instance_klass();
|
||||
ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
|
||||
|
||||
InstanceKlass* ik = InstanceKlass::cast(e);
|
||||
|
||||
// Only unload classes that are not strongly reachable
|
||||
if (!is_strongly_reachable(loader_data, e)) {
|
||||
// Entry was not visited in phase1 (negated test from phase1)
|
||||
assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
|
||||
ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
|
||||
|
||||
// Do we need to delete this system dictionary entry?
|
||||
bool purge_entry = false;
|
||||
|
||||
// Do we need to delete this system dictionary entry?
|
||||
if (loader_data->is_unloading()) {
|
||||
// If the loader is not live this entry should always be
|
||||
// removed (will never be looked up again).
|
||||
purge_entry = true;
|
||||
} else {
|
||||
// The loader in this entry is alive. If the klass is dead,
|
||||
// (determined by checking the defining class loader)
|
||||
// the loader must be an initiating loader (rather than the
|
||||
// defining loader). Remove this entry.
|
||||
if (k_def_class_loader_data->is_unloading()) {
|
||||
// If we get here, the class_loader_data must not be the defining
|
||||
// loader, it must be an initiating one.
|
||||
assert(k_def_class_loader_data != loader_data,
|
||||
"cannot have live defining loader and unreachable klass");
|
||||
// Loader is live, but class and its defining loader are dead.
|
||||
// Remove the entry. The class is going away.
|
||||
purge_entry = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (purge_entry) {
|
||||
*p = probe->next();
|
||||
if (probe == _current_class_entry) {
|
||||
_current_class_entry = NULL;
|
||||
}
|
||||
free_entry(probe);
|
||||
continue;
|
||||
}
|
||||
// If the klass that this loader initiated is dead,
|
||||
// (determined by checking the defining class loader)
|
||||
// remove this entry.
|
||||
if (k_def_class_loader_data->is_unloading()) {
|
||||
assert(k_def_class_loader_data != loader_data(),
|
||||
"cannot have live defining loader and unreachable klass");
|
||||
*p = probe->next();
|
||||
free_entry(probe);
|
||||
continue;
|
||||
}
|
||||
p = probe->next_addr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||
// Do strong roots marking if the closures are the same.
|
||||
if (strong == weak || !ClassUnloading) {
|
||||
// Only the protection domain oops contain references into the heap. Iterate
|
||||
// over all of them.
|
||||
_pd_cache_table->oops_do(strong);
|
||||
} else {
|
||||
if (weak != NULL) {
|
||||
_pd_cache_table->oops_do(weak);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dictionary::remove_classes_in_error_state() {
|
||||
assert(DumpSharedSpaces, "supported only when dumping");
|
||||
DictionaryEntry* probe = NULL;
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
|
||||
probe = *p;
|
||||
InstanceKlass* ik = InstanceKlass::cast(probe->klass());
|
||||
InstanceKlass* ik = probe->instance_klass();
|
||||
if (ik->is_in_error_state()) { // purge this entry
|
||||
*p = probe->next();
|
||||
if (probe == _current_class_entry) {
|
||||
_current_class_entry = NULL;
|
||||
}
|
||||
free_entry(probe);
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
|
||||
@ -241,13 +201,13 @@ void Dictionary::remove_classes_in_error_state() {
|
||||
}
|
||||
|
||||
// Just the classes from defining class loaders
|
||||
void Dictionary::classes_do(void f(Klass*)) {
|
||||
void Dictionary::classes_do(void f(InstanceKlass*)) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
Klass* k = probe->klass();
|
||||
if (probe->loader_data() == k->class_loader_data()) {
|
||||
InstanceKlass* k = probe->instance_klass();
|
||||
if (loader_data() == k->class_loader_data()) {
|
||||
f(k);
|
||||
}
|
||||
}
|
||||
@ -256,78 +216,50 @@ void Dictionary::classes_do(void f(Klass*)) {
|
||||
|
||||
// Added for initialize_itable_for_klass to handle exceptions
|
||||
// Just the classes from defining class loaders
|
||||
void Dictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
|
||||
void Dictionary::classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
Klass* k = probe->klass();
|
||||
if (probe->loader_data() == k->class_loader_data()) {
|
||||
InstanceKlass* k = probe->instance_klass();
|
||||
if (loader_data() == k->class_loader_data()) {
|
||||
f(k, CHECK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All classes, and their class loaders
|
||||
// Don't iterate over placeholders
|
||||
void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
|
||||
// All classes, and their class loaders, including initiating class loaders
|
||||
void Dictionary::all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
Klass* k = probe->klass();
|
||||
f(k, probe->loader_data());
|
||||
InstanceKlass* k = probe->instance_klass();
|
||||
f(k, loader_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Dictionary::oops_do(OopClosure* f) {
|
||||
// Only the protection domain oops contain references into the heap. Iterate
|
||||
// over all of them.
|
||||
_pd_cache_table->oops_do(f);
|
||||
}
|
||||
|
||||
void Dictionary::unlink(BoolObjectClosure* is_alive) {
|
||||
// Only the protection domain cache table may contain references to the heap
|
||||
// that need to be unlinked.
|
||||
_pd_cache_table->unlink(is_alive);
|
||||
}
|
||||
|
||||
InstanceKlass* Dictionary::try_get_next_class() {
|
||||
while (true) {
|
||||
if (_current_class_entry != NULL) {
|
||||
InstanceKlass* k = _current_class_entry->klass();
|
||||
_current_class_entry = _current_class_entry->next();
|
||||
return k;
|
||||
}
|
||||
_current_class_index = (_current_class_index + 1) % table_size();
|
||||
_current_class_entry = bucket(_current_class_index);
|
||||
}
|
||||
// never reached
|
||||
}
|
||||
|
||||
// Add a loaded class to the system dictionary.
|
||||
// Add a loaded class to the dictionary.
|
||||
// Readers of the SystemDictionary aren't always locked, so _buckets
|
||||
// is volatile. The store of the next field in the constructor is
|
||||
// also cast to volatile; we do this to ensure store order is maintained
|
||||
// by the compilers.
|
||||
|
||||
void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
|
||||
void Dictionary::add_klass(int index, unsigned int hash, Symbol* class_name,
|
||||
InstanceKlass* obj) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert(obj != NULL, "adding NULL obj");
|
||||
assert(obj->name() == class_name, "sanity check on name");
|
||||
assert(loader_data != NULL, "Must be non-NULL");
|
||||
|
||||
unsigned int hash = compute_hash(class_name, loader_data);
|
||||
int index = hash_to_index(hash);
|
||||
DictionaryEntry* entry = new_entry(hash, obj, loader_data);
|
||||
DictionaryEntry* entry = new_entry(hash, obj);
|
||||
add_entry(index, entry);
|
||||
}
|
||||
|
||||
|
||||
// This routine does not lock the system dictionary.
|
||||
// This routine does not lock the dictionary.
|
||||
//
|
||||
// Since readers don't hold a lock, we must make sure that system
|
||||
// dictionary entries are only removed at a safepoint (when only one
|
||||
@ -337,13 +269,14 @@ void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
|
||||
// Callers should be aware that an entry could be added just after
|
||||
// _buckets[index] is read here, so the caller will not see the new entry.
|
||||
DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
|
||||
Symbol* class_name,
|
||||
ClassLoaderData* loader_data) {
|
||||
Symbol* class_name) {
|
||||
for (DictionaryEntry* entry = bucket(index);
|
||||
entry != NULL;
|
||||
entry = entry->next()) {
|
||||
if (entry->hash() == hash && entry->equals(class_name, loader_data)) {
|
||||
return entry;
|
||||
if (entry->hash() == hash && entry->equals(class_name)) {
|
||||
if (!DumpSharedSpaces || SystemDictionaryShared::is_builtin(entry)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -351,10 +284,10 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
|
||||
|
||||
|
||||
InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name,
|
||||
ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
||||
DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
|
||||
Handle protection_domain) {
|
||||
DictionaryEntry* entry = get_entry(index, hash, name);
|
||||
if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
|
||||
return entry->klass();
|
||||
return entry->instance_klass();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@ -362,12 +295,12 @@ InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name,
|
||||
|
||||
|
||||
InstanceKlass* Dictionary::find_class(int index, unsigned int hash,
|
||||
Symbol* name, ClassLoaderData* loader_data) {
|
||||
Symbol* name) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert (index == index_for(name, loader_data), "incorrect index?");
|
||||
assert (index == index_for(name), "incorrect index?");
|
||||
|
||||
DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
|
||||
return (entry != NULL) ? entry->klass() : NULL;
|
||||
DictionaryEntry* entry = get_entry(index, hash, name);
|
||||
return (entry != NULL) ? entry->instance_klass() : NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -376,19 +309,19 @@ InstanceKlass* Dictionary::find_class(int index, unsigned int hash,
|
||||
|
||||
InstanceKlass* Dictionary::find_shared_class(int index, unsigned int hash,
|
||||
Symbol* name) {
|
||||
assert (index == index_for(name, NULL), "incorrect index?");
|
||||
assert (index == index_for(name), "incorrect index?");
|
||||
|
||||
DictionaryEntry* entry = get_entry(index, hash, name, NULL);
|
||||
return (entry != NULL) ? entry->klass() : NULL;
|
||||
DictionaryEntry* entry = get_entry(index, hash, name);
|
||||
return (entry != NULL) ? entry->instance_klass() : NULL;
|
||||
}
|
||||
|
||||
|
||||
void Dictionary::add_protection_domain(int index, unsigned int hash,
|
||||
InstanceKlass* klass,
|
||||
ClassLoaderData* loader_data, Handle protection_domain,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
Symbol* klass_name = klass->name();
|
||||
DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data);
|
||||
DictionaryEntry* entry = get_entry(index, hash, klass_name);
|
||||
|
||||
assert(entry != NULL,"entry must be present, we just created it");
|
||||
assert(protection_domain() != NULL,
|
||||
@ -403,9 +336,8 @@ void Dictionary::add_protection_domain(int index, unsigned int hash,
|
||||
|
||||
bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
|
||||
Symbol* name,
|
||||
ClassLoaderData* loader_data,
|
||||
Handle protection_domain) {
|
||||
DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
|
||||
DictionaryEntry* entry = get_entry(index, hash, name);
|
||||
return entry->is_valid_protection_domain(protection_domain);
|
||||
}
|
||||
|
||||
@ -432,13 +364,12 @@ void Dictionary::reorder_dictionary() {
|
||||
DictionaryEntry* p = master_list;
|
||||
master_list = master_list->next();
|
||||
p->set_next(NULL);
|
||||
Symbol* class_name = p->klass()->name();
|
||||
Symbol* class_name = p->instance_klass()->name();
|
||||
// Since the null class loader data isn't copied to the CDS archive,
|
||||
// compute the hash with NULL for loader data.
|
||||
unsigned int hash = compute_hash(class_name, NULL);
|
||||
unsigned int hash = compute_hash(class_name);
|
||||
int index = hash_to_index(hash);
|
||||
p->set_hash(hash);
|
||||
p->set_loader_data(NULL); // loader_data isn't copied to CDS
|
||||
p->set_next(bucket(index));
|
||||
set_entry(index, p);
|
||||
}
|
||||
@ -507,8 +438,9 @@ void SymbolPropertyTable::methods_do(void f(Method*)) {
|
||||
void Dictionary::print(bool details) {
|
||||
ResourceMark rm;
|
||||
|
||||
assert(loader_data() != NULL, "loader data should not be null");
|
||||
if (details) {
|
||||
tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
|
||||
tty->print_cr("Java dictionary (table_size=%d, classes=%d)",
|
||||
table_size(), number_of_entries());
|
||||
tty->print_cr("^ indicates that initiating loader is different from "
|
||||
"defining loader");
|
||||
@ -518,10 +450,9 @@ void Dictionary::print(bool details) {
|
||||
for (DictionaryEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
Klass* e = probe->klass();
|
||||
ClassLoaderData* loader_data = probe->loader_data();
|
||||
Klass* e = probe->instance_klass();
|
||||
bool is_defining_class =
|
||||
(loader_data == e->class_loader_data());
|
||||
(loader_data() == e->class_loader_data());
|
||||
if (details) {
|
||||
tty->print("%4d: ", index);
|
||||
}
|
||||
@ -530,41 +461,36 @@ void Dictionary::print(bool details) {
|
||||
|
||||
if (details) {
|
||||
tty->print(", loader ");
|
||||
if (loader_data != NULL) {
|
||||
loader_data->print_value();
|
||||
} else {
|
||||
tty->print("NULL");
|
||||
}
|
||||
e->class_loader_data()->print_value();
|
||||
}
|
||||
tty->cr();
|
||||
}
|
||||
}
|
||||
|
||||
if (details) {
|
||||
tty->cr();
|
||||
_pd_cache_table->print();
|
||||
}
|
||||
tty->cr();
|
||||
}
|
||||
|
||||
void DictionaryEntry::verify() {
|
||||
Klass* e = klass();
|
||||
ClassLoaderData* cld = loader_data();
|
||||
Klass* e = instance_klass();
|
||||
guarantee(e->is_instance_klass(),
|
||||
"Verify of system dictionary failed");
|
||||
"Verify of dictionary failed");
|
||||
e->verify();
|
||||
verify_protection_domain_set();
|
||||
}
|
||||
|
||||
void Dictionary::verify() {
|
||||
guarantee(number_of_entries() >= 0, "Verify of dictionary failed");
|
||||
|
||||
ClassLoaderData* cld = loader_data();
|
||||
// class loader must be present; a null class loader is the
|
||||
// boostrap loader
|
||||
guarantee(cld != NULL || DumpSharedSpaces ||
|
||||
cld->class_loader() == NULL ||
|
||||
cld->class_loader()->is_instance(),
|
||||
"checking type of class_loader");
|
||||
e->verify();
|
||||
verify_protection_domain_set();
|
||||
}
|
||||
|
||||
void Dictionary::verify() {
|
||||
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
|
||||
verify_table<DictionaryEntry>("System Dictionary");
|
||||
_pd_cache_table->verify();
|
||||
|
||||
ResourceMark rm;
|
||||
stringStream tempst;
|
||||
tempst.print("System Dictionary for %s", cld->loader_name());
|
||||
verify_table<DictionaryEntry>(tempst.as_string());
|
||||
}
|
||||
|
||||
|
||||
@ -36,21 +36,16 @@ class DictionaryEntry;
|
||||
class BoolObjectClosure;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// The data structure for the system dictionary (and the shared system
|
||||
// The data structure for the class loader data dictionaries (and the shared system
|
||||
// dictionary).
|
||||
|
||||
class Dictionary : public TwoOopHashtable<InstanceKlass*, mtClass> {
|
||||
class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
|
||||
friend class VMStructs;
|
||||
private:
|
||||
// current iteration index.
|
||||
static int _current_class_index;
|
||||
// pointer to the current hash table entry.
|
||||
static DictionaryEntry* _current_class_entry;
|
||||
|
||||
ProtectionDomainCacheTable* _pd_cache_table;
|
||||
ClassLoaderData* _loader_data; // backpointer to owning loader
|
||||
ClassLoaderData* loader_data() const { return _loader_data; }
|
||||
|
||||
DictionaryEntry* get_entry(int index, unsigned int hash,
|
||||
Symbol* name, ClassLoaderData* loader_data);
|
||||
DictionaryEntry* get_entry(int index, unsigned int hash, Symbol* name);
|
||||
|
||||
protected:
|
||||
DictionaryEntry* bucket(int i) const {
|
||||
@ -66,61 +61,48 @@ protected:
|
||||
Hashtable<InstanceKlass*, mtClass>::add_entry(index, (HashtableEntry<InstanceKlass*, mtClass>*)new_entry);
|
||||
}
|
||||
|
||||
static size_t entry_size();
|
||||
public:
|
||||
Dictionary(int table_size);
|
||||
Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
|
||||
|
||||
DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass, ClassLoaderData* loader_data);
|
||||
|
||||
void free_entry(DictionaryEntry* entry);
|
||||
|
||||
void add_klass(Symbol* class_name, ClassLoaderData* loader_data, InstanceKlass* obj);
|
||||
static size_t entry_size();
|
||||
public:
|
||||
Dictionary(ClassLoaderData* loader_data, int table_size);
|
||||
Dictionary(ClassLoaderData* loader_data, int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
|
||||
~Dictionary();
|
||||
|
||||
InstanceKlass* find_class(int index, unsigned int hash,
|
||||
Symbol* name, ClassLoaderData* loader_data);
|
||||
DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass);
|
||||
|
||||
void add_klass(int index, unsigned int hash, Symbol* class_name, InstanceKlass* obj);
|
||||
|
||||
InstanceKlass* find_class(int index, unsigned int hash, Symbol* name);
|
||||
|
||||
InstanceKlass* find_shared_class(int index, unsigned int hash, Symbol* name);
|
||||
|
||||
// Compiler support
|
||||
InstanceKlass* try_get_next_class();
|
||||
|
||||
// GC support
|
||||
void oops_do(OopClosure* f);
|
||||
void roots_oops_do(OopClosure* strong, OopClosure* weak);
|
||||
|
||||
void classes_do(void f(Klass*));
|
||||
void classes_do(void f(Klass*, TRAPS), TRAPS);
|
||||
void classes_do(void f(Klass*, ClassLoaderData*));
|
||||
void classes_do(void f(InstanceKlass*));
|
||||
void classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
|
||||
void all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
|
||||
|
||||
void unlink(BoolObjectClosure* is_alive);
|
||||
void remove_classes_in_error_state();
|
||||
|
||||
// Classes loaded by the bootstrap loader are always strongly reachable.
|
||||
// If we're not doing class unloading, all classes are strongly reachable.
|
||||
static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) {
|
||||
assert (klass != NULL, "should have non-null klass");
|
||||
return (loader_data->is_the_null_class_loader_data() || !ClassUnloading);
|
||||
}
|
||||
|
||||
// Unload (that is, break root links to) all unmarked classes and loaders.
|
||||
// Unload classes whose defining loaders are unloaded
|
||||
void do_unloading();
|
||||
|
||||
// Protection domains
|
||||
InstanceKlass* find(int index, unsigned int hash, Symbol* name,
|
||||
ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
|
||||
InstanceKlass* find(int index, unsigned int hash, Symbol* name, Handle protection_domain);
|
||||
bool is_valid_protection_domain(int index, unsigned int hash,
|
||||
Symbol* name, ClassLoaderData* loader_data,
|
||||
Symbol* name,
|
||||
Handle protection_domain);
|
||||
void add_protection_domain(int index, unsigned int hash,
|
||||
InstanceKlass* klass, ClassLoaderData* loader_data,
|
||||
InstanceKlass* klass,
|
||||
Handle protection_domain, TRAPS);
|
||||
|
||||
// Sharing support
|
||||
void reorder_dictionary();
|
||||
|
||||
ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
|
||||
|
||||
void print(bool details = true);
|
||||
#ifdef ASSERT
|
||||
void printPerformanceInfoDetails();
|
||||
@ -128,14 +110,14 @@ public:
|
||||
void verify();
|
||||
};
|
||||
|
||||
// An entry in the system dictionary, this describes a class as
|
||||
// { InstanceKlass*, loader, protection_domain }.
|
||||
// An entry in the class loader data dictionaries, this describes a class as
|
||||
// { InstanceKlass*, protection_domain }.
|
||||
|
||||
class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
friend class VMStructs;
|
||||
private:
|
||||
// Contains the set of approved protection domains that can access
|
||||
// this system dictionary entry.
|
||||
// this dictionary entry.
|
||||
//
|
||||
// This protection domain set is a set of tuples:
|
||||
//
|
||||
@ -155,7 +137,6 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
// ClassLoader.checkPackageAccess().
|
||||
//
|
||||
ProtectionDomainEntry* _pd_set;
|
||||
ClassLoaderData* _loader_data;
|
||||
|
||||
public:
|
||||
// Tells whether a protection is in the approved set.
|
||||
@ -163,7 +144,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
// Adds a protection domain to the approved set.
|
||||
void add_protection_domain(Dictionary* dict, Handle protection_domain);
|
||||
|
||||
InstanceKlass* klass() const { return (InstanceKlass*)literal(); }
|
||||
InstanceKlass* instance_klass() const { return literal(); }
|
||||
|
||||
DictionaryEntry* next() const {
|
||||
return (DictionaryEntry*)HashtableEntry<InstanceKlass*, mtClass>::next();
|
||||
@ -173,13 +154,10 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
return (DictionaryEntry**)HashtableEntry<InstanceKlass*, mtClass>::next_addr();
|
||||
}
|
||||
|
||||
ClassLoaderData* loader_data() const { return _loader_data; }
|
||||
void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; }
|
||||
|
||||
ProtectionDomainEntry* pd_set() const { return _pd_set; }
|
||||
void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; }
|
||||
|
||||
// Tells whether the initiating class' protection can access the this _klass
|
||||
// Tells whether the initiating class' protection domain can access the klass in this entry
|
||||
bool is_valid_protection_domain(Handle protection_domain) {
|
||||
if (!ProtectionDomainVerification) return true;
|
||||
if (!SystemDictionary::has_checkPackageAccess()) return true;
|
||||
@ -197,9 +175,9 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
}
|
||||
}
|
||||
|
||||
bool equals(const Symbol* class_name, ClassLoaderData* loader_data) const {
|
||||
bool equals(const Symbol* class_name) const {
|
||||
InstanceKlass* klass = (InstanceKlass*)literal();
|
||||
return (klass->name() == class_name && _loader_data == loader_data);
|
||||
return (klass->name() == class_name);
|
||||
}
|
||||
|
||||
void print_count(outputStream *st) {
|
||||
|
||||
@ -1082,8 +1082,8 @@ const char* java_lang_Class::as_external_name(oop java_class) {
|
||||
return name;
|
||||
}
|
||||
|
||||
Klass* java_lang_Class::array_klass(oop java_class) {
|
||||
Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
|
||||
Klass* java_lang_Class::array_klass_acquire(oop java_class) {
|
||||
Klass* k = ((Klass*)java_class->metadata_field_acquire(_array_klass_offset));
|
||||
assert(k == NULL || k->is_klass() && k->is_array_klass(), "should be array klass");
|
||||
return k;
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ class java_lang_Class : AllStatic {
|
||||
static BasicType primitive_type(oop java_class);
|
||||
static oop primitive_mirror(BasicType t);
|
||||
// JVM_NewArray support
|
||||
static Klass* array_klass(oop java_class);
|
||||
static Klass* array_klass_acquire(oop java_class);
|
||||
static void release_set_array_klass(oop java_class, Klass* klass);
|
||||
// compiler support for class operations
|
||||
static int klass_offset_in_bytes() { return _klass_offset; }
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/loaderConstraints.hpp"
|
||||
#include "logging/log.hpp"
|
||||
@ -36,8 +37,8 @@ void LoaderConstraintEntry::set_loader(int i, oop p) {
|
||||
set_loader_data(i, ClassLoaderData::class_loader_data(p));
|
||||
}
|
||||
|
||||
LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
|
||||
: Hashtable<InstanceKlass*, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
|
||||
LoaderConstraintTable::LoaderConstraintTable(int table_size)
|
||||
: Hashtable<InstanceKlass*, mtClass>(table_size, sizeof(LoaderConstraintEntry)) {};
|
||||
|
||||
|
||||
LoaderConstraintEntry* LoaderConstraintTable::new_entry(
|
||||
@ -315,7 +316,7 @@ InstanceKlass* LoaderConstraintTable::find_constrained_klass(Symbol* name,
|
||||
LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
|
||||
if (p != NULL && p->klass() != NULL) {
|
||||
assert(p->klass()->is_instance_klass(), "sanity");
|
||||
if (p->klass()->is_loaded()) {
|
||||
if (!p->klass()->is_loaded()) {
|
||||
// Only return fully loaded classes. Classes found through the
|
||||
// constraints might still be in the process of loading.
|
||||
return NULL;
|
||||
@ -425,10 +426,9 @@ void LoaderConstraintTable::merge_loader_constraints(
|
||||
}
|
||||
|
||||
|
||||
void LoaderConstraintTable::verify(Dictionary* dictionary,
|
||||
PlaceholderTable* placeholders) {
|
||||
void LoaderConstraintTable::verify(PlaceholderTable* placeholders) {
|
||||
Thread *thread = Thread::current();
|
||||
for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
|
||||
for (int cindex = 0; cindex < table_size(); cindex++) {
|
||||
for (LoaderConstraintEntry* probe = bucket(cindex);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
@ -437,17 +437,18 @@ void LoaderConstraintTable::verify(Dictionary* dictionary,
|
||||
guarantee(ik->name() == probe->name(), "name should match");
|
||||
Symbol* name = ik->name();
|
||||
ClassLoaderData* loader_data = ik->class_loader_data();
|
||||
unsigned int d_hash = dictionary->compute_hash(name, loader_data);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
InstanceKlass* k = dictionary->find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* k = dictionary->find_class(d_index, d_hash, name);
|
||||
if (k != NULL) {
|
||||
// We found the class in the system dictionary, so we should
|
||||
// We found the class in the dictionary, so we should
|
||||
// make sure that the Klass* matches what we already have.
|
||||
guarantee(k == probe->klass(), "klass should be in dictionary");
|
||||
} else {
|
||||
// If we don't find the class in the system dictionary, it
|
||||
// If we don't find the class in the dictionary, it
|
||||
// has to be in the placeholders table.
|
||||
unsigned int p_hash = placeholders->compute_hash(name, loader_data);
|
||||
unsigned int p_hash = placeholders->compute_hash(name);
|
||||
int p_index = placeholders->hash_to_index(p_hash);
|
||||
PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
|
||||
name, loader_data);
|
||||
@ -471,8 +472,9 @@ void LoaderConstraintTable::verify(Dictionary* dictionary,
|
||||
void LoaderConstraintTable::print() {
|
||||
ResourceMark rm;
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
|
||||
for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
|
||||
tty->print_cr("Java loader constraints (entries=%d, constraints=%d)",
|
||||
table_size(), number_of_entries());
|
||||
for (int cindex = 0; cindex < table_size(); cindex++) {
|
||||
for (LoaderConstraintEntry* probe = bucket(cindex);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
|
||||
@ -25,28 +25,22 @@
|
||||
#ifndef SHARE_VM_CLASSFILE_LOADERCONSTRAINTS_HPP
|
||||
#define SHARE_VM_CLASSFILE_LOADERCONSTRAINTS_HPP
|
||||
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/placeholders.hpp"
|
||||
#include "utilities/hashtable.hpp"
|
||||
|
||||
class ClassLoaderData;
|
||||
class LoaderConstraintEntry;
|
||||
class Symbol;
|
||||
|
||||
class LoaderConstraintTable : public Hashtable<InstanceKlass*, mtClass> {
|
||||
friend class VMStructs;
|
||||
|
||||
private:
|
||||
|
||||
enum Constants {
|
||||
_loader_constraint_size = 107, // number of entries in constraint table
|
||||
_nof_buckets = 1009 // number of buckets in hash table
|
||||
};
|
||||
|
||||
LoaderConstraintEntry** find_loader_constraint(Symbol* name,
|
||||
Handle loader);
|
||||
|
||||
public:
|
||||
|
||||
LoaderConstraintTable(int nof_buckets);
|
||||
LoaderConstraintTable(int table_size);
|
||||
|
||||
LoaderConstraintEntry* new_entry(unsigned int hash, Symbol* name,
|
||||
InstanceKlass* klass, int num_loaders,
|
||||
@ -84,14 +78,13 @@ public:
|
||||
|
||||
void purge_loader_constraints();
|
||||
|
||||
void verify(Dictionary* dictionary, PlaceholderTable* placeholders);
|
||||
void verify(PlaceholderTable* placeholders);
|
||||
#ifndef PRODUCT
|
||||
void print();
|
||||
#endif
|
||||
};
|
||||
|
||||
class LoaderConstraintEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||
friend class VMStructs;
|
||||
private:
|
||||
Symbol* _name; // class name
|
||||
int _num_loaders;
|
||||
|
||||
@ -339,12 +339,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle
|
||||
Symbol* version, Symbol* location,
|
||||
ClassLoaderData* loader_data) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule);
|
||||
|
||||
// Initialize everything BasicHashtable would
|
||||
entry->set_next(NULL);
|
||||
entry->set_hash(hash);
|
||||
entry->set_literal(name);
|
||||
ModuleEntry* entry = (ModuleEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
|
||||
|
||||
// Initialize fields specific to a ModuleEntry
|
||||
entry->init();
|
||||
|
||||
@ -198,12 +198,7 @@ PackageEntryTable::~PackageEntryTable() {
|
||||
|
||||
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
|
||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||
PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule);
|
||||
|
||||
// Initialize everything BasicHashtable would
|
||||
entry->set_next(NULL);
|
||||
entry->set_hash(hash);
|
||||
entry->set_literal(name);
|
||||
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
|
||||
|
||||
TRACE_INIT_ID(entry);
|
||||
|
||||
|
||||
@ -172,7 +172,7 @@ void PlaceholderTable::find_and_remove(int index, unsigned int hash,
|
||||
}
|
||||
|
||||
PlaceholderTable::PlaceholderTable(int table_size)
|
||||
: TwoOopHashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
|
||||
: Hashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
@ -34,8 +34,7 @@ class PlaceholderEntry;
|
||||
// being loaded, as well as arrays of primitives.
|
||||
//
|
||||
|
||||
class PlaceholderTable : public TwoOopHashtable<Symbol*, mtClass> {
|
||||
friend class VMStructs;
|
||||
class PlaceholderTable : public Hashtable<Symbol*, mtClass> {
|
||||
|
||||
public:
|
||||
PlaceholderTable(int table_size);
|
||||
@ -149,8 +148,6 @@ public:
|
||||
// The system dictionary is the only user of this class.
|
||||
|
||||
class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {
|
||||
friend class VMStructs;
|
||||
|
||||
|
||||
private:
|
||||
ClassLoaderData* _loader_data; // initiating loader
|
||||
|
||||
@ -88,14 +88,14 @@ void ProtectionDomainCacheTable::print() {
|
||||
for (ProtectionDomainCacheEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
tty->print("%4d: ", index);
|
||||
probe->print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheEntry::print() {
|
||||
tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " next " PTR_FORMAT,
|
||||
p2i(this), p2i(literal()), p2i(next()));
|
||||
tty->print_cr("protection_domain: " PTR_FORMAT, p2i(literal()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
// Dictionary entry pd_set point to entries in this hashtable. Please refer
|
||||
// to dictionary.hpp pd_set for more information about how protection domain entries
|
||||
// are used.
|
||||
// This table is walked during GC, rather than the entire system dictionary
|
||||
// This table is walked during GC, rather than the class loader data graph dictionaries.
|
||||
class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
|
||||
friend class VMStructs;
|
||||
public:
|
||||
@ -55,7 +55,7 @@ class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
|
||||
void verify();
|
||||
};
|
||||
|
||||
// The ProtectionDomainCacheTable contains all protection domain oops. The system
|
||||
// The ProtectionDomainCacheTable contains all protection domain oops. The
|
||||
// dictionary entries reference its entries instead of having references to oops
|
||||
// directly.
|
||||
// This is used to speed up system dictionary iteration: the oops in the
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "classfile/loaderConstraints.hpp"
|
||||
#include "classfile/packageEntry.hpp"
|
||||
#include "classfile/placeholders.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/resolutionErrors.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
@ -88,19 +89,14 @@
|
||||
#include "trace/tracing.hpp"
|
||||
#endif
|
||||
|
||||
Dictionary* SystemDictionary::_dictionary = NULL;
|
||||
PlaceholderTable* SystemDictionary::_placeholders = NULL;
|
||||
Dictionary* SystemDictionary::_shared_dictionary = NULL;
|
||||
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
|
||||
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
||||
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
|
||||
|
||||
ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL;
|
||||
|
||||
int SystemDictionary::_number_of_modifications = 0;
|
||||
int SystemDictionary::_sdgeneration = 0;
|
||||
const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,5051,10103,
|
||||
20201,40423,99991};
|
||||
|
||||
oop SystemDictionary::_system_loader_lock_obj = NULL;
|
||||
|
||||
InstanceKlass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
|
||||
@ -116,6 +112,10 @@ bool SystemDictionary::_has_checkPackageAccess = false;
|
||||
// lazily initialized klass variables
|
||||
InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
|
||||
|
||||
// Default ProtectionDomainCacheSize value
|
||||
|
||||
const int defaultProtectionDomainCacheSize = 1009;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Java-level SystemLoader
|
||||
@ -343,32 +343,32 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
// Double-check, if child class is already loaded, just return super-class,interface
|
||||
// Don't add a placedholder if already loaded, i.e. already in system dictionary
|
||||
// Don't add a placedholder if already loaded, i.e. already in appropriate class loader
|
||||
// dictionary.
|
||||
// Make sure there's a placeholder for the *child* before resolving.
|
||||
// Used as a claim that this thread is currently loading superclass/classloader
|
||||
// Used here for ClassCircularity checks and also for heap verification
|
||||
// (every InstanceKlass in the heap needs to be in the system dictionary
|
||||
// or have a placeholder).
|
||||
// Must check ClassCircularity before checking if super class is already loaded
|
||||
// (every InstanceKlass needs to be in its class loader dictionary or have a placeholder).
|
||||
// Must check ClassCircularity before checking if super class is already loaded.
|
||||
//
|
||||
// We might not already have a placeholder if this child_name was
|
||||
// first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass);
|
||||
// the name of the class might not be known until the stream is actually
|
||||
// parsed.
|
||||
// Bugs 4643874, 4715493
|
||||
// compute_hash can have a safepoint
|
||||
|
||||
ClassLoaderData* loader_data = class_loader_data(class_loader);
|
||||
unsigned int d_hash = dictionary()->compute_hash(child_name, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
unsigned int p_hash = placeholders()->compute_hash(child_name, loader_data);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(child_name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
unsigned int p_hash = placeholders()->compute_hash(child_name);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
// can't throw error holding a lock
|
||||
bool child_already_loaded = false;
|
||||
bool throw_circularity_error = false;
|
||||
{
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
Klass* childk = find_class(d_index, d_hash, child_name, loader_data);
|
||||
Klass* childk = find_class(d_index, d_hash, child_name, dictionary);
|
||||
Klass* quicksuperk;
|
||||
// to support // loading: if child done loading, just return superclass
|
||||
// if class_name, & class_loader don't match:
|
||||
@ -445,13 +445,18 @@ void SystemDictionary::validate_protection_domain(InstanceKlass* klass,
|
||||
ls.cr();
|
||||
}
|
||||
|
||||
// This handle and the class_loader handle passed in keeps this class from
|
||||
// being unloaded through several GC points.
|
||||
// The class_loader handle passed in is the initiating loader.
|
||||
Handle mirror(THREAD, klass->java_mirror());
|
||||
|
||||
InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass();
|
||||
JavaCalls::call_special(&result,
|
||||
class_loader,
|
||||
system_loader,
|
||||
vmSymbols::checkPackageAccess_name(),
|
||||
vmSymbols::class_protectiondomain_signature(),
|
||||
Handle(THREAD, klass->java_mirror()),
|
||||
mirror,
|
||||
protection_domain,
|
||||
THREAD);
|
||||
|
||||
@ -466,27 +471,16 @@ void SystemDictionary::validate_protection_domain(InstanceKlass* klass,
|
||||
// If no exception has been thrown, we have validated the protection domain
|
||||
// Insert the protection domain of the initiating class into the set.
|
||||
{
|
||||
// We recalculate the entry here -- we've called out to java since
|
||||
// the last time it was calculated.
|
||||
ClassLoaderData* loader_data = class_loader_data(class_loader);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
|
||||
Symbol* kn = klass->name();
|
||||
unsigned int d_hash = dictionary()->compute_hash(kn, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
unsigned int d_hash = dictionary->compute_hash(kn);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
{
|
||||
// Note that we have an entry, and entries can be deleted only during GC,
|
||||
// so we cannot allow GC to occur while we're holding this entry.
|
||||
|
||||
// We're using a NoSafepointVerifier to catch any place where we
|
||||
// might potentially do a GC at all.
|
||||
// Dictionary::do_unloading() asserts that classes in SD are only
|
||||
// unloaded at a safepoint. Anonymous classes are not in SD.
|
||||
NoSafepointVerifier nosafepoint;
|
||||
dictionary()->add_protection_domain(d_index, d_hash, klass, loader_data,
|
||||
protection_domain, THREAD);
|
||||
}
|
||||
dictionary->add_protection_domain(d_index, d_hash, klass,
|
||||
protection_domain, THREAD);
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,9 +542,10 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
|
||||
Handle protection_domain, Handle lockObject, TRAPS) {
|
||||
|
||||
ClassLoaderData* loader_data = class_loader_data(class_loader);
|
||||
unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
unsigned int p_hash = placeholders()->compute_hash(name);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
|
||||
// superk is not used, resolve_super called for circularity check only
|
||||
@ -573,7 +568,7 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
|
||||
if (!class_loader.is_null() && is_parallelCapable(class_loader)) {
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
// Check if classloading completed while we were loading superclass or waiting
|
||||
return find_class(d_index, d_hash, name, loader_data);
|
||||
return find_class(d_index, d_hash, name, dictionary);
|
||||
}
|
||||
|
||||
// must loop to both handle other placeholder updates
|
||||
@ -583,7 +578,7 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
|
||||
while (super_load_in_progress) {
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
// Check if classloading completed while we were loading superclass or waiting
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so just return it
|
||||
return check;
|
||||
@ -663,6 +658,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
// Fix for 4474172; see evaluation for more details
|
||||
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
|
||||
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
|
||||
// Do lookup to see if class already exist and the protection domain
|
||||
// has the right access
|
||||
@ -670,10 +666,9 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
// All subsequent calls use find_class, and set has_loaded_class so that
|
||||
// before we return a result we call out to java to check for valid protection domain
|
||||
// to allow returning the Klass* and add it to the pd_set if it is valid
|
||||
unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
Klass* probe = dictionary()->find(d_index, d_hash, name, loader_data,
|
||||
protection_domain, THREAD);
|
||||
unsigned int d_hash = dictionary->compute_hash(name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
Klass* probe = dictionary->find(d_index, d_hash, name, protection_domain);
|
||||
if (probe != NULL) return probe;
|
||||
|
||||
|
||||
@ -691,7 +686,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
DoObjectLock = false;
|
||||
}
|
||||
|
||||
unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
|
||||
unsigned int p_hash = placeholders()->compute_hash(name);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
|
||||
// Class is not in SystemDictionary so we have to do loading.
|
||||
@ -710,7 +705,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
|
||||
{
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so just return it
|
||||
class_has_been_loaded = true;
|
||||
@ -794,7 +789,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
double_lock_wait(lockObject, THREAD);
|
||||
}
|
||||
// Check if classloading completed while we were waiting
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so just return it
|
||||
k = check;
|
||||
@ -819,7 +814,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
// i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL
|
||||
// one final check if the load has already completed
|
||||
// class loaders holding the ObjectLock shouldn't find the class here
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so return it after checking/adding protection domain
|
||||
k = check;
|
||||
@ -852,7 +847,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
if (k == NULL && HAS_PENDING_EXCEPTION
|
||||
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so just use it
|
||||
k = check;
|
||||
@ -886,7 +881,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
}
|
||||
}
|
||||
}
|
||||
} // load_instance_class loop
|
||||
} // load_instance_class
|
||||
|
||||
if (load_instance_added == true) {
|
||||
// clean up placeholder entries for LOAD_INSTANCE success or error
|
||||
@ -919,16 +914,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
// Check the protection domain has the right access
|
||||
{
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
// Note that we have an entry, and entries can be deleted only during GC,
|
||||
// so we cannot allow GC to occur while we're holding this entry.
|
||||
// We're using a NoSafepointVerifier to catch any place where we
|
||||
// might potentially do a GC at all.
|
||||
// Dictionary::do_unloading() asserts that classes in SD are only
|
||||
// unloaded at a safepoint. Anonymous classes are not in SD.
|
||||
NoSafepointVerifier nosafepoint;
|
||||
if (dictionary()->is_valid_protection_domain(d_index, d_hash, name,
|
||||
loader_data,
|
||||
protection_domain)) {
|
||||
if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
|
||||
protection_domain)) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
@ -968,20 +955,11 @@ Klass* SystemDictionary::find(Symbol* class_name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
|
||||
{
|
||||
// Note that we have an entry, and entries can be deleted only during GC,
|
||||
// so we cannot allow GC to occur while we're holding this entry.
|
||||
// We're using a NoSafepointVerifier to catch any place where we
|
||||
// might potentially do a GC at all.
|
||||
// Dictionary::do_unloading() asserts that classes in SD are only
|
||||
// unloaded at a safepoint. Anonymous classes are not in SD.
|
||||
NoSafepointVerifier nosafepoint;
|
||||
return dictionary()->find(d_index, d_hash, class_name, loader_data,
|
||||
protection_domain, THREAD);
|
||||
}
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(class_name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
return dictionary->find(d_index, d_hash, class_name,
|
||||
protection_domain);
|
||||
}
|
||||
|
||||
|
||||
@ -1035,7 +1013,6 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
|
||||
guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
|
||||
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
|
||||
loader_data->record_dependency(host_klass, CHECK_NULL);
|
||||
} else {
|
||||
loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||
}
|
||||
@ -1066,7 +1043,7 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
// deoptimizations.
|
||||
add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
|
||||
|
||||
// But, do not add to system dictionary.
|
||||
// But, do not add to dictionary.
|
||||
|
||||
// compiled code dependencies need to be validated anyway
|
||||
notice_modification();
|
||||
@ -1189,9 +1166,10 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
#if INCLUDE_CDS
|
||||
void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
|
||||
int number_of_entries) {
|
||||
assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
|
||||
assert(length == _shared_dictionary_size * sizeof(HashtableBucket<mtClass>),
|
||||
"bad shared dictionary size.");
|
||||
_shared_dictionary = new Dictionary(_nof_buckets, t, number_of_entries);
|
||||
_shared_dictionary = new Dictionary(ClassLoaderData::the_null_class_loader_data(),
|
||||
_shared_dictionary_size, t, number_of_entries);
|
||||
}
|
||||
|
||||
|
||||
@ -1200,7 +1178,7 @@ void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int le
|
||||
|
||||
InstanceKlass* SystemDictionary::find_shared_class(Symbol* class_name) {
|
||||
if (shared_dictionary() != NULL) {
|
||||
unsigned int d_hash = shared_dictionary()->compute_hash(class_name, NULL);
|
||||
unsigned int d_hash = shared_dictionary()->compute_hash(class_name);
|
||||
int d_index = shared_dictionary()->hash_to_index(d_hash);
|
||||
|
||||
return shared_dictionary()->find_shared_class(d_index, d_hash, class_name);
|
||||
@ -1626,8 +1604,9 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) {
|
||||
// Parallel classloaders will call find_or_define_instance_class
|
||||
// which will require a token to perform the define class
|
||||
Symbol* name_h = k->name();
|
||||
unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(name_h);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
|
||||
|
||||
// Register class just loaded with class loader (placed in Vector)
|
||||
@ -1645,7 +1624,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) {
|
||||
|
||||
// Add the new class. We need recompile lock during update of CHA.
|
||||
{
|
||||
unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
|
||||
unsigned int p_hash = placeholders()->compute_hash(name_h);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
|
||||
MutexLocker mu_r(Compile_lock, THREAD);
|
||||
@ -1695,12 +1674,13 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
|
||||
|
||||
Symbol* name_h = k->name(); // passed in class_name may be null
|
||||
ClassLoaderData* loader_data = class_loader_data(class_loader);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
|
||||
unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
unsigned int d_hash = dictionary->compute_hash(name_h);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
|
||||
// Hold SD lock around find_class and placeholder creation for DEFINE_CLASS
|
||||
unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
|
||||
unsigned int p_hash = placeholders()->compute_hash(name_h);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
PlaceholderEntry* probe;
|
||||
|
||||
@ -1708,7 +1688,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
// First check if class already defined
|
||||
if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
|
||||
if (check != NULL) {
|
||||
return check;
|
||||
}
|
||||
@ -1730,7 +1710,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
|
||||
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
|
||||
SystemDictionary_lock->notify_all();
|
||||
#ifdef ASSERT
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
|
||||
assert(check != NULL, "definer missed recording success");
|
||||
#endif
|
||||
return probe->instance_klass();
|
||||
@ -1769,6 +1749,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) {
|
||||
// If class_loader is NULL we synchronize on _system_loader_lock_obj
|
||||
if (class_loader.is_null()) {
|
||||
@ -1806,12 +1787,9 @@ void SystemDictionary::check_loader_lock_contention(Handle loader_lock, TRAPS) {
|
||||
|
||||
InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash,
|
||||
Symbol* class_name,
|
||||
ClassLoaderData* loader_data) {
|
||||
Dictionary* dictionary) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert (index == dictionary()->index_for(class_name, loader_data),
|
||||
"incorrect index?");
|
||||
|
||||
return dictionary()->find_class(index, hash, class_name, loader_data);
|
||||
return dictionary->find_class(index, hash, class_name);
|
||||
}
|
||||
|
||||
|
||||
@ -1819,14 +1797,17 @@ InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash,
|
||||
Symbol* SystemDictionary::find_placeholder(Symbol* class_name,
|
||||
ClassLoaderData* loader_data) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
unsigned int p_hash = placeholders()->compute_hash(class_name, loader_data);
|
||||
unsigned int p_hash = placeholders()->compute_hash(class_name);
|
||||
int p_index = placeholders()->hash_to_index(p_hash);
|
||||
return placeholders()->find_entry(p_index, p_hash, class_name, loader_data);
|
||||
}
|
||||
|
||||
|
||||
// Used for assertions and verification only
|
||||
// Precalculating the hash and index is an optimization because there are many lookups
|
||||
// before adding the class.
|
||||
InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
#ifndef ASSERT
|
||||
guarantee(VerifyBeforeGC ||
|
||||
VerifyDuringGC ||
|
||||
@ -1834,18 +1815,11 @@ InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData*
|
||||
VerifyDuringStartup ||
|
||||
VerifyAfterGC, "too expensive");
|
||||
#endif
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
|
||||
// First look in the loaded class array
|
||||
unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
return find_class(d_index, d_hash, class_name, loader_data);
|
||||
}
|
||||
|
||||
|
||||
// Get the next class in the dictionary.
|
||||
Klass* SystemDictionary::try_get_next_class() {
|
||||
return dictionary()->try_get_next_class();
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
unsigned int d_hash = dictionary->compute_hash(class_name);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
return find_class(d_index, d_hash, class_name, dictionary);
|
||||
}
|
||||
|
||||
|
||||
@ -1872,33 +1846,10 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// GC support
|
||||
|
||||
// Following roots during mark-sweep is separated in two phases.
|
||||
//
|
||||
// The first phase follows preloaded classes and all other system
|
||||
// classes, since these will never get unloaded anyway.
|
||||
//
|
||||
// The second phase removes (unloads) unreachable classes from the
|
||||
// system dictionary and follows the remaining classes' contents.
|
||||
|
||||
void SystemDictionary::always_strong_oops_do(OopClosure* blk) {
|
||||
roots_oops_do(blk, NULL);
|
||||
}
|
||||
|
||||
// Calculate a "good" systemdictionary size based
|
||||
// on predicted or current loaded classes count
|
||||
int SystemDictionary::calculate_systemdictionary_size(int classcount) {
|
||||
int newsize = _old_default_sdsize;
|
||||
if ((classcount > 0) && !DumpSharedSpaces) {
|
||||
int desiredsize = classcount/_average_depth_goal;
|
||||
for (newsize = _primelist[_sdgeneration]; _sdgeneration < _prime_array_size -1;
|
||||
newsize = _primelist[++_sdgeneration]) {
|
||||
if (desiredsize <= newsize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newsize;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
class VerifySDReachableAndLiveClosure : public OopClosure {
|
||||
@ -1907,7 +1858,7 @@ private:
|
||||
|
||||
template <class T> void do_oop_work(T* p) {
|
||||
oop obj = oopDesc::load_decode_heap_oop(p);
|
||||
guarantee(_is_alive->do_object_b(obj), "Oop in system dictionary must be live");
|
||||
guarantee(_is_alive->do_object_b(obj), "Oop in protection domain cache table must be live");
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1936,20 +1887,20 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive,
|
||||
|
||||
if (unloading_occurred) {
|
||||
GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
|
||||
dictionary()->do_unloading();
|
||||
constraints()->purge_loader_constraints();
|
||||
resolution_errors()->purge_resolution_errors();
|
||||
}
|
||||
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) t("ProtectionDomainCacheTable", gc_timer);
|
||||
// Oops referenced by the system dictionary may get unreachable independently
|
||||
// Oops referenced by the protection domain cache table may get unreachable independently
|
||||
// of the class loader (eg. cached protection domain oops). So we need to
|
||||
// explicitly unlink them here instead of in Dictionary::do_unloading.
|
||||
dictionary()->unlink(is_alive);
|
||||
// explicitly unlink them here.
|
||||
_pd_cache_table->unlink(is_alive);
|
||||
|
||||
#ifdef ASSERT
|
||||
VerifySDReachableAndLiveClosure cl(is_alive);
|
||||
dictionary()->oops_do(&cl);
|
||||
_pd_cache_table->oops_do(&cl);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1966,8 +1917,16 @@ void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||
strong->do_oop(&_system_loader_lock_obj);
|
||||
CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
|
||||
|
||||
// Adjust dictionary
|
||||
dictionary()->roots_oops_do(strong, weak);
|
||||
// Do strong roots marking if the closures are the same.
|
||||
if (strong == weak || !ClassUnloading) {
|
||||
// Only the protection domain oops contain references into the heap. Iterate
|
||||
// over all of them.
|
||||
_pd_cache_table->oops_do(strong);
|
||||
} else {
|
||||
if (weak != NULL) {
|
||||
_pd_cache_table->oops_do(weak);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit extra methods
|
||||
invoke_method_table()->oops_do(strong);
|
||||
@ -1982,8 +1941,9 @@ void SystemDictionary::oops_do(OopClosure* f) {
|
||||
f->do_oop(&_system_loader_lock_obj);
|
||||
CDS_ONLY(SystemDictionaryShared::oops_do(f);)
|
||||
|
||||
// Adjust dictionary
|
||||
dictionary()->oops_do(f);
|
||||
// Only the protection domain oops contain references into the heap. Iterate
|
||||
// over all of them.
|
||||
_pd_cache_table->oops_do(f);
|
||||
|
||||
// Visit extra methods
|
||||
invoke_method_table()->oops_do(f);
|
||||
@ -1991,25 +1951,6 @@ void SystemDictionary::oops_do(OopClosure* f) {
|
||||
ResolvedMethodTable::oops_do(f);
|
||||
}
|
||||
|
||||
// Just the classes from defining class loaders
|
||||
// Don't iterate over placeholders
|
||||
void SystemDictionary::classes_do(void f(Klass*)) {
|
||||
dictionary()->classes_do(f);
|
||||
}
|
||||
|
||||
// Added for initialize_itable_for_klass
|
||||
// Just the classes from defining class loaders
|
||||
// Don't iterate over placeholders
|
||||
void SystemDictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
|
||||
dictionary()->classes_do(f, CHECK);
|
||||
}
|
||||
|
||||
// All classes, and their class loaders
|
||||
// Don't iterate over placeholders
|
||||
void SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
|
||||
dictionary()->classes_do(f);
|
||||
}
|
||||
|
||||
void SystemDictionary::methods_do(void f(Method*)) {
|
||||
// Walk methods in loaded classes
|
||||
ClassLoaderDataGraph::methods_do(f);
|
||||
@ -2018,7 +1959,7 @@ void SystemDictionary::methods_do(void f(Method*)) {
|
||||
}
|
||||
|
||||
void SystemDictionary::remove_classes_in_error_state() {
|
||||
dictionary()->remove_classes_in_error_state();
|
||||
ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -2042,15 +1983,12 @@ void SystemDictionary::load_abstract_ownable_synchronizer_klass(TRAPS) {
|
||||
|
||||
void SystemDictionary::initialize(TRAPS) {
|
||||
// Allocate arrays
|
||||
assert(dictionary() == NULL,
|
||||
"SystemDictionary should only be initialized once");
|
||||
_sdgeneration = 0;
|
||||
_dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount));
|
||||
_placeholders = new PlaceholderTable(_nof_buckets);
|
||||
_placeholders = new PlaceholderTable(_placeholder_table_size);
|
||||
_number_of_modifications = 0;
|
||||
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
|
||||
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
|
||||
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
|
||||
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||
|
||||
// Allocate private object used as system class loader lock
|
||||
_system_loader_lock_obj = oopFactory::new_intArray(0, CHECK);
|
||||
@ -2204,9 +2142,9 @@ BasicType SystemDictionary::box_klass_type(Klass* k) {
|
||||
// Constraints on class loaders. The details of the algorithm can be
|
||||
// found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
|
||||
// Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is
|
||||
// that the system dictionary needs to maintain a set of contraints that
|
||||
// that the dictionary needs to maintain a set of contraints that
|
||||
// must be satisfied by all classes in the dictionary.
|
||||
// if defining is true, then LinkageError if already in systemDictionary
|
||||
// if defining is true, then LinkageError if already in dictionary
|
||||
// if initiating loader, then ok if InstanceKlass matches existing entry
|
||||
|
||||
void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
|
||||
@ -2221,12 +2159,12 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
|
||||
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
|
||||
InstanceKlass* check = find_class(d_index, d_hash, name, loader_data->dictionary());
|
||||
if (check != NULL) {
|
||||
// if different InstanceKlass - duplicate class definition,
|
||||
// else - ok, class loaded by a different thread in parallel,
|
||||
// we should only have found it if it was done loading and ok to use
|
||||
// system dictionary only holds instance classes, placeholders
|
||||
// dictionary only holds instance classes, placeholders
|
||||
// also holds array classes
|
||||
|
||||
assert(check->is_instance_klass(), "noninstance in systemdictionary");
|
||||
@ -2267,7 +2205,7 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
|
||||
}
|
||||
|
||||
|
||||
// Update system dictionary - done after check_constraint and add_to_hierachy
|
||||
// Update class loader data dictionary - done after check_constraint and add_to_hierachy
|
||||
// have been called.
|
||||
void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
|
||||
int p_index, unsigned int p_hash,
|
||||
@ -2280,40 +2218,41 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
|
||||
ClassLoaderData *loader_data = class_loader_data(class_loader);
|
||||
|
||||
{
|
||||
MutexLocker mu1(SystemDictionary_lock, THREAD);
|
||||
MutexLocker mu1(SystemDictionary_lock, THREAD);
|
||||
|
||||
// See whether biased locking is enabled and if so set it for this
|
||||
// klass.
|
||||
// Note that this must be done past the last potential blocking
|
||||
// point / safepoint. We enable biased locking lazily using a
|
||||
// VM_Operation to iterate the SystemDictionary and installing the
|
||||
// biasable mark word into each InstanceKlass's prototype header.
|
||||
// To avoid race conditions where we accidentally miss enabling the
|
||||
// optimization for one class in the process of being added to the
|
||||
// dictionary, we must not safepoint after the test of
|
||||
// BiasedLocking::enabled().
|
||||
if (UseBiasedLocking && BiasedLocking::enabled()) {
|
||||
// Set biased locking bit for all loaded classes; it will be
|
||||
// cleared if revocation occurs too often for this type
|
||||
// NOTE that we must only do this when the class is initally
|
||||
// defined, not each time it is referenced from a new class loader
|
||||
if (k->class_loader() == class_loader()) {
|
||||
k->set_prototype_header(markOopDesc::biased_locking_prototype());
|
||||
// See whether biased locking is enabled and if so set it for this
|
||||
// klass.
|
||||
// Note that this must be done past the last potential blocking
|
||||
// point / safepoint. We enable biased locking lazily using a
|
||||
// VM_Operation to iterate the SystemDictionary and installing the
|
||||
// biasable mark word into each InstanceKlass's prototype header.
|
||||
// To avoid race conditions where we accidentally miss enabling the
|
||||
// optimization for one class in the process of being added to the
|
||||
// dictionary, we must not safepoint after the test of
|
||||
// BiasedLocking::enabled().
|
||||
if (UseBiasedLocking && BiasedLocking::enabled()) {
|
||||
// Set biased locking bit for all loaded classes; it will be
|
||||
// cleared if revocation occurs too often for this type
|
||||
// NOTE that we must only do this when the class is initally
|
||||
// defined, not each time it is referenced from a new class loader
|
||||
if (k->class_loader() == class_loader()) {
|
||||
k->set_prototype_header(markOopDesc::biased_locking_prototype());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a new system dictionary entry.
|
||||
InstanceKlass* sd_check = find_class(d_index, d_hash, name, loader_data);
|
||||
if (sd_check == NULL) {
|
||||
dictionary()->add_klass(name, loader_data, k);
|
||||
notice_modification();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
sd_check = find_class(d_index, d_hash, name, loader_data);
|
||||
assert (sd_check != NULL, "should have entry in system dictionary");
|
||||
// Note: there may be a placeholder entry: for circularity testing
|
||||
// or for parallel defines
|
||||
#endif
|
||||
// Make a new dictionary entry.
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
InstanceKlass* sd_check = find_class(d_index, d_hash, name, dictionary);
|
||||
if (sd_check == NULL) {
|
||||
dictionary->add_klass(d_index, d_hash, name, k);
|
||||
notice_modification();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
sd_check = find_class(d_index, d_hash, name, dictionary);
|
||||
assert (sd_check != NULL, "should have entry in dictionary");
|
||||
// Note: there may be a placeholder entry: for circularity testing
|
||||
// or for parallel defines
|
||||
#endif
|
||||
SystemDictionary_lock->notify_all();
|
||||
}
|
||||
}
|
||||
@ -2383,21 +2322,21 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
|
||||
constraint_name = fd.object_key();
|
||||
}
|
||||
}
|
||||
unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, loader_data1);
|
||||
int d_index1 = dictionary()->hash_to_index(d_hash1);
|
||||
|
||||
unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, loader_data2);
|
||||
int d_index2 = dictionary()->hash_to_index(d_hash2);
|
||||
Dictionary* dictionary1 = loader_data1->dictionary();
|
||||
unsigned int d_hash1 = dictionary1->compute_hash(constraint_name);
|
||||
int d_index1 = dictionary1->hash_to_index(d_hash1);
|
||||
|
||||
Dictionary* dictionary2 = loader_data2->dictionary();
|
||||
unsigned int d_hash2 = dictionary2->compute_hash(constraint_name);
|
||||
int d_index2 = dictionary2->hash_to_index(d_hash2);
|
||||
|
||||
{
|
||||
MutexLocker mu_s(SystemDictionary_lock, THREAD);
|
||||
|
||||
// Better never do a GC while we're holding these oops
|
||||
NoSafepointVerifier nosafepoint;
|
||||
|
||||
InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1);
|
||||
InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2);
|
||||
return constraints()->add_entry(constraint_name, klass1, class_loader1,
|
||||
klass2, class_loader2);
|
||||
MutexLocker mu_s(SystemDictionary_lock, THREAD);
|
||||
InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, dictionary1);
|
||||
InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, dictionary2);
|
||||
return constraints()->add_entry(constraint_name, klass1, class_loader1,
|
||||
klass2, class_loader2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2847,64 +2786,73 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller,
|
||||
return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
|
||||
}
|
||||
|
||||
// Since the identity hash code for symbols changes when the symbols are
|
||||
// moved from the regular perm gen (hash in the mark word) to the shared
|
||||
// spaces (hash is the address), the classes loaded into the dictionary
|
||||
// may be in the wrong buckets.
|
||||
// Protection domain cache table handling
|
||||
|
||||
ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {
|
||||
return _pd_cache_table->get(protection_domain);
|
||||
}
|
||||
|
||||
|
||||
void SystemDictionary::reorder_dictionary() {
|
||||
dictionary()->reorder_dictionary();
|
||||
ClassLoaderData::the_null_class_loader_data()->dictionary()->reorder_dictionary();
|
||||
}
|
||||
|
||||
|
||||
void SystemDictionary::copy_buckets(char** top, char* end) {
|
||||
dictionary()->copy_buckets(top, end);
|
||||
ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_buckets(top, end);
|
||||
}
|
||||
|
||||
|
||||
void SystemDictionary::copy_table(char** top, char* end) {
|
||||
dictionary()->copy_table(top, end);
|
||||
ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_table(top, end);
|
||||
}
|
||||
|
||||
int SystemDictionary::number_of_classes() {
|
||||
return dictionary()->number_of_entries();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SystemDictionary::print_shared(bool details) {
|
||||
shared_dictionary()->print(details);
|
||||
}
|
||||
|
||||
void SystemDictionary::print(bool details) {
|
||||
dictionary()->print(details);
|
||||
if (shared_dictionary() != NULL) {
|
||||
tty->print_cr("Shared Dictionary");
|
||||
shared_dictionary()->print(details);
|
||||
}
|
||||
|
||||
GCMutexLocker mu(SystemDictionary_lock);
|
||||
|
||||
ClassLoaderDataGraph::print_dictionary(details);
|
||||
|
||||
// Placeholders
|
||||
GCMutexLocker mu(SystemDictionary_lock);
|
||||
placeholders()->print();
|
||||
tty->cr();
|
||||
|
||||
// loader constraints - print under SD_lock
|
||||
constraints()->print();
|
||||
tty->cr();
|
||||
|
||||
_pd_cache_table->print();
|
||||
tty->cr();
|
||||
}
|
||||
|
||||
|
||||
void SystemDictionary::verify() {
|
||||
guarantee(dictionary() != NULL, "Verify of system dictionary failed");
|
||||
guarantee(constraints() != NULL,
|
||||
"Verify of loader constraints failed");
|
||||
guarantee(dictionary()->number_of_entries() >= 0 &&
|
||||
placeholders()->number_of_entries() >= 0,
|
||||
"Verify of system dictionary failed");
|
||||
|
||||
// Verify dictionary
|
||||
dictionary()->verify();
|
||||
guarantee(placeholders()->number_of_entries() >= 0,
|
||||
"Verify of placeholders failed");
|
||||
|
||||
GCMutexLocker mu(SystemDictionary_lock);
|
||||
|
||||
// Verify dictionary
|
||||
ClassLoaderDataGraph::verify_dictionary();
|
||||
|
||||
placeholders()->verify();
|
||||
|
||||
// Verify constraint table
|
||||
guarantee(constraints() != NULL, "Verify of loader constraints failed");
|
||||
constraints()->verify(dictionary(), placeholders());
|
||||
constraints()->verify(placeholders());
|
||||
|
||||
_pd_cache_table->verify();
|
||||
}
|
||||
|
||||
// caller needs ResourceMark
|
||||
|
||||
@ -35,31 +35,34 @@
|
||||
#include "utilities/hashtable.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
|
||||
// The system dictionary stores all loaded classes and maps:
|
||||
// The dictionary in each ClassLoaderData stores all loaded classes, either
|
||||
// initiatied by its class loader or defined by its class loader:
|
||||
//
|
||||
// [class name,class loader] -> class i.e. [Symbol*,oop] -> Klass*
|
||||
// class loader -> ClassLoaderData -> [class, protection domain set]
|
||||
//
|
||||
// Classes are loaded lazily. The default VM class loader is
|
||||
// represented as NULL.
|
||||
|
||||
// The underlying data structure is an open hash table with a fixed number
|
||||
// of buckets. During loading the loader object is locked, (for the VM loader
|
||||
// a private lock object is used). Class loading can thus be done concurrently,
|
||||
// but only by different loaders.
|
||||
// The underlying data structure is an open hash table (Dictionary) per
|
||||
// ClassLoaderData with a fixed number of buckets. During loading the
|
||||
// class loader object is locked, (for the VM loader a private lock object is used).
|
||||
// The global SystemDictionary_lock is held for all additions into the ClassLoaderData
|
||||
// dictionaries. TODO: fix lock granularity so that class loading can
|
||||
// be done concurrently, but only by different loaders.
|
||||
//
|
||||
// During loading a placeholder (name, loader) is temporarily placed in
|
||||
// a side data structure, and is used to detect ClassCircularityErrors
|
||||
// and to perform verification during GC. A GC can occur in the midst
|
||||
// of class loading, as we call out to Java, have to take locks, etc.
|
||||
//
|
||||
// When class loading is finished, a new entry is added to the system
|
||||
// dictionary and the place holder is removed. Note that the protection
|
||||
// domain field of the system dictionary has not yet been filled in when
|
||||
// the "real" system dictionary entry is created.
|
||||
// When class loading is finished, a new entry is added to the dictionary
|
||||
// of the class loader and the placeholder is removed. Note that the protection
|
||||
// domain field of the dictionary entry has not yet been filled in when
|
||||
// the "real" dictionary entry is created.
|
||||
//
|
||||
// Clients of this class who are interested in finding if a class has
|
||||
// been completely loaded -- not classes in the process of being loaded --
|
||||
// can read the SystemDictionary unlocked. This is safe because
|
||||
// can read the dictionary unlocked. This is safe because
|
||||
// - entries are only deleted at safepoints
|
||||
// - readers cannot come to a safepoint while actively examining
|
||||
// an entry (an entry cannot be deleted from under a reader)
|
||||
@ -78,6 +81,8 @@ class LoaderConstraintTable;
|
||||
template <MEMFLAGS F> class HashtableBucket;
|
||||
class ResolutionErrorTable;
|
||||
class SymbolPropertyTable;
|
||||
class ProtectionDomainCacheTable;
|
||||
class ProtectionDomainCacheEntry;
|
||||
class GCTimer;
|
||||
|
||||
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
|
||||
@ -281,7 +286,7 @@ public:
|
||||
bool is_superclass,
|
||||
TRAPS);
|
||||
|
||||
// Parse new stream. This won't update the system dictionary or
|
||||
// Parse new stream. This won't update the dictionary or
|
||||
// class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses.
|
||||
// Also used by Unsafe_DefineAnonymousClass
|
||||
static InstanceKlass* parse_stream(Symbol* class_name,
|
||||
@ -348,14 +353,6 @@ public:
|
||||
Handle class_loader,
|
||||
TRAPS);
|
||||
|
||||
// Iterate over all klasses in dictionary
|
||||
// Just the classes from defining class loaders
|
||||
static void classes_do(void f(Klass*));
|
||||
// Added for initialize_itable_for_klass to handle exceptions
|
||||
static void classes_do(void f(Klass*, TRAPS), TRAPS);
|
||||
// All classes, and their class loaders, including initiating class loaders
|
||||
static void classes_do(void f(Klass*, ClassLoaderData*));
|
||||
|
||||
// Iterate over all methods in all klasses
|
||||
static void methods_do(void f(Method*));
|
||||
|
||||
@ -394,11 +391,6 @@ public:
|
||||
static void print(bool details = true);
|
||||
static void print_shared(bool details = true);
|
||||
|
||||
// Number of contained klasses
|
||||
// This is both fully loaded classes and classes in the process
|
||||
// of being loaded
|
||||
static int number_of_classes();
|
||||
|
||||
// Monotonically increasing counter which grows as classes are
|
||||
// loaded or modifications such as hot-swapping or setting/removing
|
||||
// of breakpoints are performed
|
||||
@ -558,28 +550,21 @@ public:
|
||||
static Symbol* find_resolution_error(const constantPoolHandle& pool, int which,
|
||||
Symbol** message);
|
||||
|
||||
|
||||
static ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
|
||||
|
||||
protected:
|
||||
|
||||
enum Constants {
|
||||
_loader_constraint_size = 107, // number of entries in constraint table
|
||||
_resolution_error_size = 107, // number of entries in resolution error table
|
||||
_invoke_method_size = 139, // number of entries in invoke method table
|
||||
_nof_buckets = 1009, // number of buckets in hash table for placeholders
|
||||
_old_default_sdsize = 1009, // backward compat for system dictionary size
|
||||
_prime_array_size = 8, // array of primes for system dictionary size
|
||||
_average_depth_goal = 3 // goal for lookup length
|
||||
_shared_dictionary_size = 1009, // number of entries in shared dictionary
|
||||
_placeholder_table_size = 1009 // number of entries in hash table for placeholders
|
||||
};
|
||||
|
||||
|
||||
// Static variables
|
||||
|
||||
// hashtable sizes for system dictionary to allow growth
|
||||
// prime numbers for system dictionary size
|
||||
static int _sdgeneration;
|
||||
static const int _primelist[_prime_array_size];
|
||||
|
||||
// Hashtable holding loaded classes.
|
||||
static Dictionary* _dictionary;
|
||||
// Static tables owned by the SystemDictionary
|
||||
|
||||
// Hashtable holding placeholders for classes being loaded.
|
||||
static PlaceholderTable* _placeholders;
|
||||
@ -588,7 +573,7 @@ public:
|
||||
static Dictionary* _shared_dictionary;
|
||||
|
||||
// Monotonically increasing counter which grows with
|
||||
// _number_of_classes as well as hot-swapping and breakpoint setting
|
||||
// loading classes as well as hot-swapping and breakpoint setting
|
||||
// and removal.
|
||||
static int _number_of_modifications;
|
||||
|
||||
@ -604,10 +589,8 @@ public:
|
||||
// Invoke methods (JSR 292)
|
||||
static SymbolPropertyTable* _invoke_method_table;
|
||||
|
||||
public:
|
||||
// for VM_CounterDecay iteration support
|
||||
friend class CounterDecay;
|
||||
static Klass* try_get_next_class();
|
||||
// ProtectionDomain cache
|
||||
static ProtectionDomainCacheTable* _pd_cache_table;
|
||||
|
||||
protected:
|
||||
static void validate_protection_domain(InstanceKlass* klass,
|
||||
@ -616,7 +599,6 @@ protected:
|
||||
|
||||
friend class VM_PopulateDumpSharedSpace;
|
||||
friend class TraversePlaceholdersClosure;
|
||||
static Dictionary* dictionary() { return _dictionary; }
|
||||
static Dictionary* shared_dictionary() { return _shared_dictionary; }
|
||||
static PlaceholderTable* placeholders() { return _placeholders; }
|
||||
static LoaderConstraintTable* constraints() { return _loader_constraints; }
|
||||
@ -666,7 +648,7 @@ protected:
|
||||
|
||||
// Basic find on loaded classes
|
||||
static InstanceKlass* find_class(int index, unsigned int hash,
|
||||
Symbol* name, ClassLoaderData* loader_data);
|
||||
Symbol* name, Dictionary* dictionary);
|
||||
static InstanceKlass* find_class(Symbol* class_name, ClassLoaderData* loader_data);
|
||||
|
||||
// Basic find on classes in the midst of being loaded
|
||||
|
||||
@ -69,6 +69,7 @@ public:
|
||||
}
|
||||
|
||||
static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {}
|
||||
static bool is_builtin(DictionaryEntry* entry) { return true; }
|
||||
|
||||
static InstanceKlass* lookup_from_stream(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
|
||||
@ -1285,7 +1285,7 @@ void CodeCache::flush_evol_dependents_on(InstanceKlass* ev_k) {
|
||||
|
||||
|
||||
// Flushes compiled methods dependent on dependee
|
||||
void CodeCache::flush_dependents_on_method(methodHandle m_h) {
|
||||
void CodeCache::flush_dependents_on_method(const methodHandle& m_h) {
|
||||
// --- Compile_lock is not held. However we are at a safepoint.
|
||||
assert_locked_or_safepoint(Compile_lock);
|
||||
|
||||
|
||||
@ -282,7 +282,7 @@ class CodeCache : AllStatic {
|
||||
static void flush_evol_dependents_on(InstanceKlass* dependee);
|
||||
#endif // HOTSWAP
|
||||
// Support for fullspeed debugging
|
||||
static void flush_dependents_on_method(methodHandle dependee);
|
||||
static void flush_dependents_on_method(const methodHandle& dependee);
|
||||
|
||||
// tells how many nmethods have dependencies
|
||||
static int number_of_nmethods_with_dependencies();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -123,7 +123,7 @@ CompilerDirectives* CompilerDirectives::next() {
|
||||
return _next;
|
||||
}
|
||||
|
||||
bool CompilerDirectives::match(methodHandle method) {
|
||||
bool CompilerDirectives::match(const methodHandle& method) {
|
||||
if (is_default_directive()) {
|
||||
return true;
|
||||
}
|
||||
@ -232,7 +232,7 @@ DirectiveSet::~DirectiveSet() {
|
||||
// - Need to free copy after use
|
||||
// - Requires a modified bit so we don't overwrite options that is set by directives
|
||||
|
||||
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
|
||||
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
|
||||
// Early bail out - checking all options is expensive - we rely on them not being used
|
||||
// Only set a flag if it has not been modified and value changes.
|
||||
// Only copy set if a flag needs to be set
|
||||
@ -307,7 +307,7 @@ CompilerDirectives* DirectiveSet::directive() {
|
||||
return _directive;
|
||||
}
|
||||
|
||||
bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
|
||||
bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
|
||||
if (_inlinematchers != NULL) {
|
||||
if (_inlinematchers->match(method, inline_action)) {
|
||||
return true;
|
||||
@ -384,7 +384,7 @@ void DirectiveSet::print_inline(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
|
||||
bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
|
||||
@ -543,7 +543,7 @@ void DirectivesStack::release(CompilerDirectives* dir) {
|
||||
}
|
||||
}
|
||||
|
||||
DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
|
||||
DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
|
||||
assert(_depth > 0, "Must never be empty");
|
||||
|
||||
DirectiveSet* match = NULL;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -84,7 +84,7 @@ private:
|
||||
static void pop_inner(); // no lock version of pop
|
||||
public:
|
||||
static void init();
|
||||
static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
|
||||
static DirectiveSet* getMatchingDirective(const methodHandle& mh, AbstractCompiler* comp);
|
||||
static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
|
||||
static void push(CompilerDirectives* directive);
|
||||
static void pop(int count);
|
||||
@ -109,11 +109,11 @@ public:
|
||||
bool should_inline(ciMethod* inlinee);
|
||||
bool should_not_inline(ciMethod* inlinee);
|
||||
void print_inline(outputStream* st);
|
||||
DirectiveSet* compilecommand_compatibility_init(methodHandle method);
|
||||
DirectiveSet* compilecommand_compatibility_init(const methodHandle& method);
|
||||
bool is_exclusive_copy() { return _directive == NULL; }
|
||||
bool matches_inline(methodHandle method, int inline_action);
|
||||
bool matches_inline(const methodHandle& method, int inline_action);
|
||||
static DirectiveSet* clone(DirectiveSet const* src);
|
||||
bool is_intrinsic_disabled(methodHandle method);
|
||||
bool is_intrinsic_disabled(const methodHandle& method);
|
||||
static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
|
||||
void finalize(outputStream* st);
|
||||
|
||||
@ -170,7 +170,7 @@ public:
|
||||
CompilerDirectives* next();
|
||||
void set_next(CompilerDirectives* next) {_next = next; }
|
||||
|
||||
bool match(methodHandle method);
|
||||
bool match(const methodHandle& method);
|
||||
BasicMatcher* match() { return _match; }
|
||||
bool add_match(char* str, const char*& error_msg);
|
||||
DirectiveSet* get_for(AbstractCompiler *comp);
|
||||
|
||||
@ -132,7 +132,7 @@ class TypedMethodOptionMatcher : public MethodMatcher {
|
||||
}
|
||||
|
||||
static TypedMethodOptionMatcher* parse_method_pattern(char*& line, const char*& error_msg);
|
||||
TypedMethodOptionMatcher* match(methodHandle method, const char* opt, OptionType type);
|
||||
TypedMethodOptionMatcher* match(const methodHandle& method, const char* opt, OptionType type);
|
||||
|
||||
void init(const char* opt, OptionType type, TypedMethodOptionMatcher* next) {
|
||||
_next = next;
|
||||
@ -261,7 +261,7 @@ TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*&
|
||||
return tom;
|
||||
}
|
||||
|
||||
TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(methodHandle method, const char* opt, OptionType type) {
|
||||
TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(const methodHandle& method, const char* opt, OptionType type) {
|
||||
TypedMethodOptionMatcher* current = this;
|
||||
while (current != NULL) {
|
||||
// Fastest compare first.
|
||||
@ -289,7 +289,7 @@ static void add_option_string(TypedMethodOptionMatcher* matcher,
|
||||
return;
|
||||
}
|
||||
|
||||
static bool check_predicate(OracleCommand command, methodHandle method) {
|
||||
static bool check_predicate(OracleCommand command, const methodHandle& method) {
|
||||
return ((lists[command] != NULL) &&
|
||||
!method.is_null() &&
|
||||
lists[command]->match(method));
|
||||
|
||||
@ -628,11 +628,20 @@ void DirectivesParser::test() {
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" c2: {" "\n"
|
||||
" PrintInlining: false," "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", true);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" c2: {" "\n"
|
||||
" VectorizeDebug: 1," "\n"
|
||||
" VectorizeDebug: -1," "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", true);
|
||||
"]" "\n", COMPILER2_PRESENT(true) NOT_COMPILER2(false));
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
|
||||
@ -109,7 +109,7 @@ AbstractInterpreterGenerator::AbstractInterpreterGenerator(StubQueue* _code) {
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Entry points
|
||||
|
||||
AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m) {
|
||||
AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHandle& m) {
|
||||
// Abstract method?
|
||||
if (m->is_abstract()) return abstract;
|
||||
|
||||
|
||||
@ -130,11 +130,11 @@ class AbstractInterpreter: AllStatic {
|
||||
|
||||
|
||||
// Method activation
|
||||
static MethodKind method_kind(methodHandle m);
|
||||
static MethodKind method_kind(const methodHandle& m);
|
||||
static address entry_for_kind(MethodKind k) { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; }
|
||||
static address entry_for_method(methodHandle m) { return entry_for_kind(method_kind(m)); }
|
||||
static address entry_for_method(const methodHandle& m) { return entry_for_kind(method_kind(m)); }
|
||||
|
||||
static address entry_for_cds_method(methodHandle m) {
|
||||
static address entry_for_cds_method(const methodHandle& m) {
|
||||
MethodKind k = method_kind(m);
|
||||
assert(0 <= k && k < number_of_method_entries, "illegal kind");
|
||||
return _cds_entry_table[k];
|
||||
|
||||
@ -212,7 +212,7 @@ BasicType Bytecode_loadconstant::result_type() const {
|
||||
}
|
||||
|
||||
oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
|
||||
assert(_method.not_null(), "must supply method to resolve constant");
|
||||
assert(_method != NULL, "must supply method to resolve constant");
|
||||
int index = raw_index();
|
||||
ConstantPool* constants = _method->constants();
|
||||
if (has_cache_index()) {
|
||||
|
||||
@ -178,11 +178,11 @@ class Bytecode_tableswitch: public Bytecode {
|
||||
|
||||
class Bytecode_member_ref: public Bytecode {
|
||||
protected:
|
||||
const methodHandle _method; // method containing the bytecode
|
||||
const Method* _method; // method containing the bytecode
|
||||
|
||||
Bytecode_member_ref(const methodHandle& method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {}
|
||||
Bytecode_member_ref(const methodHandle& method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method()) {}
|
||||
|
||||
methodHandle method() const { return _method; }
|
||||
const Method* method() const { return _method; }
|
||||
ConstantPool* constants() const { return _method->constants(); }
|
||||
ConstantPoolCache* cpcache() const { return _method->constants()->cache(); }
|
||||
ConstantPoolCacheEntry* cpcache_entry() const;
|
||||
@ -312,15 +312,15 @@ class Bytecode_anewarray: public Bytecode {
|
||||
// Abstraction for ldc, ldc_w and ldc2_w
|
||||
class Bytecode_loadconstant: public Bytecode {
|
||||
private:
|
||||
const methodHandle _method;
|
||||
const Method* _method;
|
||||
|
||||
int raw_index() const;
|
||||
|
||||
public:
|
||||
Bytecode_loadconstant(const methodHandle& method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); }
|
||||
Bytecode_loadconstant(const methodHandle& method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method()) { verify(); }
|
||||
|
||||
void verify() const {
|
||||
assert(_method.not_null(), "must supply method");
|
||||
assert(_method != NULL, "must supply method");
|
||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
||||
assert(stdc == Bytecodes::_ldc ||
|
||||
stdc == Bytecodes::_ldc_w ||
|
||||
|
||||
@ -2790,7 +2790,7 @@ run:
|
||||
CALL_VM(continuation_bci = (intptr_t)InterpreterRuntime::exception_handler_for_exception(THREAD, except_oop()),
|
||||
handle_exception);
|
||||
|
||||
except_oop = THREAD->vm_result();
|
||||
except_oop = Handle(THREAD, THREAD->vm_result());
|
||||
THREAD->set_vm_result(NULL);
|
||||
if (continuation_bci >= 0) {
|
||||
// Place exception on top of stack
|
||||
@ -2994,7 +2994,7 @@ run:
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD));
|
||||
}
|
||||
assert(THREAD->has_pending_exception(), "Lost our exception!");
|
||||
illegal_state_oop = THREAD->pending_exception();
|
||||
illegal_state_oop = Handle(THREAD, THREAD->pending_exception());
|
||||
THREAD->clear_pending_exception();
|
||||
}
|
||||
}
|
||||
@ -3011,7 +3011,7 @@ run:
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD));
|
||||
}
|
||||
assert(THREAD->has_pending_exception(), "Lost our exception!");
|
||||
illegal_state_oop = THREAD->pending_exception();
|
||||
illegal_state_oop = Handle(THREAD, THREAD->pending_exception());
|
||||
THREAD->clear_pending_exception();
|
||||
}
|
||||
} else {
|
||||
@ -3028,7 +3028,7 @@ run:
|
||||
if (rcvr == NULL) {
|
||||
if (!suppress_error) {
|
||||
VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap);
|
||||
illegal_state_oop = THREAD->pending_exception();
|
||||
illegal_state_oop = Handle(THREAD, THREAD->pending_exception());
|
||||
THREAD->clear_pending_exception();
|
||||
}
|
||||
} else if (UseHeavyMonitors) {
|
||||
@ -3038,7 +3038,7 @@ run:
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base));
|
||||
}
|
||||
if (THREAD->has_pending_exception()) {
|
||||
if (!suppress_error) illegal_state_oop = THREAD->pending_exception();
|
||||
if (!suppress_error) illegal_state_oop = Handle(THREAD, THREAD->pending_exception());
|
||||
THREAD->clear_pending_exception();
|
||||
}
|
||||
} else {
|
||||
@ -3059,7 +3059,7 @@ run:
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base));
|
||||
}
|
||||
if (THREAD->has_pending_exception()) {
|
||||
if (!suppress_error) illegal_state_oop = THREAD->pending_exception();
|
||||
if (!suppress_error) illegal_state_oop = Handle(THREAD, THREAD->pending_exception());
|
||||
THREAD->clear_pending_exception();
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ IRT_END
|
||||
// Exceptions
|
||||
|
||||
void InterpreterRuntime::note_trap_inner(JavaThread* thread, int reason,
|
||||
methodHandle trap_method, int trap_bci, TRAPS) {
|
||||
const methodHandle& trap_method, int trap_bci, TRAPS) {
|
||||
if (trap_method.not_null()) {
|
||||
MethodData* trap_mdo = trap_method->method_data();
|
||||
if (trap_mdo == NULL) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,7 +66,7 @@ class InterpreterRuntime: AllStatic {
|
||||
static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
|
||||
static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
|
||||
static void note_trap_inner(JavaThread* thread, int reason,
|
||||
methodHandle trap_method, int trap_bci, TRAPS);
|
||||
const methodHandle& trap_method, int trap_bci, TRAPS);
|
||||
static void note_trap(JavaThread *thread, int reason, TRAPS);
|
||||
#ifdef CC_INTERP
|
||||
// Profile traps in C++ interpreter.
|
||||
|
||||
@ -104,7 +104,7 @@ const char* InvocationCounter::state_as_short_string(State state) {
|
||||
}
|
||||
|
||||
|
||||
static address do_nothing(methodHandle method, TRAPS) {
|
||||
static address do_nothing(const methodHandle& method, TRAPS) {
|
||||
// dummy action for inactive invocation counters
|
||||
MethodCounters* mcs = method->method_counters();
|
||||
assert(mcs != NULL, "");
|
||||
@ -114,7 +114,7 @@ static address do_nothing(methodHandle method, TRAPS) {
|
||||
}
|
||||
|
||||
|
||||
static address do_decay(methodHandle method, TRAPS) {
|
||||
static address do_decay(const methodHandle& method, TRAPS) {
|
||||
// decay invocation counters so compilation gets delayed
|
||||
MethodCounters* mcs = method->method_counters();
|
||||
assert(mcs != NULL, "");
|
||||
@ -130,7 +130,7 @@ void InvocationCounter::def(State state, int init, Action action) {
|
||||
_action[state] = action;
|
||||
}
|
||||
|
||||
address dummy_invocation_counter_overflow(methodHandle m, TRAPS) {
|
||||
address dummy_invocation_counter_overflow(const methodHandle& m, TRAPS) {
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -62,7 +62,7 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC {
|
||||
static int InterpreterBackwardBranchLimit; // A separate threshold for on stack replacement
|
||||
static int InterpreterProfileLimit; // Profiling threshold scaled for interpreter use
|
||||
|
||||
typedef address (*Action)(methodHandle method, TRAPS);
|
||||
typedef address (*Action)(const methodHandle& method, TRAPS);
|
||||
|
||||
enum PublicConstants {
|
||||
count_increment = count_grain, // use this value to increment the 32bit _counter word
|
||||
|
||||
@ -235,7 +235,7 @@ void CallInfo::print() {
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Implementation of LinkInfo
|
||||
|
||||
LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS) {
|
||||
LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, const methodHandle& current_method, TRAPS) {
|
||||
// resolve klass
|
||||
_resolved_klass = pool->klass_ref_at(index, CHECK);
|
||||
|
||||
@ -315,9 +315,11 @@ void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass,
|
||||
|
||||
// Look up method in klasses, including static methods
|
||||
// Then look up local default methods
|
||||
methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve, TRAPS) {
|
||||
Method* LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve) {
|
||||
NoSafepointVerifier nsv; // Method* returned may not be reclaimed
|
||||
|
||||
Klass* klass = link_info.resolved_klass();
|
||||
Symbol* name = link_info.name();
|
||||
Symbol* signature = link_info.signature();
|
||||
@ -327,7 +329,7 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
|
||||
if (klass->is_array_klass()) {
|
||||
// Only consider klass and super klass for arrays
|
||||
return methodHandle(THREAD, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
||||
@ -363,7 +365,7 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return methodHandle(THREAD, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// returns first instance method
|
||||
@ -418,15 +420,13 @@ int LinkResolver::vtable_index_of_interface_method(Klass* klass,
|
||||
return vtable_index;
|
||||
}
|
||||
|
||||
methodHandle LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info, TRAPS) {
|
||||
Method* LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info) {
|
||||
InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass());
|
||||
|
||||
// Specify 'true' in order to skip default methods when searching the
|
||||
// interfaces. Function lookup_method_in_klasses() already looked for
|
||||
// the method in the default methods table.
|
||||
return methodHandle(THREAD,
|
||||
ik->lookup_method_in_all_interfaces(cp_info.name(), cp_info.signature(),
|
||||
Klass::skip_defaults));
|
||||
return ik->lookup_method_in_all_interfaces(cp_info.name(), cp_info.signature(), Klass::skip_defaults);
|
||||
}
|
||||
|
||||
methodHandle LinkResolver::lookup_polymorphic_method(
|
||||
@ -713,13 +713,12 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
}
|
||||
|
||||
|
||||
// 3. lookup method in resolved klass and its super klasses
|
||||
methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL);
|
||||
methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, true, false));
|
||||
|
||||
// 4. lookup method in all the interfaces implemented by the resolved klass
|
||||
if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // not found in the class hierarchy
|
||||
resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
|
||||
resolved_method = methodHandle(THREAD, lookup_method_in_interfaces(link_info));
|
||||
|
||||
if (resolved_method.is_null()) {
|
||||
// JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
|
||||
@ -817,11 +816,11 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, B
|
||||
|
||||
// lookup method in this interface or its super, java.lang.Object
|
||||
// JDK8: also look for static methods
|
||||
methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL);
|
||||
methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, false, true));
|
||||
|
||||
if (resolved_method.is_null() && !resolved_klass->is_array_klass()) {
|
||||
// lookup method in all the super-interfaces
|
||||
resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
|
||||
resolved_method = methodHandle(THREAD, lookup_method_in_interfaces(link_info));
|
||||
}
|
||||
|
||||
if (resolved_method.is_null()) {
|
||||
|
||||
@ -152,7 +152,7 @@ class LinkInfo : public StackObj {
|
||||
skip_access_check
|
||||
};
|
||||
|
||||
LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS);
|
||||
LinkInfo(const constantPoolHandle& pool, int index, const methodHandle& current_method, TRAPS);
|
||||
LinkInfo(const constantPoolHandle& pool, int index, TRAPS);
|
||||
|
||||
// Condensed information from other call sites within the vm.
|
||||
@ -163,7 +163,7 @@ class LinkInfo : public StackObj {
|
||||
_name(name), _signature(signature), _current_klass(current_klass), _current_method(methodHandle()),
|
||||
_check_access(check_access == needs_access_check), _tag(tag) {}
|
||||
|
||||
LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, methodHandle current_method,
|
||||
LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, const methodHandle& current_method,
|
||||
AccessCheck check_access = needs_access_check,
|
||||
constantTag tag = JVM_CONSTANT_Invalid) :
|
||||
_resolved_klass(resolved_klass),
|
||||
@ -201,10 +201,11 @@ class LinkResolver: AllStatic {
|
||||
|
||||
private:
|
||||
|
||||
static methodHandle lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve, TRAPS);
|
||||
static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS);
|
||||
static Method* lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve);
|
||||
static Method* lookup_method_in_interfaces(const LinkInfo& link_info);
|
||||
|
||||
static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
|
||||
Handle *appendix_result_or_null,
|
||||
Handle *method_type_result, TRAPS);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,9 +39,9 @@ class OopMapCacheEntry: private InterpreterOopMap {
|
||||
|
||||
protected:
|
||||
// Initialization
|
||||
void fill(methodHandle method, int bci);
|
||||
void fill(const methodHandle& method, int bci);
|
||||
// fills the bit mask for native calls
|
||||
void fill_for_native(methodHandle method);
|
||||
void fill_for_native(const methodHandle& method);
|
||||
void set_mask(CellTypeState* vars, CellTypeState* stack, int stack_top);
|
||||
|
||||
// Deallocate bit masks and initialize fields
|
||||
@ -80,7 +80,7 @@ class OopMapForCacheEntry: public GenerateOopMap {
|
||||
virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars);
|
||||
|
||||
public:
|
||||
OopMapForCacheEntry(methodHandle method, int bci, OopMapCacheEntry *entry);
|
||||
OopMapForCacheEntry(const methodHandle& method, int bci, OopMapCacheEntry *entry);
|
||||
|
||||
// Computes stack map for (method,bci) and initialize entry
|
||||
void compute_map(TRAPS);
|
||||
@ -88,7 +88,7 @@ class OopMapForCacheEntry: public GenerateOopMap {
|
||||
};
|
||||
|
||||
|
||||
OopMapForCacheEntry::OopMapForCacheEntry(methodHandle method, int bci, OopMapCacheEntry* entry) : GenerateOopMap(method) {
|
||||
OopMapForCacheEntry::OopMapForCacheEntry(const methodHandle& method, int bci, OopMapCacheEntry* entry) : GenerateOopMap(method) {
|
||||
_bci = bci;
|
||||
_entry = entry;
|
||||
_stack_top = -1;
|
||||
@ -242,7 +242,7 @@ class MaskFillerForNative: public NativeSignatureIterator {
|
||||
void pass_double() { /* ignore */ }
|
||||
void pass_object() { set_one(offset()); }
|
||||
|
||||
MaskFillerForNative(methodHandle method, uintptr_t* mask, int size) : NativeSignatureIterator(method) {
|
||||
MaskFillerForNative(const methodHandle& method, uintptr_t* mask, int size) : NativeSignatureIterator(method) {
|
||||
_mask = mask;
|
||||
_size = size;
|
||||
// initialize with 0
|
||||
@ -301,7 +301,7 @@ void OopMapCacheEntry::deallocate_bit_mask() {
|
||||
}
|
||||
|
||||
|
||||
void OopMapCacheEntry::fill_for_native(methodHandle mh) {
|
||||
void OopMapCacheEntry::fill_for_native(const methodHandle& mh) {
|
||||
assert(mh->is_native(), "method must be native method");
|
||||
set_mask_size(mh->size_of_parameters() * bits_per_entry);
|
||||
allocate_bit_mask();
|
||||
@ -311,7 +311,7 @@ void OopMapCacheEntry::fill_for_native(methodHandle mh) {
|
||||
}
|
||||
|
||||
|
||||
void OopMapCacheEntry::fill(methodHandle method, int bci) {
|
||||
void OopMapCacheEntry::fill(const methodHandle& method, int bci) {
|
||||
HandleMark hm;
|
||||
// Flush entry to deallocate an existing entry
|
||||
flush();
|
||||
|
||||
@ -117,7 +117,7 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
|
||||
// require that local 0 is never overwritten so it's available as an
|
||||
// argument for registration.
|
||||
|
||||
void Rewriter::rewrite_Object_init(methodHandle method, TRAPS) {
|
||||
void Rewriter::rewrite_Object_init(const methodHandle& method, TRAPS) {
|
||||
RawBytecodeStream bcs(method);
|
||||
while (!bcs.is_last_bytecode()) {
|
||||
Bytecodes::Code opcode = bcs.raw_next();
|
||||
@ -491,17 +491,16 @@ void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_err
|
||||
}
|
||||
|
||||
// After constant pool is created, revisit methods containing jsrs.
|
||||
methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) {
|
||||
methodHandle Rewriter::rewrite_jsrs(const methodHandle& method, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
ResolveOopMapConflicts romc(method);
|
||||
methodHandle original_method = method;
|
||||
method = romc.do_potential_rewrite(CHECK_(methodHandle()));
|
||||
methodHandle new_method = romc.do_potential_rewrite(CHECK_(methodHandle()));
|
||||
// Update monitor matching info.
|
||||
if (romc.monitor_safe()) {
|
||||
method->set_guaranteed_monitor_matching();
|
||||
new_method->set_guaranteed_monitor_matching();
|
||||
}
|
||||
|
||||
return method;
|
||||
return new_method;
|
||||
}
|
||||
|
||||
void Rewriter::rewrite_bytecodes(TRAPS) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user