mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 04:24:49 +02:00
Merge
This commit is contained in:
commit
c380e15d57
311 changed files with 9026 additions and 1752 deletions
2
.hgtags
2
.hgtags
|
@ -53,3 +53,5 @@ ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73
|
||||||
09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76
|
09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76
|
||||||
1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77
|
1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77
|
||||||
4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78
|
4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78
|
||||||
|
e9c98378f6b9256c0595ef2985ca5899f0c0e274 jdk7-b79
|
||||||
|
e6abd38682d237306d6c147c17538ec9e7f8e3a7 jdk7-b80
|
||||||
|
|
|
@ -53,3 +53,5 @@ d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
|
||||||
c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76
|
c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76
|
||||||
1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77
|
1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77
|
||||||
ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78
|
ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78
|
||||||
|
20aeeb51713990dbea6929a2e100a8bbf5df70d4 jdk7-b79
|
||||||
|
a3242906c7747b5d9bcc3d118c7c3c69aa40f4b7 jdk7-b80
|
||||||
|
|
|
@ -53,3 +53,5 @@ b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73
|
||||||
937144222e2219939101b0129d26a872a7956b13 jdk7-b76
|
937144222e2219939101b0129d26a872a7956b13 jdk7-b76
|
||||||
6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77
|
6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77
|
||||||
a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78
|
a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78
|
||||||
|
ec0421b5703b677e2226cf4bf7ae4eaafd8061c5 jdk7-b79
|
||||||
|
0336e70ca0aeabc783cc01658f36cb6e27ea7934 jdk7-b80
|
||||||
|
|
|
@ -123,7 +123,7 @@ public abstract class Expression
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Coerces a number to the target type of this expression.
|
* Coerces a number to the target type of this expression.
|
||||||
* @parm number The number to coerce.
|
* @param obj The number to coerce.
|
||||||
* @return the value of number coerced to the (target) type of
|
* @return the value of number coerced to the (target) type of
|
||||||
* this expression.
|
* this expression.
|
||||||
**/
|
**/
|
||||||
|
@ -142,7 +142,7 @@ public abstract class Expression
|
||||||
/**
|
/**
|
||||||
* Coerces an integral value (BigInteger) to its corresponding unsigned
|
* Coerces an integral value (BigInteger) to its corresponding unsigned
|
||||||
* representation, if the target type of this expression is unsigned.
|
* representation, if the target type of this expression is unsigned.
|
||||||
* @parm b The BigInteger to be coerced.
|
* @param b The BigInteger to be coerced.
|
||||||
* @return the value of an integral type coerced to its corresponding
|
* @return the value of an integral type coerced to its corresponding
|
||||||
* unsigned integral type, if the target type of this expression is
|
* unsigned integral type, if the target type of this expression is
|
||||||
* unsigned.
|
* unsigned.
|
||||||
|
@ -170,7 +170,7 @@ public abstract class Expression
|
||||||
/**
|
/**
|
||||||
* Coerces an integral value (BigInteger) to its corresponding signed
|
* Coerces an integral value (BigInteger) to its corresponding signed
|
||||||
* representation, if the target type of this expression is signed.
|
* representation, if the target type of this expression is signed.
|
||||||
* @parm b The BigInteger to be coerced.
|
* @param b The BigInteger to be coerced.
|
||||||
* @return the value of an integral type coerced to its corresponding
|
* @return the value of an integral type coerced to its corresponding
|
||||||
* signed integral type, if the target type of this expression is
|
* signed integral type, if the target type of this expression is
|
||||||
* signed.
|
* signed.
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class PortableRemoteObject {
|
||||||
* happens implicitly when the object is sent or received as an argument
|
* happens implicitly when the object is sent or received as an argument
|
||||||
* on a remote method call, but in some circumstances it is useful to
|
* on a remote method call, but in some circumstances it is useful to
|
||||||
* perform this action by making an explicit call. See the
|
* perform this action by making an explicit call. See the
|
||||||
* {@link Stub#connect} method for more information.
|
* {@link javax.rmi.CORBA.Stub#connect} method for more information.
|
||||||
* @param target the object to connect.
|
* @param target the object to connect.
|
||||||
* @param source a previously connected object.
|
* @param source a previously connected object.
|
||||||
* @throws RemoteException if <code>source</code> is not connected
|
* @throws RemoteException if <code>source</code> is not connected
|
||||||
|
|
|
@ -31,7 +31,7 @@ package org.omg.CORBA;
|
||||||
* indicate whether policies should replace the
|
* indicate whether policies should replace the
|
||||||
* existing policies of an <code>Object</code> or be added to them.
|
* existing policies of an <code>Object</code> or be added to them.
|
||||||
* <P>
|
* <P>
|
||||||
* The method {@link omg.org.CORBA.Object._set_policy_override} takes
|
* The method {@link org.omg.CORBA.Object#_set_policy_override} takes
|
||||||
* either <code>SetOverrideType.SET_OVERRIDE</code> or
|
* either <code>SetOverrideType.SET_OVERRIDE</code> or
|
||||||
* <code>SetOverrideType.ADD_OVERRIDE</code> as its second argument.
|
* <code>SetOverrideType.ADD_OVERRIDE</code> as its second argument.
|
||||||
* The method <code>_set_policy_override</code>
|
* The method <code>_set_policy_override</code>
|
||||||
|
|
|
@ -545,8 +545,6 @@ public class TCKind {
|
||||||
* @param _value the <code>int</code> to convert. It must be one of
|
* @param _value the <code>int</code> to convert. It must be one of
|
||||||
* the <code>int</code> constants in the class
|
* the <code>int</code> constants in the class
|
||||||
* <code>TCKind</code>.
|
* <code>TCKind</code>.
|
||||||
* @return a new <code>TCKind</code> instance whose <code>value</code>
|
|
||||||
* field matches the given <code>int</code>
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected TCKind(int _value){
|
protected TCKind(int _value){
|
||||||
|
|
|
@ -43,7 +43,6 @@ public class ServantObject
|
||||||
/** The real servant. The local stub may cast this field to the expected type, and then
|
/** The real servant. The local stub may cast this field to the expected type, and then
|
||||||
* invoke the operation directly. Note, the object may or may not be the actual servant
|
* invoke the operation directly. Note, the object may or may not be the actual servant
|
||||||
* instance.
|
* instance.
|
||||||
* @return The real servant
|
|
||||||
*/
|
*/
|
||||||
public java.lang.Object servant;
|
public java.lang.Object servant;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ module CosNaming
|
||||||
*
|
*
|
||||||
* @param n Name of the object <p>
|
* @param n Name of the object <p>
|
||||||
*
|
*
|
||||||
* @parm obj The Object to rebind with the given name <p>
|
* @param obj The Object to rebind with the given name <p>
|
||||||
*
|
*
|
||||||
* @exception org.omg.CosNaming.NamingContextPackage.NotFound Indicates the name does not identify a binding.<p>
|
* @exception org.omg.CosNaming.NamingContextPackage.NotFound Indicates the name does not identify a binding.<p>
|
||||||
*
|
*
|
||||||
|
|
|
@ -1730,7 +1730,7 @@ module PortableInterceptor {
|
||||||
* <p>
|
* <p>
|
||||||
* Any number of components may exist with the same component ID.
|
* Any number of components may exist with the same component ID.
|
||||||
*
|
*
|
||||||
* @param a_component The IOP.TaggedComponent to add.
|
* @param tagged_component The IOP.TaggedComponent to add.
|
||||||
*/
|
*/
|
||||||
void add_ior_component
|
void add_ior_component
|
||||||
(in IOP::TaggedComponent tagged_component);
|
(in IOP::TaggedComponent tagged_component);
|
||||||
|
@ -1744,7 +1744,7 @@ module PortableInterceptor {
|
||||||
* <p>
|
* <p>
|
||||||
* Any number of components may exist with the same component ID.
|
* Any number of components may exist with the same component ID.
|
||||||
*
|
*
|
||||||
* @param a_component The <code>IOP.TaggedComponent</code> to add.
|
* @param tagged_component The <code>IOP.TaggedComponent</code> to add.
|
||||||
* @param profile_id The profile id of the profile to
|
* @param profile_id The profile id of the profile to
|
||||||
* which this component will be added.
|
* which this component will be added.
|
||||||
* @exception BAD_PARAM thrown, with a standard minor code of 29, if the
|
* @exception BAD_PARAM thrown, with a standard minor code of 29, if the
|
||||||
|
|
|
@ -53,3 +53,5 @@ d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
|
||||||
9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76
|
9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76
|
||||||
455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77
|
455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77
|
||||||
e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78
|
e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78
|
||||||
|
a5a6adfca6ecefb5894a848debabfe442ff50e25 jdk7-b79
|
||||||
|
3003ddd1d4330b06cb4691ae74d600d3685899eb jdk7-b80
|
||||||
|
|
|
@ -63,12 +63,12 @@ public class SystemDictionary {
|
||||||
javaSystemLoaderField = type.getOopField("_java_system_loader");
|
javaSystemLoaderField = type.getOopField("_java_system_loader");
|
||||||
nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue();
|
nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue();
|
||||||
|
|
||||||
objectKlassField = type.getOopField(WK_KLASS("object_klass"));
|
objectKlassField = type.getOopField(WK_KLASS("Object_klass"));
|
||||||
classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass"));
|
classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass"));
|
||||||
stringKlassField = type.getOopField(WK_KLASS("string_klass"));
|
stringKlassField = type.getOopField(WK_KLASS("String_klass"));
|
||||||
systemKlassField = type.getOopField(WK_KLASS("system_klass"));
|
systemKlassField = type.getOopField(WK_KLASS("System_klass"));
|
||||||
threadKlassField = type.getOopField(WK_KLASS("thread_klass"));
|
threadKlassField = type.getOopField(WK_KLASS("Thread_klass"));
|
||||||
threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass"));
|
threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This WK functions must follow the definitions in systemDictionary.hpp:
|
// This WK functions must follow the definitions in systemDictionary.hpp:
|
||||||
|
|
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||||
|
|
||||||
HS_MAJOR_VER=17
|
HS_MAJOR_VER=17
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=06
|
HS_BUILD_NUMBER=08
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=7
|
JDK_MINOR_VER=7
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -394,6 +394,11 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
|
||||||
|
// No special entry points that preclude compilation
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// This method tells the deoptimizer how big an interpreted frame must be:
|
// This method tells the deoptimizer how big an interpreted frame must be:
|
||||||
int AbstractInterpreter::size_activation(methodOop method,
|
int AbstractInterpreter::size_activation(methodOop method,
|
||||||
int tempcount,
|
int tempcount,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
// Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
//
|
//
|
||||||
// This code is free software; you can redistribute it and/or modify it
|
// This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1885,6 +1885,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||||
return RegMask();
|
return RegMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||||
|
return RegMask();
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6664,7 +6668,7 @@ instruct cmovII_imm(cmpOp cmp, flagsReg icc, iRegI dst, immI11 src) %{
|
||||||
ins_pipe(ialu_imm);
|
ins_pipe(ialu_imm);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmovII_U_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
|
instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
|
||||||
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
|
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
|
||||||
ins_cost(150);
|
ins_cost(150);
|
||||||
size(4);
|
size(4);
|
||||||
|
@ -6673,7 +6677,7 @@ instruct cmovII_U_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
|
||||||
ins_pipe(ialu_reg);
|
ins_pipe(ialu_reg);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmovII_U_imm(cmpOpU cmp, flagsRegU icc, iRegI dst, immI11 src) %{
|
instruct cmovIIu_imm(cmpOpU cmp, flagsRegU icc, iRegI dst, immI11 src) %{
|
||||||
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
|
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
|
||||||
ins_cost(140);
|
ins_cost(140);
|
||||||
size(4);
|
size(4);
|
||||||
|
@ -6719,6 +6723,16 @@ instruct cmovNI_reg(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src) %{
|
||||||
ins_pipe(ialu_reg);
|
ins_pipe(ialu_reg);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// This instruction also works with CmpN so we don't need cmovNN_reg.
|
||||||
|
instruct cmovNIu_reg(cmpOpU cmp, flagsRegU icc, iRegN dst, iRegN src) %{
|
||||||
|
match(Set dst (CMoveN (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(150);
|
||||||
|
size(4);
|
||||||
|
format %{ "MOV$cmp $icc,$src,$dst" %}
|
||||||
|
ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(ialu_reg);
|
||||||
|
%}
|
||||||
|
|
||||||
instruct cmovNF_reg(cmpOpF cmp, flagsRegF fcc, iRegN dst, iRegN src) %{
|
instruct cmovNF_reg(cmpOpF cmp, flagsRegF fcc, iRegN dst, iRegN src) %{
|
||||||
match(Set dst (CMoveN (Binary cmp fcc) (Binary dst src)));
|
match(Set dst (CMoveN (Binary cmp fcc) (Binary dst src)));
|
||||||
ins_cost(150);
|
ins_cost(150);
|
||||||
|
@ -6756,6 +6770,16 @@ instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
|
||||||
ins_pipe(ialu_reg);
|
ins_pipe(ialu_reg);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
|
||||||
|
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(150);
|
||||||
|
|
||||||
|
size(4);
|
||||||
|
format %{ "MOV$cmp $icc,$src,$dst\t! ptr" %}
|
||||||
|
ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(ialu_reg);
|
||||||
|
%}
|
||||||
|
|
||||||
instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
|
instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
|
||||||
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
|
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
|
||||||
ins_cost(140);
|
ins_cost(140);
|
||||||
|
@ -6766,6 +6790,16 @@ instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
|
||||||
ins_pipe(ialu_imm);
|
ins_pipe(ialu_imm);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
|
||||||
|
match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(140);
|
||||||
|
|
||||||
|
size(4);
|
||||||
|
format %{ "MOV$cmp $icc,$src,$dst\t! ptr" %}
|
||||||
|
ins_encode( enc_cmov_imm(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(ialu_imm);
|
||||||
|
%}
|
||||||
|
|
||||||
instruct cmovPF_reg(cmpOpF cmp, flagsRegF fcc, iRegP dst, iRegP src) %{
|
instruct cmovPF_reg(cmpOpF cmp, flagsRegF fcc, iRegP dst, iRegP src) %{
|
||||||
match(Set dst (CMoveP (Binary cmp fcc) (Binary dst src)));
|
match(Set dst (CMoveP (Binary cmp fcc) (Binary dst src)));
|
||||||
ins_cost(150);
|
ins_cost(150);
|
||||||
|
@ -6805,6 +6839,17 @@ instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
|
||||||
ins_pipe(int_conditional_float_move);
|
ins_pipe(int_conditional_float_move);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
|
||||||
|
match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(150);
|
||||||
|
|
||||||
|
size(4);
|
||||||
|
format %{ "FMOVS$cmp $icc,$src,$dst" %}
|
||||||
|
opcode(0x101);
|
||||||
|
ins_encode( enc_cmovf_reg(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(int_conditional_float_move);
|
||||||
|
%}
|
||||||
|
|
||||||
// Conditional move,
|
// Conditional move,
|
||||||
instruct cmovFF_reg(cmpOpF cmp, flagsRegF fcc, regF dst, regF src) %{
|
instruct cmovFF_reg(cmpOpF cmp, flagsRegF fcc, regF dst, regF src) %{
|
||||||
match(Set dst (CMoveF (Binary cmp fcc) (Binary dst src)));
|
match(Set dst (CMoveF (Binary cmp fcc) (Binary dst src)));
|
||||||
|
@ -6838,6 +6883,17 @@ instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
|
||||||
ins_pipe(int_conditional_double_move);
|
ins_pipe(int_conditional_double_move);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
|
||||||
|
match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(150);
|
||||||
|
|
||||||
|
size(4);
|
||||||
|
format %{ "FMOVD$cmp $icc,$src,$dst" %}
|
||||||
|
opcode(0x102);
|
||||||
|
ins_encode( enc_cmovf_reg(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(int_conditional_double_move);
|
||||||
|
%}
|
||||||
|
|
||||||
// Conditional move,
|
// Conditional move,
|
||||||
instruct cmovDF_reg(cmpOpF cmp, flagsRegF fcc, regD dst, regD src) %{
|
instruct cmovDF_reg(cmpOpF cmp, flagsRegF fcc, regD dst, regD src) %{
|
||||||
match(Set dst (CMoveD (Binary cmp fcc) (Binary dst src)));
|
match(Set dst (CMoveD (Binary cmp fcc) (Binary dst src)));
|
||||||
|
@ -6877,6 +6933,17 @@ instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
|
||||||
|
match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
|
||||||
|
ins_cost(150);
|
||||||
|
|
||||||
|
size(4);
|
||||||
|
format %{ "MOV$cmp $icc,$src,$dst\t! long" %}
|
||||||
|
ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) );
|
||||||
|
ins_pipe(ialu_reg);
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
instruct cmovLF_reg(cmpOpF cmp, flagsRegF fcc, iRegL dst, iRegL src) %{
|
instruct cmovLF_reg(cmpOpF cmp, flagsRegF fcc, iRegL dst, iRegL src) %{
|
||||||
match(Set dst (CMoveL (Binary cmp fcc) (Binary dst src)));
|
match(Set dst (CMoveL (Binary cmp fcc) (Binary dst src)));
|
||||||
ins_cost(150);
|
ins_cost(150);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2862,6 +2862,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
// arraycopy stubs used by compilers
|
// arraycopy stubs used by compilers
|
||||||
generate_arraycopy_stubs();
|
generate_arraycopy_stubs();
|
||||||
|
|
||||||
|
// Don't initialize the platform math functions since sparc
|
||||||
|
// doesn't have intrinsics for these operations.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,14 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||||
// This is the sp before any possible extension (adapter/locals).
|
// This is the sp before any possible extension (adapter/locals).
|
||||||
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
||||||
|
|
||||||
|
address sender_pc = this->sender_pc();
|
||||||
|
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
|
||||||
|
assert(sender_cb, "sanity");
|
||||||
|
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
|
||||||
|
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
|
||||||
|
unextended_sp = (intptr_t*) at(link_offset);
|
||||||
|
}
|
||||||
|
|
||||||
// The interpreter and compiler(s) always save EBP/RBP in a known
|
// The interpreter and compiler(s) always save EBP/RBP in a known
|
||||||
// location on entry. We must record where that location is
|
// location on entry. We must record where that location is
|
||||||
// so this if EBP/RBP was live on callout from c2 we can find
|
// so this if EBP/RBP was live on callout from c2 we can find
|
||||||
|
@ -352,7 +360,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
}
|
}
|
||||||
#endif /* COMPILER2 */
|
#endif /* COMPILER2 */
|
||||||
return frame(sp, unextended_sp, link(), sender_pc());
|
return frame(sp, unextended_sp, link(), sender_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -375,6 +383,18 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||||
|
|
||||||
intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
|
intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
|
||||||
|
|
||||||
|
intptr_t* unextended_sp = sender_sp;
|
||||||
|
// If we are returning to a compiled method handle call site,
|
||||||
|
// the saved_fp will in fact be a saved value of the unextended SP.
|
||||||
|
// The simplest way to tell whether we are returning to such a call
|
||||||
|
// site is as follows:
|
||||||
|
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
|
||||||
|
assert(sender_cb, "sanity");
|
||||||
|
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
|
||||||
|
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
|
||||||
|
unextended_sp = saved_fp;
|
||||||
|
}
|
||||||
|
|
||||||
if (map->update_map()) {
|
if (map->update_map()) {
|
||||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||||
|
@ -399,7 +419,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sender_sp != sp(), "must have changed");
|
assert(sender_sp != sp(), "must have changed");
|
||||||
return frame(sender_sp, saved_fp, sender_pc);
|
return frame(sender_sp, unextended_sp, saved_fp, sender_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame frame::sender(RegisterMap* map) const {
|
frame frame::sender(RegisterMap* map) const {
|
||||||
|
|
|
@ -228,8 +228,9 @@ inline intptr_t* frame::interpreter_frame_tos_address() const {
|
||||||
if (last_sp == NULL) {
|
if (last_sp == NULL) {
|
||||||
return sp();
|
return sp();
|
||||||
} else {
|
} else {
|
||||||
// sp() may have been extended by an adapter
|
// sp() may have been extended or shrunk by an adapter. At least
|
||||||
assert(last_sp < fp() && last_sp >= sp(), "bad tos");
|
// check that we don't fall behind the legal region.
|
||||||
|
assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos");
|
||||||
return last_sp;
|
return last_sp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,9 @@ static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
|
||||||
// Verify that argslot lies within (rsp, rbp].
|
// Verify that argslot lies within (rsp, rbp].
|
||||||
Label L_ok, L_bad;
|
Label L_ok, L_bad;
|
||||||
__ cmpptr(rax_argslot, rbp);
|
__ cmpptr(rax_argslot, rbp);
|
||||||
__ jcc(Assembler::above, L_bad);
|
__ jccb(Assembler::above, L_bad);
|
||||||
__ cmpptr(rsp, rax_argslot);
|
__ cmpptr(rsp, rax_argslot);
|
||||||
__ jcc(Assembler::below, L_ok);
|
__ jccb(Assembler::below, L_ok);
|
||||||
__ bind(L_bad);
|
__ bind(L_bad);
|
||||||
__ stop(error_message);
|
__ stop(error_message);
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
|
@ -136,9 +136,9 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
||||||
if (arg_slots.is_register()) {
|
if (arg_slots.is_register()) {
|
||||||
Label L_ok, L_bad;
|
Label L_ok, L_bad;
|
||||||
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
||||||
__ jcc(Assembler::greater, L_bad);
|
__ jccb(Assembler::greater, L_bad);
|
||||||
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
||||||
__ jcc(Assembler::zero, L_ok);
|
__ jccb(Assembler::zero, L_ok);
|
||||||
__ bind(L_bad);
|
__ bind(L_bad);
|
||||||
__ stop("assert arg_slots <= 0 and clear low bits");
|
__ stop("assert arg_slots <= 0 and clear low bits");
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
|
@ -173,7 +173,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
||||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||||
__ addptr(rdx_temp, wordSize);
|
__ addptr(rdx_temp, wordSize);
|
||||||
__ cmpptr(rdx_temp, rax_argslot);
|
__ cmpptr(rdx_temp, rax_argslot);
|
||||||
__ jcc(Assembler::less, loop);
|
__ jccb(Assembler::less, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now move the argslot down, to point to the opened-up space.
|
// Now move the argslot down, to point to the opened-up space.
|
||||||
|
@ -211,9 +211,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||||
Label L_ok, L_bad;
|
Label L_ok, L_bad;
|
||||||
__ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
|
__ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
|
||||||
__ cmpptr(rbx_temp, rbp);
|
__ cmpptr(rbx_temp, rbp);
|
||||||
__ jcc(Assembler::above, L_bad);
|
__ jccb(Assembler::above, L_bad);
|
||||||
__ cmpptr(rsp, rax_argslot);
|
__ cmpptr(rsp, rax_argslot);
|
||||||
__ jcc(Assembler::below, L_ok);
|
__ jccb(Assembler::below, L_ok);
|
||||||
__ bind(L_bad);
|
__ bind(L_bad);
|
||||||
__ stop("deleted argument(s) must fall within current frame");
|
__ stop("deleted argument(s) must fall within current frame");
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
|
@ -221,9 +221,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||||
if (arg_slots.is_register()) {
|
if (arg_slots.is_register()) {
|
||||||
Label L_ok, L_bad;
|
Label L_ok, L_bad;
|
||||||
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
||||||
__ jcc(Assembler::less, L_bad);
|
__ jccb(Assembler::less, L_bad);
|
||||||
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
||||||
__ jcc(Assembler::zero, L_ok);
|
__ jccb(Assembler::zero, L_ok);
|
||||||
__ bind(L_bad);
|
__ bind(L_bad);
|
||||||
__ stop("assert arg_slots >= 0 and clear low bits");
|
__ stop("assert arg_slots >= 0 and clear low bits");
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
|
@ -258,7 +258,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||||
__ addptr(rdx_temp, -wordSize);
|
__ addptr(rdx_temp, -wordSize);
|
||||||
__ cmpptr(rdx_temp, rsp);
|
__ cmpptr(rdx_temp, rsp);
|
||||||
__ jcc(Assembler::greaterEqual, loop);
|
__ jccb(Assembler::greaterEqual, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now move the argslot up, to point to the just-copied block.
|
// Now move the argslot up, to point to the just-copied block.
|
||||||
|
@ -268,8 +268,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
extern "C" void print_method_handle(oop mh);
|
||||||
void trace_method_handle_stub(const char* adaptername,
|
void trace_method_handle_stub(const char* adaptername,
|
||||||
oopDesc* mh,
|
oop mh,
|
||||||
intptr_t* entry_sp,
|
intptr_t* entry_sp,
|
||||||
intptr_t* saved_sp,
|
intptr_t* saved_sp,
|
||||||
intptr_t* saved_bp) {
|
intptr_t* saved_bp) {
|
||||||
|
@ -280,6 +281,7 @@ void trace_method_handle_stub(const char* adaptername,
|
||||||
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
|
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
|
||||||
if (last_sp != saved_sp)
|
if (last_sp != saved_sp)
|
||||||
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
||||||
|
if (Verbose) print_method_handle(mh);
|
||||||
}
|
}
|
||||||
#endif //PRODUCT
|
#endif //PRODUCT
|
||||||
|
|
||||||
|
@ -382,11 +384,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
|
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
|
||||||
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
|
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
|
||||||
__ testptr(rbx_method, rbx_method);
|
__ testptr(rbx_method, rbx_method);
|
||||||
__ jcc(Assembler::zero, no_method);
|
__ jccb(Assembler::zero, no_method);
|
||||||
int jobject_oop_offset = 0;
|
int jobject_oop_offset = 0;
|
||||||
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
|
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
|
||||||
__ testptr(rbx_method, rbx_method);
|
__ testptr(rbx_method, rbx_method);
|
||||||
__ jcc(Assembler::zero, no_method);
|
__ jccb(Assembler::zero, no_method);
|
||||||
__ verify_oop(rbx_method);
|
__ verify_oop(rbx_method);
|
||||||
__ push(rdi_pc); // and restore caller PC
|
__ push(rdi_pc); // and restore caller PC
|
||||||
__ jmp(rbx_method_fie);
|
__ jmp(rbx_method_fie);
|
||||||
|
@ -533,16 +535,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
if (arg_type == T_OBJECT) {
|
if (arg_type == T_OBJECT) {
|
||||||
__ movptr(Address(rax_argslot, 0), rbx_temp);
|
__ movptr(Address(rax_argslot, 0), rbx_temp);
|
||||||
} else {
|
} else {
|
||||||
__ load_sized_value(rbx_temp, prim_value_addr,
|
__ load_sized_value(rdx_temp, prim_value_addr,
|
||||||
type2aelembytes(arg_type), is_signed_subword_type(arg_type));
|
type2aelembytes(arg_type), is_signed_subword_type(arg_type));
|
||||||
__ movptr(Address(rax_argslot, 0), rbx_temp);
|
__ movptr(Address(rax_argslot, 0), rdx_temp);
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
if (arg_slots == 2) {
|
if (arg_slots == 2) {
|
||||||
__ movl(rbx_temp, prim_value_addr.plus_disp(wordSize));
|
__ movl(rdx_temp, prim_value_addr.plus_disp(wordSize));
|
||||||
__ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp);
|
__ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp);
|
||||||
}
|
}
|
||||||
#endif //_LP64
|
#endif //_LP64
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direct_to_method) {
|
if (direct_to_method) {
|
||||||
|
@ -584,7 +585,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
Label done;
|
Label done;
|
||||||
__ movptr(rdx_temp, vmarg);
|
__ movptr(rdx_temp, vmarg);
|
||||||
__ testl(rdx_temp, rdx_temp);
|
__ testl(rdx_temp, rdx_temp);
|
||||||
__ jcc(Assembler::zero, done); // no cast if null
|
__ jccb(Assembler::zero, done); // no cast if null
|
||||||
__ load_klass(rdx_temp, rdx_temp);
|
__ load_klass(rdx_temp, rdx_temp);
|
||||||
|
|
||||||
// live at this point:
|
// live at this point:
|
||||||
|
@ -675,24 +676,24 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
// (now we are done with the old MH)
|
// (now we are done with the old MH)
|
||||||
|
|
||||||
// original 32-bit vmdata word must be of this form:
|
// original 32-bit vmdata word must be of this form:
|
||||||
// | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
|
// | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
|
||||||
__ xchgl(rcx, rbx_vminfo); // free rcx for shifts
|
__ xchgptr(rcx, rbx_vminfo); // free rcx for shifts
|
||||||
__ shll(rdx_temp /*, rcx*/);
|
__ shll(rdx_temp /*, rcx*/);
|
||||||
Label zero_extend, done;
|
Label zero_extend, done;
|
||||||
__ testl(rcx, CONV_VMINFO_SIGN_FLAG);
|
__ testl(rcx, CONV_VMINFO_SIGN_FLAG);
|
||||||
__ jcc(Assembler::zero, zero_extend);
|
__ jccb(Assembler::zero, zero_extend);
|
||||||
|
|
||||||
// this path is taken for int->byte, int->short
|
// this path is taken for int->byte, int->short
|
||||||
__ sarl(rdx_temp /*, rcx*/);
|
__ sarl(rdx_temp /*, rcx*/);
|
||||||
__ jmp(done);
|
__ jmpb(done);
|
||||||
|
|
||||||
__ bind(zero_extend);
|
__ bind(zero_extend);
|
||||||
// this is taken for int->char
|
// this is taken for int->char
|
||||||
__ shrl(rdx_temp /*, rcx*/);
|
__ shrl(rdx_temp /*, rcx*/);
|
||||||
|
|
||||||
__ bind(done);
|
__ bind(done);
|
||||||
__ movptr(vmarg, rdx_temp);
|
__ movl(vmarg, rdx_temp);
|
||||||
__ xchgl(rcx, rbx_vminfo); // restore rcx_recv
|
__ xchgptr(rcx, rbx_vminfo); // restore rcx_recv
|
||||||
|
|
||||||
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
||||||
}
|
}
|
||||||
|
@ -861,7 +862,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
// Verify that argslot > destslot, by at least swap_bytes.
|
// Verify that argslot > destslot, by at least swap_bytes.
|
||||||
Label L_ok;
|
Label L_ok;
|
||||||
__ cmpptr(rax_argslot, rbx_destslot);
|
__ cmpptr(rax_argslot, rbx_destslot);
|
||||||
__ jcc(Assembler::aboveEqual, L_ok);
|
__ jccb(Assembler::aboveEqual, L_ok);
|
||||||
__ stop("source must be above destination (upward rotation)");
|
__ stop("source must be above destination (upward rotation)");
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
}
|
}
|
||||||
|
@ -877,7 +878,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
__ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
|
__ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
|
||||||
__ addptr(rax_argslot, -wordSize);
|
__ addptr(rax_argslot, -wordSize);
|
||||||
__ cmpptr(rax_argslot, rbx_destslot);
|
__ cmpptr(rax_argslot, rbx_destslot);
|
||||||
__ jcc(Assembler::aboveEqual, loop);
|
__ jccb(Assembler::aboveEqual, loop);
|
||||||
} else {
|
} else {
|
||||||
__ addptr(rax_argslot, swap_bytes);
|
__ addptr(rax_argslot, swap_bytes);
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -885,7 +886,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
// Verify that argslot < destslot, by at least swap_bytes.
|
// Verify that argslot < destslot, by at least swap_bytes.
|
||||||
Label L_ok;
|
Label L_ok;
|
||||||
__ cmpptr(rax_argslot, rbx_destslot);
|
__ cmpptr(rax_argslot, rbx_destslot);
|
||||||
__ jcc(Assembler::belowEqual, L_ok);
|
__ jccb(Assembler::belowEqual, L_ok);
|
||||||
__ stop("source must be below destination (downward rotation)");
|
__ stop("source must be below destination (downward rotation)");
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
}
|
}
|
||||||
|
@ -901,7 +902,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
__ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
|
__ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
|
||||||
__ addptr(rax_argslot, wordSize);
|
__ addptr(rax_argslot, wordSize);
|
||||||
__ cmpptr(rax_argslot, rbx_destslot);
|
__ cmpptr(rax_argslot, rbx_destslot);
|
||||||
__ jcc(Assembler::belowEqual, loop);
|
__ jccb(Assembler::belowEqual, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pop the original first chunk into the destination slot, now free
|
// pop the original first chunk into the destination slot, now free
|
||||||
|
@ -967,7 +968,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
__ addptr(rax_argslot, wordSize);
|
__ addptr(rax_argslot, wordSize);
|
||||||
__ addptr(rdx_newarg, wordSize);
|
__ addptr(rdx_newarg, wordSize);
|
||||||
__ cmpptr(rdx_newarg, rbx_oldarg);
|
__ cmpptr(rdx_newarg, rbx_oldarg);
|
||||||
__ jcc(Assembler::less, loop);
|
__ jccb(Assembler::less, loop);
|
||||||
|
|
||||||
__ pop(rdi); // restore temp
|
__ pop(rdi); // restore temp
|
||||||
|
|
||||||
|
@ -1119,7 +1120,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||||
}
|
}
|
||||||
__ addptr(rax_argslot, Interpreter::stackElementSize());
|
__ addptr(rax_argslot, Interpreter::stackElementSize());
|
||||||
__ cmpptr(rax_argslot, rdx_argslot_limit);
|
__ cmpptr(rax_argslot, rdx_argslot_limit);
|
||||||
__ jcc(Assembler::less, loop);
|
__ jccb(Assembler::less, loop);
|
||||||
} else if (length_constant == 0) {
|
} else if (length_constant == 0) {
|
||||||
__ bind(skip_array_check);
|
__ bind(skip_array_check);
|
||||||
// nothing to copy
|
// nothing to copy
|
||||||
|
|
|
@ -43,11 +43,11 @@ ExceptionBlob* OptoRuntime::_exception_blob;
|
||||||
// This code is entered with a jmp.
|
// This code is entered with a jmp.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// rax,: exception oop
|
// rax: exception oop
|
||||||
// rdx: exception pc
|
// rdx: exception pc
|
||||||
//
|
//
|
||||||
// Results:
|
// Results:
|
||||||
// rax,: exception oop
|
// rax: exception oop
|
||||||
// rdx: exception pc in caller or ???
|
// rdx: exception pc in caller or ???
|
||||||
// destination: exception handler of caller
|
// destination: exception handler of caller
|
||||||
//
|
//
|
||||||
|
@ -113,17 +113,17 @@ void OptoRuntime::generate_exception_blob() {
|
||||||
__ addptr(rsp, return_off * wordSize); // Epilog!
|
__ addptr(rsp, return_off * wordSize); // Epilog!
|
||||||
__ pop(rdx); // Exception pc
|
__ pop(rdx); // Exception pc
|
||||||
|
|
||||||
|
// rax: exception handler for given <exception oop/exception pc>
|
||||||
|
|
||||||
// rax,: exception handler for given <exception oop/exception pc>
|
// Restore SP from BP if the exception PC is a MethodHandle call.
|
||||||
|
__ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0);
|
||||||
|
__ cmovptr(Assembler::notEqual, rsp, rbp);
|
||||||
|
|
||||||
// We have a handler in rax, (could be deopt blob)
|
// We have a handler in rax, (could be deopt blob)
|
||||||
// rdx - throwing pc, deopt blob will need it.
|
// rdx - throwing pc, deopt blob will need it.
|
||||||
|
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
|
|
||||||
// rcx contains handler address
|
|
||||||
|
|
||||||
__ get_thread(rcx); // TLS
|
|
||||||
// Get the exception
|
// Get the exception
|
||||||
__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));
|
__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));
|
||||||
// Get the exception pc in case we are deoptimized
|
// Get the exception pc in case we are deoptimized
|
||||||
|
@ -137,7 +137,7 @@ void OptoRuntime::generate_exception_blob() {
|
||||||
|
|
||||||
__ pop(rcx);
|
__ pop(rcx);
|
||||||
|
|
||||||
// rax,: exception oop
|
// rax: exception oop
|
||||||
// rcx: exception handler
|
// rcx: exception handler
|
||||||
// rdx: exception pc
|
// rdx: exception pc
|
||||||
__ jmp (rcx);
|
__ jmp (rcx);
|
||||||
|
|
|
@ -638,6 +638,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
|
|
||||||
__ movptr(rax, Address(rsp, 0));
|
__ movptr(rax, Address(rsp, 0));
|
||||||
|
|
||||||
|
// Must preserve original SP for loading incoming arguments because
|
||||||
|
// we need to align the outgoing SP for compiled code.
|
||||||
|
__ movptr(r11, rsp);
|
||||||
|
|
||||||
// Cut-out for having no stack args. Since up to 2 int/oop args are passed
|
// Cut-out for having no stack args. Since up to 2 int/oop args are passed
|
||||||
// in registers, we will occasionally have no stack args.
|
// in registers, we will occasionally have no stack args.
|
||||||
int comp_words_on_stack = 0;
|
int comp_words_on_stack = 0;
|
||||||
|
@ -661,6 +665,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
// as far as the placement of the call instruction
|
// as far as the placement of the call instruction
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
|
|
||||||
|
// Put saved SP in another register
|
||||||
|
const Register saved_sp = rax;
|
||||||
|
__ movptr(saved_sp, r11);
|
||||||
|
|
||||||
// Will jump to the compiled code just as if compiled code was doing it.
|
// Will jump to the compiled code just as if compiled code was doing it.
|
||||||
// Pre-load the register-jump target early, to schedule it better.
|
// Pre-load the register-jump target early, to schedule it better.
|
||||||
__ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset())));
|
__ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset())));
|
||||||
|
@ -680,11 +688,7 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(),
|
assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(),
|
||||||
"scrambled load targets?");
|
"scrambled load targets?");
|
||||||
// Load in argument order going down.
|
// Load in argument order going down.
|
||||||
// int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize;
|
int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes();
|
||||||
// base ld_off on r13 (sender_sp) as the stack alignment makes offsets from rsp
|
|
||||||
// unpredictable
|
|
||||||
int ld_off = ((total_args_passed - 1) - i)*Interpreter::stackElementSize();
|
|
||||||
|
|
||||||
// Point to interpreter value (vs. tag)
|
// Point to interpreter value (vs. tag)
|
||||||
int next_off = ld_off - Interpreter::stackElementSize();
|
int next_off = ld_off - Interpreter::stackElementSize();
|
||||||
//
|
//
|
||||||
|
@ -699,10 +703,14 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
if (r_1->is_stack()) {
|
if (r_1->is_stack()) {
|
||||||
// Convert stack slot to an SP offset (+ wordSize to account for return address )
|
// Convert stack slot to an SP offset (+ wordSize to account for return address )
|
||||||
int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize;
|
int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize;
|
||||||
|
|
||||||
|
// We can use r13 as a temp here because compiled code doesn't need r13 as an input
|
||||||
|
// and if we end up going thru a c2i because of a miss a reasonable value of r13
|
||||||
|
// will be generated.
|
||||||
if (!r_2->is_valid()) {
|
if (!r_2->is_valid()) {
|
||||||
// sign extend???
|
// sign extend???
|
||||||
__ movl(rax, Address(r13, ld_off));
|
__ movl(r13, Address(saved_sp, ld_off));
|
||||||
__ movptr(Address(rsp, st_off), rax);
|
__ movptr(Address(rsp, st_off), r13);
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE
|
// We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE
|
||||||
|
@ -715,9 +723,9 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
// ld_off is MSW so get LSW
|
// ld_off is MSW so get LSW
|
||||||
const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)?
|
const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)?
|
||||||
next_off : ld_off;
|
next_off : ld_off;
|
||||||
__ movq(rax, Address(r13, offset));
|
__ movq(r13, Address(saved_sp, offset));
|
||||||
// st_off is LSW (i.e. reg.first())
|
// st_off is LSW (i.e. reg.first())
|
||||||
__ movq(Address(rsp, st_off), rax);
|
__ movq(Address(rsp, st_off), r13);
|
||||||
}
|
}
|
||||||
} else if (r_1->is_Register()) { // Register argument
|
} else if (r_1->is_Register()) { // Register argument
|
||||||
Register r = r_1->as_Register();
|
Register r = r_1->as_Register();
|
||||||
|
@ -732,16 +740,16 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||||
next_off : ld_off;
|
next_off : ld_off;
|
||||||
|
|
||||||
// this can be a misaligned move
|
// this can be a misaligned move
|
||||||
__ movq(r, Address(r13, offset));
|
__ movq(r, Address(saved_sp, offset));
|
||||||
} else {
|
} else {
|
||||||
// sign extend and use a full word?
|
// sign extend and use a full word?
|
||||||
__ movl(r, Address(r13, ld_off));
|
__ movl(r, Address(saved_sp, ld_off));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!r_2->is_valid()) {
|
if (!r_2->is_valid()) {
|
||||||
__ movflt(r_1->as_XMMRegister(), Address(r13, ld_off));
|
__ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off));
|
||||||
} else {
|
} else {
|
||||||
__ movdbl(r_1->as_XMMRegister(), Address(r13, next_off));
|
__ movdbl(r_1->as_XMMRegister(), Address(saved_sp, next_off));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3319,6 +3327,10 @@ void OptoRuntime::generate_exception_blob() {
|
||||||
|
|
||||||
// rax: exception handler
|
// rax: exception handler
|
||||||
|
|
||||||
|
// Restore SP from BP if the exception PC is a MethodHandle call.
|
||||||
|
__ cmpl(Address(r15_thread, JavaThread::is_method_handle_exception_offset()), 0);
|
||||||
|
__ cmovptr(Assembler::notEqual, rsp, rbp);
|
||||||
|
|
||||||
// We have a handler in rax (could be deopt blob).
|
// We have a handler in rax (could be deopt blob).
|
||||||
__ mov(r8, rax);
|
__ mov(r8, rax);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2030,6 +2030,54 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
entry_checkcast_arraycopy);
|
entry_checkcast_arraycopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generate_math_stubs() {
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "log");
|
||||||
|
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ fld_d(Address(rsp, 4));
|
||||||
|
__ flog();
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "log10");
|
||||||
|
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ fld_d(Address(rsp, 4));
|
||||||
|
__ flog10();
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "sin");
|
||||||
|
StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ fld_d(Address(rsp, 4));
|
||||||
|
__ trigfunc('s');
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "cos");
|
||||||
|
StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ fld_d(Address(rsp, 4));
|
||||||
|
__ trigfunc('c');
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "tan");
|
||||||
|
StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ fld_d(Address(rsp, 4));
|
||||||
|
__ trigfunc('t');
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The intrinsic version of these seem to return the same value as
|
||||||
|
// the strict version.
|
||||||
|
StubRoutines::_intrinsic_exp = SharedRuntime::dexp;
|
||||||
|
StubRoutines::_intrinsic_pow = SharedRuntime::dpow;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Information about frame layout at time of blocking runtime call.
|
// Information about frame layout at time of blocking runtime call.
|
||||||
// Note that we only have to preserve callee-saved registers since
|
// Note that we only have to preserve callee-saved registers since
|
||||||
|
@ -2228,6 +2276,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
MethodHandles::generate_method_handle_stub(_masm, ek);
|
MethodHandles::generate_method_handle_stub(_masm, ek);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_math_stubs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2731,6 +2731,79 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy;
|
StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generate_math_stubs() {
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "log");
|
||||||
|
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ subq(rsp, 8);
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
__ flog();
|
||||||
|
__ fstp_d(Address(rsp, 0));
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
__ addq(rsp, 8);
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "log10");
|
||||||
|
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ subq(rsp, 8);
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
__ flog10();
|
||||||
|
__ fstp_d(Address(rsp, 0));
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
__ addq(rsp, 8);
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "sin");
|
||||||
|
StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ subq(rsp, 8);
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
__ trigfunc('s');
|
||||||
|
__ fstp_d(Address(rsp, 0));
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
__ addq(rsp, 8);
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "cos");
|
||||||
|
StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ subq(rsp, 8);
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
__ trigfunc('c');
|
||||||
|
__ fstp_d(Address(rsp, 0));
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
__ addq(rsp, 8);
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "tan");
|
||||||
|
StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc();
|
||||||
|
|
||||||
|
__ subq(rsp, 8);
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
__ trigfunc('t');
|
||||||
|
__ fstp_d(Address(rsp, 0));
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
__ addq(rsp, 8);
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The intrinsic version of these seem to return the same value as
|
||||||
|
// the strict version.
|
||||||
|
StubRoutines::_intrinsic_exp = SharedRuntime::dexp;
|
||||||
|
StubRoutines::_intrinsic_pow = SharedRuntime::dpow;
|
||||||
|
}
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
#define __ masm->
|
#define __ masm->
|
||||||
|
|
||||||
|
@ -2945,6 +3018,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
MethodHandles::generate_method_handle_stub(_masm, ek);
|
MethodHandles::generate_method_handle_stub(_masm, ek);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_math_stubs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1431,6 +1431,23 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These should never be compiled since the interpreter will prefer
|
||||||
|
// the compiled version to the intrinsic version.
|
||||||
|
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
|
||||||
|
switch (method_kind(m)) {
|
||||||
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
|
case Interpreter::java_lang_math_tan : // fall thru
|
||||||
|
case Interpreter::java_lang_math_abs : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log10 : // fall thru
|
||||||
|
case Interpreter::java_lang_math_sqrt :
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// How much stack a method activation needs in words.
|
// How much stack a method activation needs in words.
|
||||||
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
||||||
|
|
||||||
|
@ -1488,6 +1505,9 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
||||||
|
|
||||||
if (interpreter_frame != NULL) {
|
if (interpreter_frame != NULL) {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
if (!EnableMethodHandles)
|
||||||
|
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
|
||||||
|
// Probably, since deoptimization doesn't work yet.
|
||||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
||||||
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -449,8 +449,12 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
||||||
__ addptr(rax, stack_base);
|
__ addptr(rax, stack_base);
|
||||||
__ subptr(rax, stack_size);
|
__ subptr(rax, stack_size);
|
||||||
|
|
||||||
|
// Use the maximum number of pages we might bang.
|
||||||
|
const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
|
||||||
|
(StackRedPages+StackYellowPages);
|
||||||
|
|
||||||
// add in the red and yellow zone sizes
|
// add in the red and yellow zone sizes
|
||||||
__ addptr(rax, (StackRedPages + StackYellowPages) * page_size);
|
__ addptr(rax, max_pages * page_size);
|
||||||
|
|
||||||
// check against the current stack bottom
|
// check against the current stack bottom
|
||||||
__ cmpptr(rsp, rax);
|
__ cmpptr(rsp, rax);
|
||||||
|
@ -1452,6 +1456,23 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
||||||
generate_normal_entry(synchronized);
|
generate_normal_entry(synchronized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These should never be compiled since the interpreter will prefer
|
||||||
|
// the compiled version to the intrinsic version.
|
||||||
|
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
|
||||||
|
switch (method_kind(m)) {
|
||||||
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
|
case Interpreter::java_lang_math_tan : // fall thru
|
||||||
|
case Interpreter::java_lang_math_abs : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log10 : // fall thru
|
||||||
|
case Interpreter::java_lang_math_sqrt :
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// How much stack a method activation needs in words.
|
// How much stack a method activation needs in words.
|
||||||
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
||||||
const int entry_size = frame::interpreter_frame_monitor_size();
|
const int entry_size = frame::interpreter_frame_monitor_size();
|
||||||
|
@ -1502,8 +1523,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
||||||
tempcount* Interpreter::stackElementWords() + popframe_extra_args;
|
tempcount* Interpreter::stackElementWords() + popframe_extra_args;
|
||||||
if (interpreter_frame != NULL) {
|
if (interpreter_frame != NULL) {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(),
|
if (!EnableMethodHandles)
|
||||||
"Frame not properly walkable");
|
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
|
||||||
|
// Probably, since deoptimization doesn't work yet.
|
||||||
|
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
||||||
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -268,22 +268,36 @@ static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CON
|
||||||
static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
|
static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
|
||||||
static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
|
static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
|
||||||
|
|
||||||
|
// Offset hacking within calls.
|
||||||
|
static int pre_call_FPU_size() {
|
||||||
|
if (Compile::current()->in_24_bit_fp_mode())
|
||||||
|
return 6; // fldcw
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int preserve_SP_size() {
|
||||||
|
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
|
||||||
|
}
|
||||||
|
|
||||||
// !!!!! Special hack to get all type of calls to specify the byte offset
|
// !!!!! Special hack to get all type of calls to specify the byte offset
|
||||||
// from the start of the call to the point where the return address
|
// from the start of the call to the point where the return address
|
||||||
// will point.
|
// will point.
|
||||||
int MachCallStaticJavaNode::ret_addr_offset() {
|
int MachCallStaticJavaNode::ret_addr_offset() {
|
||||||
return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points
|
int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points
|
||||||
|
if (_method_handle_invoke)
|
||||||
|
offset += preserve_SP_size();
|
||||||
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachCallDynamicJavaNode::ret_addr_offset() {
|
int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||||
return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points
|
return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sizeof_FFree_Float_Stack_All = -1;
|
static int sizeof_FFree_Float_Stack_All = -1;
|
||||||
|
|
||||||
int MachCallRuntimeNode::ret_addr_offset() {
|
int MachCallRuntimeNode::ret_addr_offset() {
|
||||||
assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
|
assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
|
||||||
return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0);
|
return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicate if the safepoint node needs the polling page as an input.
|
// Indicate if the safepoint node needs the polling page as an input.
|
||||||
|
@ -299,8 +313,16 @@ bool SafePointNode::needs_polling_address_input() {
|
||||||
// The address of the call instruction needs to be 4-byte aligned to
|
// The address of the call instruction needs to be 4-byte aligned to
|
||||||
// ensure that it does not span a cache line so that it can be patched.
|
// ensure that it does not span a cache line so that it can be patched.
|
||||||
int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
|
int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
|
||||||
if (Compile::current()->in_24_bit_fp_mode())
|
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||||
current_offset += 6; // skip fldcw in pre_call_FPU, if any
|
current_offset += 1; // skip call opcode byte
|
||||||
|
return round_to(current_offset, alignment_required()) - current_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The address of the call instruction needs to be 4-byte aligned to
|
||||||
|
// ensure that it does not span a cache line so that it can be patched.
|
||||||
|
int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
|
||||||
|
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||||
|
current_offset += preserve_SP_size(); // skip mov rbp, rsp
|
||||||
current_offset += 1; // skip call opcode byte
|
current_offset += 1; // skip call opcode byte
|
||||||
return round_to(current_offset, alignment_required()) - current_offset;
|
return round_to(current_offset, alignment_required()) - current_offset;
|
||||||
}
|
}
|
||||||
|
@ -308,8 +330,7 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
|
||||||
// The address of the call instruction needs to be 4-byte aligned to
|
// The address of the call instruction needs to be 4-byte aligned to
|
||||||
// ensure that it does not span a cache line so that it can be patched.
|
// ensure that it does not span a cache line so that it can be patched.
|
||||||
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
|
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
|
||||||
if (Compile::current()->in_24_bit_fp_mode())
|
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||||
current_offset += 6; // skip fldcw in pre_call_FPU, if any
|
|
||||||
current_offset += 5; // skip MOV instruction
|
current_offset += 5; // skip MOV instruction
|
||||||
current_offset += 1; // skip call opcode byte
|
current_offset += 1; // skip call opcode byte
|
||||||
return round_to(current_offset, alignment_required()) - current_offset;
|
return round_to(current_offset, alignment_required()) - current_offset;
|
||||||
|
@ -1460,6 +1481,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||||
return RegMask();
|
return RegMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||||
|
return EBP_REG_mask;
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//----------ENCODING BLOCK-----------------------------------------------------
|
//----------ENCODING BLOCK-----------------------------------------------------
|
||||||
|
@ -1772,10 +1797,13 @@ encode %{
|
||||||
|
|
||||||
enc_class pre_call_FPU %{
|
enc_class pre_call_FPU %{
|
||||||
// If method sets FPU control word restore it here
|
// If method sets FPU control word restore it here
|
||||||
|
debug_only(int off0 = cbuf.code_size());
|
||||||
if( Compile::current()->in_24_bit_fp_mode() ) {
|
if( Compile::current()->in_24_bit_fp_mode() ) {
|
||||||
MacroAssembler masm(&cbuf);
|
MacroAssembler masm(&cbuf);
|
||||||
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
|
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
|
||||||
}
|
}
|
||||||
|
debug_only(int off1 = cbuf.code_size());
|
||||||
|
assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction");
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class post_call_FPU %{
|
enc_class post_call_FPU %{
|
||||||
|
@ -1786,6 +1814,21 @@ encode %{
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
enc_class preserve_SP %{
|
||||||
|
debug_only(int off0 = cbuf.code_size());
|
||||||
|
MacroAssembler _masm(&cbuf);
|
||||||
|
// RBP is preserved across all calls, even compiled calls.
|
||||||
|
// Use it to preserve RSP in places where the callee might change the SP.
|
||||||
|
__ movptr(rbp, rsp);
|
||||||
|
debug_only(int off1 = cbuf.code_size());
|
||||||
|
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||||
|
%}
|
||||||
|
|
||||||
|
enc_class restore_SP %{
|
||||||
|
MacroAssembler _masm(&cbuf);
|
||||||
|
__ movptr(rsp, rbp);
|
||||||
|
%}
|
||||||
|
|
||||||
enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
|
enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
|
||||||
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
|
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
|
||||||
// who we intended to call.
|
// who we intended to call.
|
||||||
|
@ -13406,6 +13449,7 @@ instruct cmovXX_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regX dst,
|
||||||
// compute_padding() functions will have to be adjusted.
|
// compute_padding() functions will have to be adjusted.
|
||||||
instruct CallStaticJavaDirect(method meth) %{
|
instruct CallStaticJavaDirect(method meth) %{
|
||||||
match(CallStaticJava);
|
match(CallStaticJava);
|
||||||
|
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||||
effect(USE meth);
|
effect(USE meth);
|
||||||
|
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
|
@ -13420,6 +13464,30 @@ instruct CallStaticJavaDirect(method meth) %{
|
||||||
ins_alignment(4);
|
ins_alignment(4);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// Call Java Static Instruction (method handle version)
|
||||||
|
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||||
|
// compute_padding() functions will have to be adjusted.
|
||||||
|
instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{
|
||||||
|
match(CallStaticJava);
|
||||||
|
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||||
|
effect(USE meth);
|
||||||
|
// EBP is saved by all callees (for interpreter stack correction).
|
||||||
|
// We use it here for a similar purpose, in {preserve,restore}_SP.
|
||||||
|
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "CALL,static/MethodHandle " %}
|
||||||
|
opcode(0xE8); /* E8 cd */
|
||||||
|
ins_encode( pre_call_FPU,
|
||||||
|
preserve_SP,
|
||||||
|
Java_Static_Call( meth ),
|
||||||
|
restore_SP,
|
||||||
|
call_epilog,
|
||||||
|
post_call_FPU );
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
ins_pc_relative(1);
|
||||||
|
ins_alignment(4);
|
||||||
|
%}
|
||||||
|
|
||||||
// Call Java Dynamic Instruction
|
// Call Java Dynamic Instruction
|
||||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||||
// compute_padding() functions will have to be adjusted.
|
// compute_padding() functions will have to be adjusted.
|
||||||
|
|
|
@ -551,12 +551,19 @@ source %{
|
||||||
|
|
||||||
#define __ _masm.
|
#define __ _masm.
|
||||||
|
|
||||||
|
static int preserve_SP_size() {
|
||||||
|
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
|
||||||
|
}
|
||||||
|
|
||||||
// !!!!! Special hack to get all types of calls to specify the byte offset
|
// !!!!! Special hack to get all types of calls to specify the byte offset
|
||||||
// from the start of the call to the point where the return address
|
// from the start of the call to the point where the return address
|
||||||
// will point.
|
// will point.
|
||||||
int MachCallStaticJavaNode::ret_addr_offset()
|
int MachCallStaticJavaNode::ret_addr_offset()
|
||||||
{
|
{
|
||||||
return 5; // 5 bytes from start of call to where return address points
|
int offset = 5; // 5 bytes from start of call to where return address points
|
||||||
|
if (_method_handle_invoke)
|
||||||
|
offset += preserve_SP_size();
|
||||||
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachCallDynamicJavaNode::ret_addr_offset()
|
int MachCallDynamicJavaNode::ret_addr_offset()
|
||||||
|
@ -587,6 +594,15 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const
|
||||||
return round_to(current_offset, alignment_required()) - current_offset;
|
return round_to(current_offset, alignment_required()) - current_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The address of the call instruction needs to be 4-byte aligned to
|
||||||
|
// ensure that it does not span a cache line so that it can be patched.
|
||||||
|
int CallStaticJavaHandleNode::compute_padding(int current_offset) const
|
||||||
|
{
|
||||||
|
current_offset += preserve_SP_size(); // skip mov rbp, rsp
|
||||||
|
current_offset += 1; // skip call opcode byte
|
||||||
|
return round_to(current_offset, alignment_required()) - current_offset;
|
||||||
|
}
|
||||||
|
|
||||||
// The address of the call instruction needs to be 4-byte aligned to
|
// The address of the call instruction needs to be 4-byte aligned to
|
||||||
// ensure that it does not span a cache line so that it can be patched.
|
// ensure that it does not span a cache line so that it can be patched.
|
||||||
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
|
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
|
||||||
|
@ -2113,6 +2129,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||||
return LONG_RDX_REG_mask;
|
return LONG_RDX_REG_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||||
|
return PTR_RBP_REG_mask;
|
||||||
|
}
|
||||||
|
|
||||||
static Address build_address(int b, int i, int s, int d) {
|
static Address build_address(int b, int i, int s, int d) {
|
||||||
Register index = as_Register(i);
|
Register index = as_Register(i);
|
||||||
Address::ScaleFactor scale = (Address::ScaleFactor)s;
|
Address::ScaleFactor scale = (Address::ScaleFactor)s;
|
||||||
|
@ -2608,6 +2628,21 @@ encode %{
|
||||||
RELOC_DISP32);
|
RELOC_DISP32);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
enc_class preserve_SP %{
|
||||||
|
debug_only(int off0 = cbuf.code_size());
|
||||||
|
MacroAssembler _masm(&cbuf);
|
||||||
|
// RBP is preserved across all calls, even compiled calls.
|
||||||
|
// Use it to preserve RSP in places where the callee might change the SP.
|
||||||
|
__ movptr(rbp, rsp);
|
||||||
|
debug_only(int off1 = cbuf.code_size());
|
||||||
|
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||||
|
%}
|
||||||
|
|
||||||
|
enc_class restore_SP %{
|
||||||
|
MacroAssembler _masm(&cbuf);
|
||||||
|
__ movptr(rsp, rbp);
|
||||||
|
%}
|
||||||
|
|
||||||
enc_class Java_Static_Call(method meth)
|
enc_class Java_Static_Call(method meth)
|
||||||
%{
|
%{
|
||||||
// JAVA STATIC CALL
|
// JAVA STATIC CALL
|
||||||
|
@ -12526,9 +12561,9 @@ instruct safePoint_poll(rFlagsReg cr)
|
||||||
// Call Java Static Instruction
|
// Call Java Static Instruction
|
||||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||||
// compute_padding() functions will have to be adjusted.
|
// compute_padding() functions will have to be adjusted.
|
||||||
instruct CallStaticJavaDirect(method meth)
|
instruct CallStaticJavaDirect(method meth) %{
|
||||||
%{
|
|
||||||
match(CallStaticJava);
|
match(CallStaticJava);
|
||||||
|
predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke());
|
||||||
effect(USE meth);
|
effect(USE meth);
|
||||||
|
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
|
@ -12540,6 +12575,28 @@ instruct CallStaticJavaDirect(method meth)
|
||||||
ins_alignment(4);
|
ins_alignment(4);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// Call Java Static Instruction (method handle version)
|
||||||
|
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||||
|
// compute_padding() functions will have to be adjusted.
|
||||||
|
instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{
|
||||||
|
match(CallStaticJava);
|
||||||
|
predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke());
|
||||||
|
effect(USE meth);
|
||||||
|
// RBP is saved by all callees (for interpreter stack correction).
|
||||||
|
// We use it here for a similar purpose, in {preserve,restore}_SP.
|
||||||
|
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "call,static/MethodHandle " %}
|
||||||
|
opcode(0xE8); /* E8 cd */
|
||||||
|
ins_encode(preserve_SP,
|
||||||
|
Java_Static_Call(meth),
|
||||||
|
restore_SP,
|
||||||
|
call_epilog);
|
||||||
|
ins_pipe(pipe_slow);
|
||||||
|
ins_pc_relative(1);
|
||||||
|
ins_alignment(4);
|
||||||
|
%}
|
||||||
|
|
||||||
// Call Java Dynamic Instruction
|
// Call Java Dynamic Instruction
|
||||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||||
// compute_padding() functions will have to be adjusted.
|
// compute_padding() functions will have to be adjusted.
|
||||||
|
|
|
@ -245,7 +245,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||||
if (handlerAddr == NULL) {
|
if (handlerAddr == NULL) {
|
||||||
CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
|
CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
|
||||||
if (HAS_PENDING_EXCEPTION)
|
if (HAS_PENDING_EXCEPTION)
|
||||||
goto unwind_and_return;
|
goto unlock_unwind_and_return;
|
||||||
|
|
||||||
handlerAddr = method->signature_handler();
|
handlerAddr = method->signature_handler();
|
||||||
assert(handlerAddr != NULL, "eh?");
|
assert(handlerAddr != NULL, "eh?");
|
||||||
|
@ -254,7 +254,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||||
CALL_VM_NOCHECK(handlerAddr =
|
CALL_VM_NOCHECK(handlerAddr =
|
||||||
InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL));
|
InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL));
|
||||||
if (HAS_PENDING_EXCEPTION)
|
if (HAS_PENDING_EXCEPTION)
|
||||||
goto unwind_and_return;
|
goto unlock_unwind_and_return;
|
||||||
}
|
}
|
||||||
handler = \
|
handler = \
|
||||||
InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
|
InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
|
||||||
|
@ -365,10 +365,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||||
// Reset handle block
|
// Reset handle block
|
||||||
thread->active_handles()->clear();
|
thread->active_handles()->clear();
|
||||||
|
|
||||||
// Unlock if necessary. It seems totally wrong that this
|
unlock_unwind_and_return:
|
||||||
// is skipped in the event of an exception but apparently
|
|
||||||
// the template interpreter does this so we do too.
|
// Unlock if necessary
|
||||||
if (monitor && !HAS_PENDING_EXCEPTION) {
|
if (monitor) {
|
||||||
BasicLock *lock = monitor->lock();
|
BasicLock *lock = monitor->lock();
|
||||||
markOop header = lock->displaced_header();
|
markOop header = lock->displaced_header();
|
||||||
oop rcvr = monitor->obj();
|
oop rcvr = monitor->obj();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* Copyright 2007, 2008 Red Hat, Inc.
|
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -239,7 +239,21 @@ void os::Linux::set_fpu_control_word(int fpu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os::is_allocatable(size_t bytes) {
|
bool os::is_allocatable(size_t bytes) {
|
||||||
ShouldNotCallThis();
|
#ifdef _LP64
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if (bytes < 2 * G) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* addr = reserve_memory(bytes, NULL);
|
||||||
|
|
||||||
|
if (addr != NULL) {
|
||||||
|
release_memory(addr, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr != NULL;
|
||||||
|
#endif // _LP64
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -252,7 +252,8 @@ class IRScopeDebugInfo: public CompilationResourceObj {
|
||||||
DebugToken* monvals = recorder->create_monitor_values(monitors());
|
DebugToken* monvals = recorder->create_monitor_values(monitors());
|
||||||
// reexecute allowed only for the topmost frame
|
// reexecute allowed only for the topmost frame
|
||||||
bool reexecute = topmost ? should_reexecute() : false;
|
bool reexecute = topmost ? should_reexecute() : false;
|
||||||
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, locvals, expvals, monvals);
|
bool is_method_handle_invoke = false;
|
||||||
|
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2000,7 +2000,7 @@ class LIR_OpVisitState: public StackObj {
|
||||||
typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode;
|
typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
maxNumberOfOperands = 14,
|
maxNumberOfOperands = 16,
|
||||||
maxNumberOfInfos = 4
|
maxNumberOfInfos = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -425,7 +425,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
|
||||||
assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
|
assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
|
||||||
assert(exception->is_oop(), "just checking");
|
assert(exception->is_oop(), "just checking");
|
||||||
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError
|
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError
|
||||||
if (!(exception->is_a(SystemDictionary::throwable_klass()))) {
|
if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
|
||||||
if (ExitVMOnVerifyError) vm_exit(-1);
|
if (ExitVMOnVerifyError) vm_exit(-1);
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
49
hotspot/src/share/vm/ci/ciCPCache.cpp
Normal file
49
hotspot/src/share/vm/ci/ciCPCache.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_ciCPCache.cpp.incl"
|
||||||
|
|
||||||
|
// ciCPCache
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciCPCache::get_f1_offset
|
||||||
|
size_t ciCPCache::get_f1_offset(int index) {
|
||||||
|
// Calculate the offset from the constantPoolCacheOop to the f1
|
||||||
|
// field.
|
||||||
|
ByteSize f1_offset =
|
||||||
|
constantPoolCacheOopDesc::entry_offset(index) +
|
||||||
|
ConstantPoolCacheEntry::f1_offset();
|
||||||
|
|
||||||
|
return in_bytes(f1_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciCPCache::print
|
||||||
|
//
|
||||||
|
// Print debugging information about the cache.
|
||||||
|
void ciCPCache::print() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,20 +22,22 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void PtrQueue::handle_zero_index() {
|
// ciCPCache
|
||||||
assert(0 == _index, "Precondition.");
|
//
|
||||||
// This thread records the full buffer and allocates a new one (while
|
// This class represents a constant pool cache.
|
||||||
// holding the lock if there is one).
|
//
|
||||||
void** buf = _buf;
|
// Note: This class is called ciCPCache as ciConstantPoolCache is used
|
||||||
_buf = qset()->allocate_buffer();
|
// for something different.
|
||||||
_sz = qset()->buffer_size();
|
class ciCPCache : public ciObject {
|
||||||
_index = _sz;
|
public:
|
||||||
assert(0 <= _index && _index <= _sz, "Invariant.");
|
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
|
||||||
if (buf != NULL) {
|
|
||||||
if (_lock) {
|
// What kind of ciObject is this?
|
||||||
locking_enqueue_completed_buffer(buf);
|
bool is_cpcache() const { return true; }
|
||||||
} else {
|
|
||||||
qset()->enqueue_complete_buffer(buf);
|
// Get the offset in bytes from the oop to the f1 field of the
|
||||||
}
|
// requested entry.
|
||||||
}
|
size_t get_f1_offset(int index);
|
||||||
}
|
|
||||||
|
void print();
|
||||||
|
};
|
46
hotspot/src/share/vm/ci/ciCallSite.cpp
Normal file
46
hotspot/src/share/vm/ci/ciCallSite.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_ciCallSite.cpp.incl"
|
||||||
|
|
||||||
|
// ciCallSite
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciCallSite::get_target
|
||||||
|
//
|
||||||
|
// Return the target MethodHandle of this CallSite.
|
||||||
|
ciMethodHandle* ciCallSite::get_target() const {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
oop method_handle_oop = java_dyn_CallSite::target(get_oop());
|
||||||
|
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciCallSite::print
|
||||||
|
//
|
||||||
|
// Print debugging information about the CallSite.
|
||||||
|
void ciCallSite::print() {
|
||||||
|
Unimplemented();
|
||||||
|
}
|
39
hotspot/src/share/vm/ci/ciCallSite.hpp
Normal file
39
hotspot/src/share/vm/ci/ciCallSite.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ciCallSite
|
||||||
|
//
|
||||||
|
// The class represents a java.dyn.CallSite object.
|
||||||
|
class ciCallSite : public ciInstance {
|
||||||
|
public:
|
||||||
|
ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
|
||||||
|
|
||||||
|
// What kind of ciObject is this?
|
||||||
|
bool is_call_site() const { return true; }
|
||||||
|
|
||||||
|
// Return the target MethodHandle of this CallSite.
|
||||||
|
ciMethodHandle* get_target() const;
|
||||||
|
|
||||||
|
void print();
|
||||||
|
};
|
|
@ -25,6 +25,7 @@
|
||||||
class ciEnv;
|
class ciEnv;
|
||||||
class ciObjectFactory;
|
class ciObjectFactory;
|
||||||
class ciConstantPoolCache;
|
class ciConstantPoolCache;
|
||||||
|
class ciCPCache;
|
||||||
|
|
||||||
class ciField;
|
class ciField;
|
||||||
class ciConstant;
|
class ciConstant;
|
||||||
|
@ -42,6 +43,8 @@ class ciTypeFlow;
|
||||||
class ciObject;
|
class ciObject;
|
||||||
class ciNullObject;
|
class ciNullObject;
|
||||||
class ciInstance;
|
class ciInstance;
|
||||||
|
class ciCallSite;
|
||||||
|
class ciMethodHandle;
|
||||||
class ciMethod;
|
class ciMethod;
|
||||||
class ciMethodData;
|
class ciMethodData;
|
||||||
class ciReceiverTypeData; // part of ciMethodData
|
class ciReceiverTypeData; // part of ciMethodData
|
||||||
|
@ -78,6 +81,7 @@ friend class ciObjectFactory;
|
||||||
// Any more access must be given explicitly.
|
// Any more access must be given explicitly.
|
||||||
#define CI_PACKAGE_ACCESS_TO \
|
#define CI_PACKAGE_ACCESS_TO \
|
||||||
friend class ciObjectFactory; \
|
friend class ciObjectFactory; \
|
||||||
|
friend class ciCallSite; \
|
||||||
friend class ciConstantPoolCache; \
|
friend class ciConstantPoolCache; \
|
||||||
friend class ciField; \
|
friend class ciField; \
|
||||||
friend class ciConstant; \
|
friend class ciConstant; \
|
||||||
|
@ -93,6 +97,7 @@ friend class ciNullObject; \
|
||||||
friend class ciInstance; \
|
friend class ciInstance; \
|
||||||
friend class ciMethod; \
|
friend class ciMethod; \
|
||||||
friend class ciMethodData; \
|
friend class ciMethodData; \
|
||||||
|
friend class ciMethodHandle; \
|
||||||
friend class ciReceiverTypeData; \
|
friend class ciReceiverTypeData; \
|
||||||
friend class ciSymbol; \
|
friend class ciSymbol; \
|
||||||
friend class ciArray; \
|
friend class ciArray; \
|
||||||
|
|
|
@ -38,17 +38,9 @@ ciInstanceKlassKlass* ciEnv::_instance_klass_klass_instance;
|
||||||
ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
|
ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
|
||||||
ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance;
|
ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance;
|
||||||
|
|
||||||
ciInstanceKlass* ciEnv::_ArrayStoreException;
|
#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
|
||||||
ciInstanceKlass* ciEnv::_Class;
|
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||||
ciInstanceKlass* ciEnv::_ClassCastException;
|
#undef WK_KLASS_DEFN
|
||||||
ciInstanceKlass* ciEnv::_Object;
|
|
||||||
ciInstanceKlass* ciEnv::_Throwable;
|
|
||||||
ciInstanceKlass* ciEnv::_Thread;
|
|
||||||
ciInstanceKlass* ciEnv::_OutOfMemoryError;
|
|
||||||
ciInstanceKlass* ciEnv::_String;
|
|
||||||
ciInstanceKlass* ciEnv::_StringBuffer;
|
|
||||||
ciInstanceKlass* ciEnv::_StringBuilder;
|
|
||||||
ciInstanceKlass* ciEnv::_Integer;
|
|
||||||
|
|
||||||
ciSymbol* ciEnv::_unloaded_cisymbol = NULL;
|
ciSymbol* ciEnv::_unloaded_cisymbol = NULL;
|
||||||
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
|
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
|
||||||
|
@ -442,12 +434,11 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass,
|
||||||
// ciEnv::get_klass_by_index_impl
|
// ciEnv::get_klass_by_index_impl
|
||||||
//
|
//
|
||||||
// Implementation of get_klass_by_index.
|
// Implementation of get_klass_by_index.
|
||||||
ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
|
ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
|
||||||
int index,
|
int index,
|
||||||
bool& is_accessible) {
|
bool& is_accessible,
|
||||||
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
ciInstanceKlass* accessor) {
|
||||||
EXCEPTION_CONTEXT;
|
EXCEPTION_CONTEXT;
|
||||||
constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants());
|
|
||||||
KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
|
KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
|
||||||
symbolHandle klass_name;
|
symbolHandle klass_name;
|
||||||
if (klass.is_null()) {
|
if (klass.is_null()) {
|
||||||
|
@ -509,22 +500,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
|
||||||
// ciEnv::get_klass_by_index
|
// ciEnv::get_klass_by_index
|
||||||
//
|
//
|
||||||
// Get a klass from the constant pool.
|
// Get a klass from the constant pool.
|
||||||
ciKlass* ciEnv::get_klass_by_index(ciInstanceKlass* accessor,
|
ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
|
||||||
int index,
|
int index,
|
||||||
bool& is_accessible) {
|
bool& is_accessible,
|
||||||
GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);)
|
ciInstanceKlass* accessor) {
|
||||||
|
GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::get_constant_by_index_impl
|
// ciEnv::get_constant_by_index_impl
|
||||||
//
|
//
|
||||||
// Implementation of get_constant_by_index().
|
// Implementation of get_constant_by_index().
|
||||||
ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
||||||
int index) {
|
int index,
|
||||||
|
ciInstanceKlass* accessor) {
|
||||||
EXCEPTION_CONTEXT;
|
EXCEPTION_CONTEXT;
|
||||||
instanceKlass* ik_accessor = accessor->get_instanceKlass();
|
|
||||||
assert(ik_accessor->is_linked(), "must be linked before accessing constant pool");
|
|
||||||
constantPoolOop cpool = ik_accessor->constants();
|
|
||||||
constantTag tag = cpool->tag_at(index);
|
constantTag tag = cpool->tag_at(index);
|
||||||
if (tag.is_int()) {
|
if (tag.is_int()) {
|
||||||
return ciConstant(T_INT, (jint)cpool->int_at(index));
|
return ciConstant(T_INT, (jint)cpool->int_at(index));
|
||||||
|
@ -552,7 +542,7 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
||||||
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
||||||
// 4881222: allow ldc to take a class type
|
// 4881222: allow ldc to take a class type
|
||||||
bool ignore;
|
bool ignore;
|
||||||
ciKlass* klass = get_klass_by_index_impl(accessor, index, ignore);
|
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
record_out_of_memory_failure();
|
record_out_of_memory_failure();
|
||||||
|
@ -561,6 +551,11 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
||||||
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
||||||
"must be an instance or array klass ");
|
"must be an instance or array klass ");
|
||||||
return ciConstant(T_OBJECT, klass);
|
return ciConstant(T_OBJECT, klass);
|
||||||
|
} else if (tag.is_object()) {
|
||||||
|
oop obj = cpool->object_at(index);
|
||||||
|
assert(obj->is_instance(), "must be an instance");
|
||||||
|
ciObject* ciobj = get_object(obj);
|
||||||
|
return ciConstant(T_OBJECT, ciobj);
|
||||||
} else {
|
} else {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return ciConstant();
|
return ciConstant();
|
||||||
|
@ -597,9 +592,10 @@ bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
|
||||||
// Pull a constant out of the constant pool. How appropriate.
|
// Pull a constant out of the constant pool. How appropriate.
|
||||||
//
|
//
|
||||||
// Implementation note: this query is currently in no way cached.
|
// Implementation note: this query is currently in no way cached.
|
||||||
ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor,
|
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
|
||||||
int index) {
|
int index,
|
||||||
GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, index); )
|
ciInstanceKlass* accessor) {
|
||||||
|
GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -701,15 +697,12 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor,
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::get_method_by_index_impl
|
// ciEnv::get_method_by_index_impl
|
||||||
ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
|
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
|
||||||
int index, Bytecodes::Code bc) {
|
int index, Bytecodes::Code bc,
|
||||||
// Get the method's declared holder.
|
ciInstanceKlass* accessor) {
|
||||||
|
|
||||||
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
|
||||||
constantPoolHandle cpool = accessor->get_instanceKlass()->constants();
|
|
||||||
int holder_index = cpool->klass_ref_index_at(index);
|
int holder_index = cpool->klass_ref_index_at(index);
|
||||||
bool holder_is_accessible;
|
bool holder_is_accessible;
|
||||||
ciKlass* holder = get_klass_by_index_impl(accessor, holder_index, holder_is_accessible);
|
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
||||||
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
||||||
|
|
||||||
// Get the method's name and signature.
|
// Get the method's name and signature.
|
||||||
|
@ -735,6 +728,33 @@ ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciEnv::get_fake_invokedynamic_method_impl
|
||||||
|
ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||||
|
int index, Bytecodes::Code bc) {
|
||||||
|
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
||||||
|
|
||||||
|
// Get the CallSite from the constant pool cache.
|
||||||
|
ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index);
|
||||||
|
assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity");
|
||||||
|
Handle call_site = cpc_entry->f1();
|
||||||
|
|
||||||
|
// Call site might not be linked yet.
|
||||||
|
if (call_site.is_null()) {
|
||||||
|
ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
|
||||||
|
ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol();
|
||||||
|
return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the methodOop from the CallSite.
|
||||||
|
methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site());
|
||||||
|
assert(method_oop != NULL, "sanity");
|
||||||
|
assert(method_oop->is_method_handle_invoke(), "consistent");
|
||||||
|
|
||||||
|
return get_object(method_oop)->as_method();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::get_instance_klass_for_declared_method_holder
|
// ciEnv::get_instance_klass_for_declared_method_holder
|
||||||
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
|
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
|
||||||
|
@ -757,14 +777,18 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::get_method_by_index
|
// ciEnv::get_method_by_index
|
||||||
ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor,
|
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
|
||||||
int index, Bytecodes::Code bc) {
|
int index, Bytecodes::Code bc,
|
||||||
GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);)
|
ciInstanceKlass* accessor) {
|
||||||
|
if (bc == Bytecodes::_invokedynamic) {
|
||||||
|
GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);)
|
||||||
|
} else {
|
||||||
|
GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::name_buffer
|
// ciEnv::name_buffer
|
||||||
|
|
|
@ -74,17 +74,9 @@ private:
|
||||||
static ciTypeArrayKlassKlass* _type_array_klass_klass_instance;
|
static ciTypeArrayKlassKlass* _type_array_klass_klass_instance;
|
||||||
static ciObjArrayKlassKlass* _obj_array_klass_klass_instance;
|
static ciObjArrayKlassKlass* _obj_array_klass_klass_instance;
|
||||||
|
|
||||||
static ciInstanceKlass* _ArrayStoreException;
|
#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name;
|
||||||
static ciInstanceKlass* _Class;
|
WK_KLASSES_DO(WK_KLASS_DECL)
|
||||||
static ciInstanceKlass* _ClassCastException;
|
#undef WK_KLASS_DECL
|
||||||
static ciInstanceKlass* _Object;
|
|
||||||
static ciInstanceKlass* _Throwable;
|
|
||||||
static ciInstanceKlass* _Thread;
|
|
||||||
static ciInstanceKlass* _OutOfMemoryError;
|
|
||||||
static ciInstanceKlass* _String;
|
|
||||||
static ciInstanceKlass* _StringBuffer;
|
|
||||||
static ciInstanceKlass* _StringBuilder;
|
|
||||||
static ciInstanceKlass* _Integer;
|
|
||||||
|
|
||||||
static ciSymbol* _unloaded_cisymbol;
|
static ciSymbol* _unloaded_cisymbol;
|
||||||
static ciInstanceKlass* _unloaded_ciinstance_klass;
|
static ciInstanceKlass* _unloaded_ciinstance_klass;
|
||||||
|
@ -120,37 +112,45 @@ private:
|
||||||
bool require_local);
|
bool require_local);
|
||||||
|
|
||||||
// Constant pool access.
|
// Constant pool access.
|
||||||
ciKlass* get_klass_by_index(ciInstanceKlass* loading_klass,
|
ciKlass* get_klass_by_index(constantPoolHandle cpool,
|
||||||
int klass_index,
|
int klass_index,
|
||||||
bool& is_accessible);
|
bool& is_accessible,
|
||||||
ciConstant get_constant_by_index(ciInstanceKlass* loading_klass,
|
ciInstanceKlass* loading_klass);
|
||||||
int constant_index);
|
ciConstant get_constant_by_index(constantPoolHandle cpool,
|
||||||
|
int constant_index,
|
||||||
|
ciInstanceKlass* accessor);
|
||||||
bool is_unresolved_string(ciInstanceKlass* loading_klass,
|
bool is_unresolved_string(ciInstanceKlass* loading_klass,
|
||||||
int constant_index) const;
|
int constant_index) const;
|
||||||
bool is_unresolved_klass(ciInstanceKlass* loading_klass,
|
bool is_unresolved_klass(ciInstanceKlass* loading_klass,
|
||||||
int constant_index) const;
|
int constant_index) const;
|
||||||
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
|
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
|
||||||
int field_index);
|
int field_index);
|
||||||
ciMethod* get_method_by_index(ciInstanceKlass* loading_klass,
|
ciMethod* get_method_by_index(constantPoolHandle cpool,
|
||||||
int method_index, Bytecodes::Code bc);
|
int method_index, Bytecodes::Code bc,
|
||||||
|
ciInstanceKlass* loading_klass);
|
||||||
|
|
||||||
// Implementation methods for loading and constant pool access.
|
// Implementation methods for loading and constant pool access.
|
||||||
ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
|
ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
|
||||||
ciSymbol* klass_name,
|
ciSymbol* klass_name,
|
||||||
bool require_local);
|
bool require_local);
|
||||||
ciKlass* get_klass_by_index_impl(ciInstanceKlass* loading_klass,
|
ciKlass* get_klass_by_index_impl(constantPoolHandle cpool,
|
||||||
int klass_index,
|
int klass_index,
|
||||||
bool& is_accessible);
|
bool& is_accessible,
|
||||||
ciConstant get_constant_by_index_impl(ciInstanceKlass* loading_klass,
|
ciInstanceKlass* loading_klass);
|
||||||
int constant_index);
|
ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
|
||||||
|
int constant_index,
|
||||||
|
ciInstanceKlass* loading_klass);
|
||||||
bool is_unresolved_string_impl (instanceKlass* loading_klass,
|
bool is_unresolved_string_impl (instanceKlass* loading_klass,
|
||||||
int constant_index) const;
|
int constant_index) const;
|
||||||
bool is_unresolved_klass_impl (instanceKlass* loading_klass,
|
bool is_unresolved_klass_impl (instanceKlass* loading_klass,
|
||||||
int constant_index) const;
|
int constant_index) const;
|
||||||
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
|
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
|
||||||
int field_index);
|
int field_index);
|
||||||
ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass,
|
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
|
||||||
int method_index, Bytecodes::Code bc);
|
int method_index, Bytecodes::Code bc,
|
||||||
|
ciInstanceKlass* loading_klass);
|
||||||
|
ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||||
|
int index, Bytecodes::Code bc);
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
bool check_klass_accessibility(ciKlass* accessing_klass,
|
bool check_klass_accessibility(ciKlass* accessing_klass,
|
||||||
|
@ -292,39 +292,13 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// Access to certain well known ciObjects.
|
// Access to certain well known ciObjects.
|
||||||
ciInstanceKlass* ArrayStoreException_klass() {
|
#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
|
||||||
return _ArrayStoreException;
|
ciInstanceKlass* name() { \
|
||||||
}
|
return _##name;\
|
||||||
ciInstanceKlass* Class_klass() {
|
|
||||||
return _Class;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* ClassCastException_klass() {
|
|
||||||
return _ClassCastException;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* Object_klass() {
|
|
||||||
return _Object;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* Throwable_klass() {
|
|
||||||
return _Throwable;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* Thread_klass() {
|
|
||||||
return _Thread;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* OutOfMemoryError_klass() {
|
|
||||||
return _OutOfMemoryError;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* String_klass() {
|
|
||||||
return _String;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* StringBuilder_klass() {
|
|
||||||
return _StringBuilder;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* StringBuffer_klass() {
|
|
||||||
return _StringBuffer;
|
|
||||||
}
|
|
||||||
ciInstanceKlass* Integer_klass() {
|
|
||||||
return _Integer;
|
|
||||||
}
|
}
|
||||||
|
WK_KLASSES_DO(WK_KLASS_FUNC)
|
||||||
|
#undef WK_KLASS_FUNC
|
||||||
|
|
||||||
ciInstance* NullPointerException_instance() {
|
ciInstance* NullPointerException_instance() {
|
||||||
assert(_NullPointerException_instance != NULL, "initialization problem");
|
assert(_NullPointerException_instance != NULL, "initialization problem");
|
||||||
return _NullPointerException_instance;
|
return _NullPointerException_instance;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -34,12 +34,16 @@
|
||||||
//
|
//
|
||||||
// Get the exception klass that this handler catches.
|
// Get the exception klass that this handler catches.
|
||||||
ciInstanceKlass* ciExceptionHandler::catch_klass() {
|
ciInstanceKlass* ciExceptionHandler::catch_klass() {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
assert(!is_catch_all(), "bad index");
|
assert(!is_catch_all(), "bad index");
|
||||||
if (_catch_klass == NULL) {
|
if (_catch_klass == NULL) {
|
||||||
bool will_link;
|
bool will_link;
|
||||||
ciKlass* k = CURRENT_ENV->get_klass_by_index(_loading_klass,
|
assert(_loading_klass->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
||||||
|
constantPoolHandle cpool(_loading_klass->get_instanceKlass()->constants());
|
||||||
|
ciKlass* k = CURRENT_ENV->get_klass_by_index(cpool,
|
||||||
_catch_klass_index,
|
_catch_klass_index,
|
||||||
will_link);
|
will_link,
|
||||||
|
_loading_klass);
|
||||||
if (!will_link && k->is_loaded()) {
|
if (!will_link && k->is_loaded()) {
|
||||||
GUARDED_VM_ENTRY(
|
GUARDED_VM_ENTRY(
|
||||||
k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name());
|
k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
|
||||||
bool ignore;
|
bool ignore;
|
||||||
// This is not really a class reference; the index always refers to the
|
// This is not really a class reference; the index always refers to the
|
||||||
// field's type signature, as a symbol. Linkage checks do not apply.
|
// field's type signature, as a symbol. Linkage checks do not apply.
|
||||||
_type = ciEnv::current(thread)->get_klass_by_index(klass, sig_index, ignore);
|
_type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass);
|
||||||
} else {
|
} else {
|
||||||
_type = ciType::make(field_type);
|
_type = ciType::make(field_type);
|
||||||
}
|
}
|
||||||
|
@ -100,9 +100,9 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
|
||||||
int holder_index = cpool->klass_ref_index_at(index);
|
int holder_index = cpool->klass_ref_index_at(index);
|
||||||
bool holder_is_accessible;
|
bool holder_is_accessible;
|
||||||
ciInstanceKlass* declared_holder =
|
ciInstanceKlass* declared_holder =
|
||||||
ciEnv::current(thread)->get_klass_by_index(klass, holder_index,
|
ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
|
||||||
holder_is_accessible)
|
holder_is_accessible,
|
||||||
->as_instance_klass();
|
klass)->as_instance_klass();
|
||||||
|
|
||||||
// The declared holder of this field may not have been loaded.
|
// The declared holder of this field may not have been loaded.
|
||||||
// Bail out with partial field information.
|
// Bail out with partial field information.
|
||||||
|
@ -161,6 +161,18 @@ ciField::ciField(fieldDescriptor *fd): _known_to_link_with(NULL) {
|
||||||
"bootstrap classes must not create & cache unshared fields");
|
"bootstrap classes must not create & cache unshared fields");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
||||||
|
if (holder == NULL)
|
||||||
|
return false;
|
||||||
|
if (holder->name() == ciSymbol::java_lang_System())
|
||||||
|
// Never trust strangely unstable finals: System.out, etc.
|
||||||
|
return false;
|
||||||
|
// Even if general trusting is disabled, trust system-built closures in these packages.
|
||||||
|
if (holder->is_in_package("java/dyn") || holder->is_in_package("sun/dyn"))
|
||||||
|
return true;
|
||||||
|
return TrustFinalNonStaticFields;
|
||||||
|
}
|
||||||
|
|
||||||
void ciField::initialize_from(fieldDescriptor* fd) {
|
void ciField::initialize_from(fieldDescriptor* fd) {
|
||||||
// Get the flags, offset, and canonical holder of the field.
|
// Get the flags, offset, and canonical holder of the field.
|
||||||
_flags = ciFlags(fd->access_flags());
|
_flags = ciFlags(fd->access_flags());
|
||||||
|
@ -168,8 +180,18 @@ void ciField::initialize_from(fieldDescriptor* fd) {
|
||||||
_holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();
|
_holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();
|
||||||
|
|
||||||
// Check to see if the field is constant.
|
// Check to see if the field is constant.
|
||||||
if (_holder->is_initialized() &&
|
if (_holder->is_initialized() && this->is_final()) {
|
||||||
this->is_final() && this->is_static()) {
|
if (!this->is_static()) {
|
||||||
|
// A field can be constant if it's a final static field or if it's
|
||||||
|
// a final non-static field of a trusted class ({java,sun}.dyn).
|
||||||
|
if (trust_final_non_static_fields(_holder)) {
|
||||||
|
_is_constant = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_is_constant = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// This field just may be constant. The only cases where it will
|
// This field just may be constant. The only cases where it will
|
||||||
// not be constant are:
|
// not be constant are:
|
||||||
//
|
//
|
||||||
|
@ -182,8 +204,8 @@ void ciField::initialize_from(fieldDescriptor* fd) {
|
||||||
// java.lang.System.out, and java.lang.System.err.
|
// java.lang.System.out, and java.lang.System.err.
|
||||||
|
|
||||||
klassOop k = _holder->get_klassOop();
|
klassOop k = _holder->get_klassOop();
|
||||||
assert( SystemDictionary::system_klass() != NULL, "Check once per vm");
|
assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
|
||||||
if( k == SystemDictionary::system_klass() ) {
|
if( k == SystemDictionary::System_klass() ) {
|
||||||
// Check offsets for case 2: System.in, System.out, or System.err
|
// Check offsets for case 2: System.in, System.out, or System.err
|
||||||
if( _offset == java_lang_System::in_offset_in_bytes() ||
|
if( _offset == java_lang_System::in_offset_in_bytes() ||
|
||||||
_offset == java_lang_System::out_offset_in_bytes() ||
|
_offset == java_lang_System::out_offset_in_bytes() ||
|
||||||
|
|
|
@ -138,10 +138,18 @@ public:
|
||||||
|
|
||||||
// Get the constant value of this field.
|
// Get the constant value of this field.
|
||||||
ciConstant constant_value() {
|
ciConstant constant_value() {
|
||||||
assert(is_constant(), "illegal call to constant_value()");
|
assert(is_static() && is_constant(), "illegal call to constant_value()");
|
||||||
return _constant_value;
|
return _constant_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the constant value of non-static final field in the given
|
||||||
|
// object.
|
||||||
|
ciConstant constant_value_of(ciObject* object) {
|
||||||
|
assert(!is_static() && is_constant(), "only if field is non-static constant");
|
||||||
|
assert(object->is_instance(), "must be instance");
|
||||||
|
return object->as_instance()->field_value(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for link time errors. Accessing a field from a
|
// Check for link time errors. Accessing a field from a
|
||||||
// certain class via a certain bytecode may or may not be legal.
|
// certain class via a certain bytecode may or may not be legal.
|
||||||
// This call checks to see if an exception may be raised by
|
// This call checks to see if an exception may be raised by
|
||||||
|
|
|
@ -36,7 +36,7 @@ ciType* ciInstance::java_mirror_type() {
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
oop m = get_oop();
|
oop m = get_oop();
|
||||||
// Return NULL if it is not java.lang.Class.
|
// Return NULL if it is not java.lang.Class.
|
||||||
if (m == NULL || m->klass() != SystemDictionary::class_klass()) {
|
if (m == NULL || m->klass() != SystemDictionary::Class_klass()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Return either a primitive type or a klass.
|
// Return either a primitive type or a klass.
|
||||||
|
|
|
@ -75,7 +75,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
|
||||||
_java_mirror = NULL;
|
_java_mirror = NULL;
|
||||||
|
|
||||||
if (is_shared()) {
|
if (is_shared()) {
|
||||||
if (h_k() != SystemDictionary::object_klass()) {
|
if (h_k() != SystemDictionary::Object_klass()) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
java_mirror();
|
java_mirror();
|
||||||
|
@ -232,8 +232,48 @@ bool ciInstanceKlass::is_java_lang_Object() {
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciInstanceKlass::uses_default_loader
|
// ciInstanceKlass::uses_default_loader
|
||||||
bool ciInstanceKlass::uses_default_loader() {
|
bool ciInstanceKlass::uses_default_loader() {
|
||||||
VM_ENTRY_MARK;
|
// Note: We do not need to resolve the handle or enter the VM
|
||||||
return loader() == NULL;
|
// in order to test null-ness.
|
||||||
|
return _loader == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciInstanceKlass::is_in_package
|
||||||
|
//
|
||||||
|
// Is this klass in the given package?
|
||||||
|
bool ciInstanceKlass::is_in_package(const char* packagename, int len) {
|
||||||
|
// To avoid class loader mischief, this test always rejects application classes.
|
||||||
|
if (!uses_default_loader())
|
||||||
|
return false;
|
||||||
|
GUARDED_VM_ENTRY(
|
||||||
|
return is_in_package_impl(packagename, len);
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) {
|
||||||
|
ASSERT_IN_VM;
|
||||||
|
|
||||||
|
// If packagename contains trailing '/' exclude it from the
|
||||||
|
// prefix-test since we test for it explicitly.
|
||||||
|
if (packagename[len - 1] == '/')
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (!name()->starts_with(packagename, len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Test if the class name is something like "java/lang".
|
||||||
|
if ((len + 1) > name()->utf8_length())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Test for trailing '/'
|
||||||
|
if ((char) name()->byte_at(len) != '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Make sure it's not actually in a subpackage:
|
||||||
|
if (name()->index_of_at(len+1, "/", 1) >= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
|
@ -29,10 +29,11 @@
|
||||||
// be loaded.
|
// be loaded.
|
||||||
class ciInstanceKlass : public ciKlass {
|
class ciInstanceKlass : public ciKlass {
|
||||||
CI_PACKAGE_ACCESS
|
CI_PACKAGE_ACCESS
|
||||||
|
friend class ciBytecodeStream;
|
||||||
friend class ciEnv;
|
friend class ciEnv;
|
||||||
|
friend class ciExceptionHandler;
|
||||||
friend class ciMethod;
|
friend class ciMethod;
|
||||||
friend class ciField;
|
friend class ciField;
|
||||||
friend class ciBytecodeStream;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
jobject _loader;
|
jobject _loader;
|
||||||
|
@ -78,6 +79,8 @@ protected:
|
||||||
|
|
||||||
const char* type_string() { return "ciInstanceKlass"; }
|
const char* type_string() { return "ciInstanceKlass"; }
|
||||||
|
|
||||||
|
bool is_in_package_impl(const char* packagename, int len);
|
||||||
|
|
||||||
void print_impl(outputStream* st);
|
void print_impl(outputStream* st);
|
||||||
|
|
||||||
ciConstantPoolCache* field_cache();
|
ciConstantPoolCache* field_cache();
|
||||||
|
@ -196,6 +199,12 @@ public:
|
||||||
|
|
||||||
bool is_java_lang_Object();
|
bool is_java_lang_Object();
|
||||||
|
|
||||||
|
// Is this klass in the given package?
|
||||||
|
bool is_in_package(const char* packagename) {
|
||||||
|
return is_in_package(packagename, (int) strlen(packagename));
|
||||||
|
}
|
||||||
|
bool is_in_package(const char* packagename, int len);
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
bool is_instance_klass() { return true; }
|
bool is_instance_klass() { return true; }
|
||||||
bool is_java_klass() { return true; }
|
bool is_java_klass() { return true; }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
ciKlass(KlassHandle k_h);
|
ciKlass(KlassHandle k_h);
|
||||||
|
|
||||||
// What is the name of this klass?
|
// What is the name of this klass?
|
||||||
ciSymbol* name() { return _name; }
|
ciSymbol* name() const { return _name; }
|
||||||
|
|
||||||
// What is its layout helper value?
|
// What is its layout helper value?
|
||||||
jint layout_helper() { return _layout_helper; }
|
jint layout_helper() { return _layout_helper; }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -687,7 +687,7 @@ int ciMethod::scale_count(int count, float prof_factor) {
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// invokedynamic support
|
// invokedynamic support
|
||||||
//
|
//
|
||||||
bool ciMethod::is_method_handle_invoke() {
|
bool ciMethod::is_method_handle_invoke() const {
|
||||||
check_is_loaded();
|
check_is_loaded();
|
||||||
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -700,6 +700,12 @@ bool ciMethod::is_method_handle_invoke() {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ciMethod::is_method_handle_adapter() const {
|
||||||
|
check_is_loaded();
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
return get_methodOop()->is_method_handle_adapter();
|
||||||
|
}
|
||||||
|
|
||||||
ciInstance* ciMethod::method_handle_type() {
|
ciInstance* ciMethod::method_handle_type() {
|
||||||
check_is_loaded();
|
check_is_loaded();
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,6 +38,8 @@ class ciMethod : public ciObject {
|
||||||
CI_PACKAGE_ACCESS
|
CI_PACKAGE_ACCESS
|
||||||
friend class ciEnv;
|
friend class ciEnv;
|
||||||
friend class ciExceptionHandlerStream;
|
friend class ciExceptionHandlerStream;
|
||||||
|
friend class ciBytecodeStream;
|
||||||
|
friend class ciMethodHandle;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// General method information.
|
// General method information.
|
||||||
|
@ -213,7 +215,10 @@ class ciMethod : public ciObject {
|
||||||
bool check_call(int refinfo_index, bool is_static) const;
|
bool check_call(int refinfo_index, bool is_static) const;
|
||||||
void build_method_data(); // make sure it exists in the VM also
|
void build_method_data(); // make sure it exists in the VM also
|
||||||
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
||||||
bool is_method_handle_invoke();
|
|
||||||
|
// JSR 292 support
|
||||||
|
bool is_method_handle_invoke() const;
|
||||||
|
bool is_method_handle_adapter() const;
|
||||||
ciInstance* method_handle_type();
|
ciInstance* method_handle_type();
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
|
@ -251,4 +256,10 @@ class ciMethod : public ciObject {
|
||||||
// Print the name of this method in various incarnations.
|
// Print the name of this method in various incarnations.
|
||||||
void print_name(outputStream* st = tty);
|
void print_name(outputStream* st = tty);
|
||||||
void print_short_name(outputStream* st = tty);
|
void print_short_name(outputStream* st = tty);
|
||||||
|
|
||||||
|
methodOop get_method_handle_target() {
|
||||||
|
klassOop receiver_limit_oop = NULL;
|
||||||
|
int flags = 0;
|
||||||
|
return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
52
hotspot/src/share/vm/ci/ciMethodHandle.cpp
Normal file
52
hotspot/src/share/vm/ci/ciMethodHandle.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_ciMethodHandle.cpp.incl"
|
||||||
|
|
||||||
|
// ciMethodHandle
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciMethodHandle::get_adapter
|
||||||
|
//
|
||||||
|
// Return an adapter for this MethodHandle.
|
||||||
|
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
|
||||||
|
Handle h(get_oop());
|
||||||
|
methodHandle callee(_callee->get_methodOop());
|
||||||
|
MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
|
||||||
|
methodHandle m = mhc.compile(CHECK_NULL);
|
||||||
|
return CURRENT_ENV->get_object(m())->as_method();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciMethodHandle::print_impl
|
||||||
|
//
|
||||||
|
// Implementation of the print method.
|
||||||
|
void ciMethodHandle::print_impl(outputStream* st) {
|
||||||
|
st->print(" type=");
|
||||||
|
get_oop()->print();
|
||||||
|
}
|
56
hotspot/src/share/vm/ci/ciMethodHandle.hpp
Normal file
56
hotspot/src/share/vm/ci/ciMethodHandle.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ciMethodHandle
|
||||||
|
//
|
||||||
|
// The class represents a java.dyn.MethodHandle object.
|
||||||
|
class ciMethodHandle : public ciInstance {
|
||||||
|
private:
|
||||||
|
ciMethod* _callee;
|
||||||
|
|
||||||
|
// Return an adapter for this MethodHandle.
|
||||||
|
ciMethod* get_adapter(bool is_invokedynamic) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void print_impl(outputStream* st);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ciMethodHandle(instanceHandle h_i) : ciInstance(h_i) {};
|
||||||
|
|
||||||
|
// What kind of ciObject is this?
|
||||||
|
bool is_method_handle() const { return true; }
|
||||||
|
|
||||||
|
ciMethod* callee() const { return _callee; }
|
||||||
|
void set_callee(ciMethod* m) { _callee = m; }
|
||||||
|
|
||||||
|
// Return an adapter for a MethodHandle call.
|
||||||
|
ciMethod* get_method_handle_adapter() const {
|
||||||
|
return get_adapter(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an adapter for an invokedynamic call.
|
||||||
|
ciMethod* get_invokedynamic_adapter() const {
|
||||||
|
return get_adapter(true);
|
||||||
|
}
|
||||||
|
};
|
|
@ -131,9 +131,12 @@ public:
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
virtual bool is_null_object() const { return false; }
|
virtual bool is_null_object() const { return false; }
|
||||||
|
virtual bool is_call_site() const { return false; }
|
||||||
|
virtual bool is_cpcache() const { return false; }
|
||||||
virtual bool is_instance() { return false; }
|
virtual bool is_instance() { return false; }
|
||||||
virtual bool is_method() { return false; }
|
virtual bool is_method() { return false; }
|
||||||
virtual bool is_method_data() { return false; }
|
virtual bool is_method_data() { return false; }
|
||||||
|
virtual bool is_method_handle() const { return false; }
|
||||||
virtual bool is_array() { return false; }
|
virtual bool is_array() { return false; }
|
||||||
virtual bool is_obj_array() { return false; }
|
virtual bool is_obj_array() { return false; }
|
||||||
virtual bool is_type_array() { return false; }
|
virtual bool is_type_array() { return false; }
|
||||||
|
@ -185,6 +188,14 @@ public:
|
||||||
assert(is_null_object(), "bad cast");
|
assert(is_null_object(), "bad cast");
|
||||||
return (ciNullObject*)this;
|
return (ciNullObject*)this;
|
||||||
}
|
}
|
||||||
|
ciCallSite* as_call_site() {
|
||||||
|
assert(is_call_site(), "bad cast");
|
||||||
|
return (ciCallSite*) this;
|
||||||
|
}
|
||||||
|
ciCPCache* as_cpcache() {
|
||||||
|
assert(is_cpcache(), "bad cast");
|
||||||
|
return (ciCPCache*) this;
|
||||||
|
}
|
||||||
ciInstance* as_instance() {
|
ciInstance* as_instance() {
|
||||||
assert(is_instance(), "bad cast");
|
assert(is_instance(), "bad cast");
|
||||||
return (ciInstance*)this;
|
return (ciInstance*)this;
|
||||||
|
@ -197,6 +208,10 @@ public:
|
||||||
assert(is_method_data(), "bad cast");
|
assert(is_method_data(), "bad cast");
|
||||||
return (ciMethodData*)this;
|
return (ciMethodData*)this;
|
||||||
}
|
}
|
||||||
|
ciMethodHandle* as_method_handle() {
|
||||||
|
assert(is_method_handle(), "bad cast");
|
||||||
|
return (ciMethodHandle*) this;
|
||||||
|
}
|
||||||
ciArray* as_array() {
|
ciArray* as_array() {
|
||||||
assert(is_array(), "bad cast");
|
assert(is_array(), "bad cast");
|
||||||
return (ciArray*)this;
|
return (ciArray*)this;
|
||||||
|
|
|
@ -144,39 +144,13 @@ void ciObjectFactory::init_shared_objects() {
|
||||||
ciEnv::_obj_array_klass_klass_instance =
|
ciEnv::_obj_array_klass_klass_instance =
|
||||||
get(Universe::objArrayKlassKlassObj())
|
get(Universe::objArrayKlassKlassObj())
|
||||||
->as_obj_array_klass_klass();
|
->as_obj_array_klass_klass();
|
||||||
ciEnv::_ArrayStoreException =
|
|
||||||
get(SystemDictionary::ArrayStoreException_klass())
|
#define WK_KLASS_DEFN(name, ignore_s, opt) \
|
||||||
->as_instance_klass();
|
if (SystemDictionary::name() != NULL) \
|
||||||
ciEnv::_Class =
|
ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass();
|
||||||
get(SystemDictionary::class_klass())
|
|
||||||
->as_instance_klass();
|
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||||
ciEnv::_ClassCastException =
|
#undef WK_KLASS_DEFN
|
||||||
get(SystemDictionary::ClassCastException_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_Object =
|
|
||||||
get(SystemDictionary::object_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_Throwable =
|
|
||||||
get(SystemDictionary::throwable_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_Thread =
|
|
||||||
get(SystemDictionary::thread_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_OutOfMemoryError =
|
|
||||||
get(SystemDictionary::OutOfMemoryError_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_String =
|
|
||||||
get(SystemDictionary::string_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_StringBuffer =
|
|
||||||
get(SystemDictionary::stringBuffer_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_StringBuilder =
|
|
||||||
get(SystemDictionary::StringBuilder_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
ciEnv::_Integer =
|
|
||||||
get(SystemDictionary::int_klass())
|
|
||||||
->as_instance_klass();
|
|
||||||
|
|
||||||
for (int len = -1; len != _ci_objects->length(); ) {
|
for (int len = -1; len != _ci_objects->length(); ) {
|
||||||
len = _ci_objects->length();
|
len = _ci_objects->length();
|
||||||
|
@ -333,6 +307,11 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
|
||||||
return new (arena()) ciMethodData(h_md);
|
return new (arena()) ciMethodData(h_md);
|
||||||
} else if (o->is_instance()) {
|
} else if (o->is_instance()) {
|
||||||
instanceHandle h_i(THREAD, (instanceOop)o);
|
instanceHandle h_i(THREAD, (instanceOop)o);
|
||||||
|
if (java_dyn_CallSite::is_instance(o))
|
||||||
|
return new (arena()) ciCallSite(h_i);
|
||||||
|
else if (java_dyn_MethodHandle::is_instance(o))
|
||||||
|
return new (arena()) ciMethodHandle(h_i);
|
||||||
|
else
|
||||||
return new (arena()) ciInstance(h_i);
|
return new (arena()) ciInstance(h_i);
|
||||||
} else if (o->is_objArray()) {
|
} else if (o->is_objArray()) {
|
||||||
objArrayHandle h_oa(THREAD, (objArrayOop)o);
|
objArrayHandle h_oa(THREAD, (objArrayOop)o);
|
||||||
|
@ -340,6 +319,9 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
|
||||||
} else if (o->is_typeArray()) {
|
} else if (o->is_typeArray()) {
|
||||||
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
|
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
|
||||||
return new (arena()) ciTypeArray(h_ta);
|
return new (arena()) ciTypeArray(h_ta);
|
||||||
|
} else if (o->is_constantPoolCache()) {
|
||||||
|
constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o);
|
||||||
|
return new (arena()) ciCPCache(h_cpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The oop is of some type not supported by the compiler interface.
|
// The oop is of some type not supported by the compiler interface.
|
||||||
|
@ -576,7 +558,7 @@ ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
|
||||||
if (key->is_perm() && _non_perm_count == 0) {
|
if (key->is_perm() && _non_perm_count == 0) {
|
||||||
return emptyBucket;
|
return emptyBucket;
|
||||||
} else if (key->is_instance()) {
|
} else if (key->is_instance()) {
|
||||||
if (key->klass() == SystemDictionary::class_klass()) {
|
if (key->klass() == SystemDictionary::Class_klass()) {
|
||||||
// class mirror instances are always perm
|
// class mirror instances are always perm
|
||||||
return emptyBucket;
|
return emptyBucket;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,8 +186,9 @@ int ciBytecodeStream::get_klass_index() const {
|
||||||
// If this bytecode is a new, newarray, multianewarray, instanceof,
|
// If this bytecode is a new, newarray, multianewarray, instanceof,
|
||||||
// or checkcast, get the referenced klass.
|
// or checkcast, get the referenced klass.
|
||||||
ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
|
ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
|
||||||
return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(),
|
VM_ENTRY_MARK;
|
||||||
will_link);
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
|
return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -213,7 +214,9 @@ int ciBytecodeStream::get_constant_index() const {
|
||||||
// If this bytecode is one of the ldc variants, get the referenced
|
// If this bytecode is one of the ldc variants, get the referenced
|
||||||
// constant.
|
// constant.
|
||||||
ciConstant ciBytecodeStream::get_constant() {
|
ciConstant ciBytecodeStream::get_constant() {
|
||||||
return CURRENT_ENV->get_constant_by_index(_holder, get_constant_index());
|
VM_ENTRY_MARK;
|
||||||
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
|
return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -264,9 +267,11 @@ ciField* ciBytecodeStream::get_field(bool& will_link) {
|
||||||
// There is no "will_link" result passed back. The user is responsible
|
// There is no "will_link" result passed back. The user is responsible
|
||||||
// for checking linkability when retrieving the associated field.
|
// for checking linkability when retrieving the associated field.
|
||||||
ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
|
ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
int holder_index = get_field_holder_index();
|
int holder_index = get_field_holder_index();
|
||||||
bool ignore;
|
bool ignore;
|
||||||
return CURRENT_ENV->get_klass_by_index(_holder, holder_index, ignore)
|
return CURRENT_ENV->get_klass_by_index(cpool, holder_index, ignore, _holder)
|
||||||
->as_instance_klass();
|
->as_instance_klass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,9 +282,10 @@ ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
|
||||||
// referenced by the current bytecode. Used for generating
|
// referenced by the current bytecode. Used for generating
|
||||||
// deoptimization information.
|
// deoptimization information.
|
||||||
int ciBytecodeStream::get_field_holder_index() {
|
int ciBytecodeStream::get_field_holder_index() {
|
||||||
VM_ENTRY_MARK;
|
GUARDED_VM_ENTRY(
|
||||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||||
return cpool->klass_ref_index_at(get_field_index());
|
return cpool->klass_ref_index_at(get_field_index());
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -321,7 +327,9 @@ int ciBytecodeStream::get_method_index() {
|
||||||
//
|
//
|
||||||
// If this is a method invocation bytecode, get the invoked method.
|
// If this is a method invocation bytecode, get the invoked method.
|
||||||
ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
||||||
ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc());
|
VM_ENTRY_MARK;
|
||||||
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
|
ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
|
||||||
will_link = m->is_loaded();
|
will_link = m->is_loaded();
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -338,11 +346,13 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
||||||
// There is no "will_link" result passed back. The user is responsible
|
// There is no "will_link" result passed back. The user is responsible
|
||||||
// for checking linkability when retrieving the associated method.
|
// for checking linkability when retrieving the associated method.
|
||||||
ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
bool ignore;
|
bool ignore;
|
||||||
// report as Dynamic for invokedynamic, which is syntactically classless
|
// report as InvokeDynamic for invokedynamic, which is syntactically classless
|
||||||
if (cur_bc() == Bytecodes::_invokedynamic)
|
if (cur_bc() == Bytecodes::_invokedynamic)
|
||||||
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false);
|
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false);
|
||||||
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
|
return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -352,8 +362,7 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
||||||
// referenced by the current bytecode. Used for generating
|
// referenced by the current bytecode. Used for generating
|
||||||
// deoptimization information.
|
// deoptimization information.
|
||||||
int ciBytecodeStream::get_method_holder_index() {
|
int ciBytecodeStream::get_method_holder_index() {
|
||||||
VM_ENTRY_MARK;
|
constantPoolOop cpool = _method->get_methodOop()->constants();
|
||||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
|
||||||
return cpool->klass_ref_index_at(get_method_index());
|
return cpool->klass_ref_index_at(get_method_index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,3 +379,31 @@ int ciBytecodeStream::get_method_signature_index() {
|
||||||
int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
|
int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
|
||||||
return cpool->signature_ref_index_at(name_and_type_index);
|
return cpool->signature_ref_index_at(name_and_type_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciBytecodeStream::get_cpcache
|
||||||
|
ciCPCache* ciBytecodeStream::get_cpcache() {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
// Get the constant pool.
|
||||||
|
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||||
|
constantPoolCacheOop cpcache = cpool->cache();
|
||||||
|
|
||||||
|
return CURRENT_ENV->get_object(cpcache)->as_cpcache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciBytecodeStream::get_call_site
|
||||||
|
ciCallSite* ciBytecodeStream::get_call_site() {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
// Get the constant pool.
|
||||||
|
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||||
|
constantPoolCacheOop cpcache = cpool->cache();
|
||||||
|
|
||||||
|
// Get the CallSite from the constant pool cache.
|
||||||
|
int method_index = get_method_index();
|
||||||
|
ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index);
|
||||||
|
oop call_site_oop = cpcache_entry->f1();
|
||||||
|
|
||||||
|
// Create a CallSite object and return it.
|
||||||
|
return CURRENT_ENV->get_object(call_site_oop)->as_call_site();
|
||||||
|
}
|
||||||
|
|
|
@ -232,6 +232,9 @@ public:
|
||||||
int get_method_holder_index();
|
int get_method_holder_index();
|
||||||
int get_method_signature_index();
|
int get_method_signature_index();
|
||||||
|
|
||||||
|
ciCPCache* get_cpcache();
|
||||||
|
ciCallSite* get_call_site();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void assert_index_size(int required_size) const {
|
void assert_index_size(int required_size) const {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -59,6 +59,22 @@ int ciSymbol::byte_at(int i) {
|
||||||
GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);)
|
GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciSymbol::starts_with
|
||||||
|
//
|
||||||
|
// Tests if the symbol starts with the given prefix.
|
||||||
|
bool ciSymbol::starts_with(const char* prefix, int len) const {
|
||||||
|
GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciSymbol::index_of
|
||||||
|
//
|
||||||
|
// Determines where the symbol contains the given substring.
|
||||||
|
int ciSymbol::index_of_at(int i, const char* str, int len) const {
|
||||||
|
GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);)
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciSymbol::utf8_length
|
// ciSymbol::utf8_length
|
||||||
int ciSymbol::utf8_length() {
|
int ciSymbol::utf8_length() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
// machine.
|
// machine.
|
||||||
class ciSymbol : public ciObject {
|
class ciSymbol : public ciObject {
|
||||||
CI_PACKAGE_ACCESS
|
CI_PACKAGE_ACCESS
|
||||||
|
// These friends all make direct use of get_symbolOop:
|
||||||
friend class ciEnv;
|
friend class ciEnv;
|
||||||
friend class ciInstanceKlass;
|
friend class ciInstanceKlass;
|
||||||
friend class ciSignature;
|
friend class ciSignature;
|
||||||
|
@ -38,13 +39,13 @@ private:
|
||||||
ciSymbol(symbolOop s) : ciObject(s) {}
|
ciSymbol(symbolOop s) : ciObject(s) {}
|
||||||
ciSymbol(symbolHandle s); // for use with vmSymbolHandles
|
ciSymbol(symbolHandle s); // for use with vmSymbolHandles
|
||||||
|
|
||||||
symbolOop get_symbolOop() { return (symbolOop)get_oop(); }
|
symbolOop get_symbolOop() const { return (symbolOop)get_oop(); }
|
||||||
|
|
||||||
const char* type_string() { return "ciSymbol"; }
|
const char* type_string() { return "ciSymbol"; }
|
||||||
|
|
||||||
void print_impl(outputStream* st);
|
void print_impl(outputStream* st);
|
||||||
|
|
||||||
int byte_at(int i);
|
// This is public in symbolOop but private here, because the base can move:
|
||||||
jbyte* base();
|
jbyte* base();
|
||||||
|
|
||||||
// Make a ciSymbol from a C string (implementation).
|
// Make a ciSymbol from a C string (implementation).
|
||||||
|
@ -55,6 +56,15 @@ public:
|
||||||
const char* as_utf8();
|
const char* as_utf8();
|
||||||
int utf8_length();
|
int utf8_length();
|
||||||
|
|
||||||
|
// Return the i-th utf8 byte, where i < utf8_length
|
||||||
|
int byte_at(int i);
|
||||||
|
|
||||||
|
// Tests if the symbol starts with the given prefix.
|
||||||
|
bool starts_with(const char* prefix, int len) const;
|
||||||
|
|
||||||
|
// Determines where the symbol contains the given substring.
|
||||||
|
int index_of_at(int i, const char* str, int len) const;
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
bool is_symbol() { return true; }
|
bool is_symbol() { return true; }
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ ciType* ciType::make(BasicType t) {
|
||||||
// short, etc.
|
// short, etc.
|
||||||
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
|
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
|
||||||
assert((uint)t < T_CONFLICT+1, "range check");
|
assert((uint)t < T_CONFLICT+1, "range check");
|
||||||
if (t == T_OBJECT) return ciEnv::_Object; // java/lang/Object
|
if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object
|
||||||
assert(_basic_types[t] != NULL, "domain check");
|
assert(_basic_types[t] != NULL, "domain check");
|
||||||
return _basic_types[t];
|
return _basic_types[t];
|
||||||
}
|
}
|
||||||
|
|
|
@ -635,8 +635,15 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
|
||||||
ciMethod* method = str->get_method(will_link);
|
ciMethod* method = str->get_method(will_link);
|
||||||
if (!will_link) {
|
if (!will_link) {
|
||||||
// We weren't able to find the method.
|
// We weren't able to find the method.
|
||||||
|
if (str->cur_bc() == Bytecodes::_invokedynamic) {
|
||||||
|
trap(str, NULL,
|
||||||
|
Deoptimization::make_trap_request
|
||||||
|
(Deoptimization::Reason_uninitialized,
|
||||||
|
Deoptimization::Action_reinterpret));
|
||||||
|
} else {
|
||||||
ciKlass* unloaded_holder = method->holder();
|
ciKlass* unloaded_holder = method->holder();
|
||||||
trap(str, unloaded_holder, str->get_method_holder_index());
|
trap(str, unloaded_holder, str->get_method_holder_index());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ciSignature* signature = method->signature();
|
ciSignature* signature = method->signature();
|
||||||
ciSignatureStream sigstr(signature);
|
ciSignatureStream sigstr(signature);
|
||||||
|
@ -1292,8 +1299,8 @@ bool ciTypeFlow::StateVector::apply_one_bytecode(ciBytecodeStream* str) {
|
||||||
case Bytecodes::_invokeinterface: do_invoke(str, true); break;
|
case Bytecodes::_invokeinterface: do_invoke(str, true); break;
|
||||||
case Bytecodes::_invokespecial: do_invoke(str, true); break;
|
case Bytecodes::_invokespecial: do_invoke(str, true); break;
|
||||||
case Bytecodes::_invokestatic: do_invoke(str, false); break;
|
case Bytecodes::_invokestatic: do_invoke(str, false); break;
|
||||||
|
|
||||||
case Bytecodes::_invokevirtual: do_invoke(str, true); break;
|
case Bytecodes::_invokevirtual: do_invoke(str, true); break;
|
||||||
|
case Bytecodes::_invokedynamic: do_invoke(str, false); break;
|
||||||
|
|
||||||
case Bytecodes::_istore: store_local_int(str->get_index()); break;
|
case Bytecodes::_istore: store_local_int(str->get_index()); break;
|
||||||
case Bytecodes::_istore_0: store_local_int(0); break;
|
case Bytecodes::_istore_0: store_local_int(0); break;
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
THREAD); \
|
THREAD); \
|
||||||
if (HAS_PENDING_EXCEPTION) { \
|
if (HAS_PENDING_EXCEPTION) { \
|
||||||
if (PENDING_EXCEPTION->klass() == \
|
if (PENDING_EXCEPTION->klass() == \
|
||||||
SystemDictionary::threaddeath_klass()) { \
|
SystemDictionary::ThreadDeath_klass()) { \
|
||||||
/* Kill the compilation. */ \
|
/* Kill the compilation. */ \
|
||||||
fatal("unhandled ci exception"); \
|
fatal("unhandled ci exception"); \
|
||||||
return (result); \
|
return (result); \
|
||||||
|
|
|
@ -430,7 +430,7 @@ void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Hand
|
||||||
case JVM_CONSTANT_UnresolvedClass :
|
case JVM_CONSTANT_UnresolvedClass :
|
||||||
// Patching a class means pre-resolving it.
|
// Patching a class means pre-resolving it.
|
||||||
// The name in the constant pool is ignored.
|
// The name in the constant pool is ignored.
|
||||||
if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance
|
if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance
|
||||||
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
||||||
"Illegal class patch at %d in class file %s",
|
"Illegal class patch at %d in class file %s",
|
||||||
index, CHECK);
|
index, CHECK);
|
||||||
|
@ -643,7 +643,7 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur
|
||||||
guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
|
guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
|
||||||
break;
|
break;
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;", 18)
|
guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
|
||||||
&& (value_type.is_string() || value_type.is_unresolved_string())),
|
&& (value_type.is_string() || value_type.is_unresolved_string())),
|
||||||
"Bad string initial value in class file %s", CHECK);
|
"Bad string initial value in class file %s", CHECK);
|
||||||
break;
|
break;
|
||||||
|
@ -1718,9 +1718,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||||
m->set_exception_table(exception_handlers());
|
m->set_exception_table(exception_handlers());
|
||||||
|
|
||||||
// Copy byte codes
|
// Copy byte codes
|
||||||
if (code_length > 0) {
|
m->set_code(code_start);
|
||||||
memcpy(m->code_base(), code_start, code_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy line number table
|
// Copy line number table
|
||||||
if (linenumber_table != NULL) {
|
if (linenumber_table != NULL) {
|
||||||
|
@ -3471,8 +3469,8 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if this klass supports the java.lang.Cloneable interface
|
// Check if this klass supports the java.lang.Cloneable interface
|
||||||
if (SystemDictionary::cloneable_klass_loaded()) {
|
if (SystemDictionary::Cloneable_klass_loaded()) {
|
||||||
if (k->is_subtype_of(SystemDictionary::cloneable_klass())) {
|
if (k->is_subtype_of(SystemDictionary::Cloneable_klass())) {
|
||||||
k->set_is_cloneable();
|
k->set_is_cloneable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4178,7 +4176,7 @@ char* ClassFileParser::skip_over_field_name(char* name, bool slash_ok, unsigned
|
||||||
// Check if ch is Java identifier start or is Java identifier part
|
// Check if ch is Java identifier start or is Java identifier part
|
||||||
// 4672820: call java.lang.Character methods directly without generating separate tables.
|
// 4672820: call java.lang.Character methods directly without generating separate tables.
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
instanceKlassHandle klass (THREAD, SystemDictionary::char_klass());
|
instanceKlassHandle klass (THREAD, SystemDictionary::Character_klass());
|
||||||
|
|
||||||
// return value
|
// return value
|
||||||
JavaValue result(T_BOOLEAN);
|
JavaValue result(T_BOOLEAN);
|
||||||
|
|
|
@ -819,7 +819,7 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||||
_package_hash_table->copy_pkgnames(packages);
|
_package_hash_table->copy_pkgnames(packages);
|
||||||
}
|
}
|
||||||
// Allocate objArray and fill with java.lang.String
|
// Allocate objArray and fill with java.lang.String
|
||||||
objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
|
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
|
||||||
nof_entries, CHECK_0);
|
nof_entries, CHECK_0);
|
||||||
objArrayHandle result(THREAD, r);
|
objArrayHandle result(THREAD, r);
|
||||||
for (int i = 0; i < nof_entries; i++) {
|
for (int i = 0; i < nof_entries; i++) {
|
||||||
|
|
|
@ -95,14 +95,14 @@ oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
|
||||||
int len;
|
int len;
|
||||||
typeArrayOop t;
|
typeArrayOop t;
|
||||||
len = OptionList::count(_packages);
|
len = OptionList::count(_packages);
|
||||||
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
|
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
|
||||||
objArrayHandle pkgNames (THREAD, pn);
|
objArrayHandle pkgNames (THREAD, pn);
|
||||||
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
||||||
typeArrayHandle pkgEnabled(THREAD, t);
|
typeArrayHandle pkgEnabled(THREAD, t);
|
||||||
fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
|
fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
|
||||||
|
|
||||||
len = OptionList::count(_classes);
|
len = OptionList::count(_classes);
|
||||||
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
|
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
|
||||||
objArrayHandle classNames (THREAD, cn);
|
objArrayHandle classNames (THREAD, cn);
|
||||||
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
||||||
typeArrayHandle classEnabled(THREAD, t);
|
typeArrayHandle classEnabled(THREAD, t);
|
||||||
|
|
|
@ -68,9 +68,9 @@ Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
||||||
// and the char array it points to end up in the same cache line.
|
// and the char array it points to end up in the same cache line.
|
||||||
oop obj;
|
oop obj;
|
||||||
if (tenured) {
|
if (tenured) {
|
||||||
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_permanent_instance(CHECK_NH);
|
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_permanent_instance(CHECK_NH);
|
||||||
} else {
|
} else {
|
||||||
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_instance(CHECK_NH);
|
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the char array. The String object must be handlized here
|
// Create the char array. The String object must be handlized here
|
||||||
|
@ -293,7 +293,7 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
|
||||||
|
|
||||||
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
||||||
assert(SharedSkipVerify ||
|
assert(SharedSkipVerify ||
|
||||||
java_string->klass() == SystemDictionary::string_klass(),
|
java_string->klass() == SystemDictionary::String_klass(),
|
||||||
"must be java_string");
|
"must be java_string");
|
||||||
typeArrayOop value = java_lang_String::value(java_string);
|
typeArrayOop value = java_lang_String::value(java_string);
|
||||||
int offset = java_lang_String::offset(java_string);
|
int offset = java_lang_String::offset(java_string);
|
||||||
|
@ -311,7 +311,7 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
||||||
|
|
||||||
void java_lang_String::print(Handle java_string, outputStream* st) {
|
void java_lang_String::print(Handle java_string, outputStream* st) {
|
||||||
oop obj = java_string();
|
oop obj = java_string();
|
||||||
assert(obj->klass() == SystemDictionary::string_klass(), "must be java_string");
|
assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string");
|
||||||
typeArrayOop value = java_lang_String::value(obj);
|
typeArrayOop value = java_lang_String::value(obj);
|
||||||
int offset = java_lang_String::offset(obj);
|
int offset = java_lang_String::offset(obj);
|
||||||
int length = java_lang_String::length(obj);
|
int length = java_lang_String::length(obj);
|
||||||
|
@ -339,9 +339,9 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
|
||||||
// class is put into the system dictionary.
|
// class is put into the system dictionary.
|
||||||
int computed_modifiers = k->compute_modifier_flags(CHECK_0);
|
int computed_modifiers = k->compute_modifier_flags(CHECK_0);
|
||||||
k->set_modifier_flags(computed_modifiers);
|
k->set_modifier_flags(computed_modifiers);
|
||||||
if (SystemDictionary::class_klass_loaded()) {
|
if (SystemDictionary::Class_klass_loaded()) {
|
||||||
// Allocate mirror (java.lang.Class instance)
|
// Allocate mirror (java.lang.Class instance)
|
||||||
Handle mirror = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
|
Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
|
||||||
// Setup indirections
|
// Setup indirections
|
||||||
mirror->obj_field_put(klass_offset, k());
|
mirror->obj_field_put(klass_offset, k());
|
||||||
k->set_java_mirror(mirror());
|
k->set_java_mirror(mirror());
|
||||||
|
@ -378,7 +378,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
|
||||||
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
|
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
|
||||||
// This should be improved by adding a field at the Java level or by
|
// This should be improved by adding a field at the Java level or by
|
||||||
// introducing a new VM klass (see comment in ClassFileParser)
|
// introducing a new VM klass (see comment in ClassFileParser)
|
||||||
oop java_class = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
|
oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
|
||||||
if (type != T_VOID) {
|
if (type != T_VOID) {
|
||||||
klassOop aklass = Universe::typeArrayKlassObj(type);
|
klassOop aklass = Universe::typeArrayKlassObj(type);
|
||||||
assert(aklass != NULL, "correct bootstrap");
|
assert(aklass != NULL, "correct bootstrap");
|
||||||
|
@ -502,7 +502,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klas
|
||||||
|
|
||||||
oop java_lang_Class::primitive_mirror(BasicType t) {
|
oop java_lang_Class::primitive_mirror(BasicType t) {
|
||||||
oop mirror = Universe::java_mirror(t);
|
oop mirror = Universe::java_mirror(t);
|
||||||
assert(mirror != NULL && mirror->is_a(SystemDictionary::class_klass()), "must be a Class");
|
assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class");
|
||||||
assert(java_lang_Class::is_primitive(mirror), "must be primitive");
|
assert(java_lang_Class::is_primitive(mirror), "must be primitive");
|
||||||
return mirror;
|
return mirror;
|
||||||
}
|
}
|
||||||
|
@ -515,14 +515,14 @@ void java_lang_Class::compute_offsets() {
|
||||||
assert(!offsets_computed, "offsets should be initialized only once");
|
assert(!offsets_computed, "offsets should be initialized only once");
|
||||||
offsets_computed = true;
|
offsets_computed = true;
|
||||||
|
|
||||||
klassOop k = SystemDictionary::class_klass();
|
klassOop k = SystemDictionary::Class_klass();
|
||||||
// The classRedefinedCount field is only present starting in 1.5,
|
// The classRedefinedCount field is only present starting in 1.5,
|
||||||
// so don't go fatal.
|
// so don't go fatal.
|
||||||
compute_optional_offset(classRedefinedCount_offset,
|
compute_optional_offset(classRedefinedCount_offset,
|
||||||
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
|
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
|
||||||
|
|
||||||
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
|
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
|
||||||
klassOop k1 = SystemDictionary::classloader_klass();
|
klassOop k1 = SystemDictionary::ClassLoader_klass();
|
||||||
compute_optional_offset(parallelCapable_offset,
|
compute_optional_offset(parallelCapable_offset,
|
||||||
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
|
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,7 @@ int java_lang_Thread::_park_event_offset = 0 ;
|
||||||
void java_lang_Thread::compute_offsets() {
|
void java_lang_Thread::compute_offsets() {
|
||||||
assert(_group_offset == 0, "offsets should be initialized only once");
|
assert(_group_offset == 0, "offsets should be initialized only once");
|
||||||
|
|
||||||
klassOop k = SystemDictionary::thread_klass();
|
klassOop k = SystemDictionary::Thread_klass();
|
||||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature());
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature());
|
||||||
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
|
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
|
||||||
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
|
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
|
||||||
|
@ -847,7 +847,7 @@ bool java_lang_ThreadGroup::is_vmAllowSuspension(oop java_thread_group) {
|
||||||
void java_lang_ThreadGroup::compute_offsets() {
|
void java_lang_ThreadGroup::compute_offsets() {
|
||||||
assert(_parent_offset == 0, "offsets should be initialized only once");
|
assert(_parent_offset == 0, "offsets should be initialized only once");
|
||||||
|
|
||||||
klassOop k = SystemDictionary::threadGroup_klass();
|
klassOop k = SystemDictionary::ThreadGroup_klass();
|
||||||
|
|
||||||
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
|
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
|
||||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
|
@ -1344,7 +1344,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
|
||||||
// No-op if stack trace is disabled
|
// No-op if stack trace is disabled
|
||||||
if (!StackTraceInThrowable) return;
|
if (!StackTraceInThrowable) return;
|
||||||
|
|
||||||
assert(throwable->is_a(SystemDictionary::throwable_klass()), "sanity check");
|
assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check");
|
||||||
|
|
||||||
oop backtrace = java_lang_Throwable::backtrace(throwable());
|
oop backtrace = java_lang_Throwable::backtrace(throwable());
|
||||||
assert(backtrace != NULL, "backtrace not preallocated");
|
assert(backtrace != NULL, "backtrace not preallocated");
|
||||||
|
@ -1449,7 +1449,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||||
assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
|
assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
|
||||||
|
|
||||||
// Allocate java.lang.StackTraceElement instance
|
// Allocate java.lang.StackTraceElement instance
|
||||||
klassOop k = SystemDictionary::stackTraceElement_klass();
|
klassOop k = SystemDictionary::StackTraceElement_klass();
|
||||||
assert(k != NULL, "must be loaded in 1.4+");
|
assert(k != NULL, "must be loaded in 1.4+");
|
||||||
instanceKlassHandle ik (THREAD, k);
|
instanceKlassHandle ik (THREAD, k);
|
||||||
if (ik->should_be_initialized()) {
|
if (ik->should_be_initialized()) {
|
||||||
|
@ -1487,7 +1487,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||||
|
|
||||||
|
|
||||||
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_accessible_object_klass();
|
klassOop k = SystemDictionary::reflect_AccessibleObject_klass();
|
||||||
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
|
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1502,7 +1502,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Method::compute_offsets() {
|
void java_lang_reflect_Method::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_method_klass();
|
klassOop k = SystemDictionary::reflect_Method_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
|
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
|
||||||
|
@ -1523,7 +1523,7 @@ void java_lang_reflect_Method::compute_offsets() {
|
||||||
|
|
||||||
Handle java_lang_reflect_Method::create(TRAPS) {
|
Handle java_lang_reflect_Method::create(TRAPS) {
|
||||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||||
klassOop klass = SystemDictionary::reflect_method_klass();
|
klassOop klass = SystemDictionary::reflect_Method_klass();
|
||||||
// This class is eagerly initialized during VM initialization, since we keep a refence
|
// This class is eagerly initialized during VM initialization, since we keep a refence
|
||||||
// to one of the methods
|
// to one of the methods
|
||||||
assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized");
|
assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized");
|
||||||
|
@ -1665,7 +1665,7 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Constructor::compute_offsets() {
|
void java_lang_reflect_Constructor::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_constructor_klass();
|
klassOop k = SystemDictionary::reflect_Constructor_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
|
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
|
||||||
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
|
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
|
||||||
|
@ -1789,7 +1789,7 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Field::compute_offsets() {
|
void java_lang_reflect_Field::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_field_klass();
|
klassOop k = SystemDictionary::reflect_Field_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
|
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
|
||||||
|
@ -1896,7 +1896,7 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) {
|
||||||
|
|
||||||
|
|
||||||
void sun_reflect_ConstantPool::compute_offsets() {
|
void sun_reflect_ConstantPool::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_constant_pool_klass();
|
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
|
||||||
// This null test can be removed post beta
|
// This null test can be removed post beta
|
||||||
if (k != NULL) {
|
if (k != NULL) {
|
||||||
compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature());
|
compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature());
|
||||||
|
@ -1906,7 +1906,7 @@ void sun_reflect_ConstantPool::compute_offsets() {
|
||||||
|
|
||||||
Handle sun_reflect_ConstantPool::create(TRAPS) {
|
Handle sun_reflect_ConstantPool::create(TRAPS) {
|
||||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||||
klassOop k = SystemDictionary::reflect_constant_pool_klass();
|
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
|
||||||
instanceKlassHandle klass (THREAD, k);
|
instanceKlassHandle klass (THREAD, k);
|
||||||
// Ensure it is initialized
|
// Ensure it is initialized
|
||||||
klass->initialize(CHECK_NH);
|
klass->initialize(CHECK_NH);
|
||||||
|
@ -1926,7 +1926,7 @@ void sun_reflect_ConstantPool::set_cp_oop(oop reflect, oop value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
|
void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass();
|
klassOop k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
|
||||||
// This null test can be removed post beta
|
// This null test can be removed post beta
|
||||||
if (k != NULL) {
|
if (k != NULL) {
|
||||||
compute_offset(_base_offset, k,
|
compute_offset(_base_offset, k,
|
||||||
|
@ -2072,7 +2072,7 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream*
|
||||||
|
|
||||||
// Support for java_lang_ref_Reference
|
// Support for java_lang_ref_Reference
|
||||||
oop java_lang_ref_Reference::pending_list_lock() {
|
oop java_lang_ref_Reference::pending_list_lock() {
|
||||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
|
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
|
||||||
char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset);
|
char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset);
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
return oopDesc::load_decode_heap_oop((narrowOop *)addr);
|
return oopDesc::load_decode_heap_oop((narrowOop *)addr);
|
||||||
|
@ -2082,7 +2082,7 @@ oop java_lang_ref_Reference::pending_list_lock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord *java_lang_ref_Reference::pending_list_addr() {
|
HeapWord *java_lang_ref_Reference::pending_list_addr() {
|
||||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
|
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
|
||||||
char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset);
|
char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset);
|
||||||
// XXX This might not be HeapWord aligned, almost rather be char *.
|
// XXX This might not be HeapWord aligned, almost rather be char *.
|
||||||
return (HeapWord*)addr;
|
return (HeapWord*)addr;
|
||||||
|
@ -2105,17 +2105,17 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) {
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong java_lang_ref_SoftReference::clock() {
|
jlong java_lang_ref_SoftReference::clock() {
|
||||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
|
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
|
||||||
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
||||||
|
|
||||||
return SystemDictionary::soft_reference_klass()->long_field(offset);
|
return SystemDictionary::SoftReference_klass()->long_field(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_ref_SoftReference::set_clock(jlong value) {
|
void java_lang_ref_SoftReference::set_clock(jlong value) {
|
||||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
|
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
|
||||||
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
||||||
|
|
||||||
SystemDictionary::soft_reference_klass()->long_field_put(offset, value);
|
SystemDictionary::SoftReference_klass()->long_field_put(offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2403,6 +2403,10 @@ oop java_dyn_MethodType::ptype(oop mt, int idx) {
|
||||||
return ptypes(mt)->obj_at(idx);
|
return ptypes(mt)->obj_at(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int java_dyn_MethodType::ptype_count(oop mt) {
|
||||||
|
return ptypes(mt)->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Support for java_dyn_MethodTypeForm
|
// Support for java_dyn_MethodTypeForm
|
||||||
|
@ -2534,7 +2538,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
|
||||||
// the generated bytecodes for reflection, and if so, "magically"
|
// the generated bytecodes for reflection, and if so, "magically"
|
||||||
// delegate to its parent to prevent class loading from occurring
|
// delegate to its parent to prevent class loading from occurring
|
||||||
// in places where applications using reflection didn't expect it.
|
// in places where applications using reflection didn't expect it.
|
||||||
klassOop delegating_cl_class = SystemDictionary::reflect_delegating_classloader_klass();
|
klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass();
|
||||||
// This might be null in non-1.4 JDKs
|
// This might be null in non-1.4 JDKs
|
||||||
if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
|
if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
|
||||||
return parent(loader);
|
return parent(loader);
|
||||||
|
@ -2549,7 +2553,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
|
||||||
void java_lang_System::compute_offsets() {
|
void java_lang_System::compute_offsets() {
|
||||||
assert(offset_of_static_fields == 0, "offsets should be initialized only once");
|
assert(offset_of_static_fields == 0, "offsets should be initialized only once");
|
||||||
|
|
||||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::system_klass());
|
instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass());
|
||||||
offset_of_static_fields = ik->offset_of_static_fields();
|
offset_of_static_fields = ik->offset_of_static_fields();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ class java_lang_String : AllStatic {
|
||||||
|
|
||||||
// Testers
|
// Testers
|
||||||
static bool is_instance(oop obj) {
|
static bool is_instance(oop obj) {
|
||||||
return obj != NULL && obj->klass() == SystemDictionary::string_klass();
|
return obj != NULL && obj->klass() == SystemDictionary::String_klass();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
|
@ -161,7 +161,7 @@ class java_lang_Class : AllStatic {
|
||||||
static void print_signature(oop java_class, outputStream *st);
|
static void print_signature(oop java_class, outputStream *st);
|
||||||
// Testing
|
// Testing
|
||||||
static bool is_instance(oop obj) {
|
static bool is_instance(oop obj) {
|
||||||
return obj != NULL && obj->klass() == SystemDictionary::class_klass();
|
return obj != NULL && obj->klass() == SystemDictionary::Class_klass();
|
||||||
}
|
}
|
||||||
static bool is_primitive(oop java_class);
|
static bool is_primitive(oop java_class);
|
||||||
static BasicType primitive_type(oop java_class);
|
static BasicType primitive_type(oop java_class);
|
||||||
|
@ -1027,6 +1027,7 @@ class java_dyn_MethodType: AllStatic {
|
||||||
static oop form(oop mt);
|
static oop form(oop mt);
|
||||||
|
|
||||||
static oop ptype(oop mt, int index);
|
static oop ptype(oop mt, int index);
|
||||||
|
static int ptype_count(oop mt);
|
||||||
|
|
||||||
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
|
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
|
||||||
static void print_signature(oop mt, outputStream* st);
|
static void print_signature(oop mt, outputStream* st);
|
||||||
|
@ -1083,6 +1084,14 @@ public:
|
||||||
static oop vmmethod(oop site);
|
static oop vmmethod(oop site);
|
||||||
static void set_vmmethod(oop site, oop ref);
|
static void set_vmmethod(oop site, oop ref);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
// Accessors for code generation:
|
// Accessors for code generation:
|
||||||
static int target_offset_in_bytes() { return _target_offset; }
|
static int target_offset_in_bytes() { return _target_offset; }
|
||||||
static int type_offset_in_bytes() { return _type_offset; }
|
static int type_offset_in_bytes() { return _type_offset; }
|
||||||
|
|
|
@ -60,10 +60,10 @@ oop SystemDictionary::java_system_loader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemDictionary::compute_java_system_loader(TRAPS) {
|
void SystemDictionary::compute_java_system_loader(TRAPS) {
|
||||||
KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass));
|
KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass));
|
||||||
JavaValue result(T_OBJECT);
|
JavaValue result(T_OBJECT);
|
||||||
JavaCalls::call_static(&result,
|
JavaCalls::call_static(&result,
|
||||||
KlassHandle(THREAD, WK_KLASS(classloader_klass)),
|
KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
|
||||||
vmSymbolHandles::getSystemClassLoader_name(),
|
vmSymbolHandles::getSystemClassLoader_name(),
|
||||||
vmSymbolHandles::void_classloader_signature(),
|
vmSymbolHandles::void_classloader_signature(),
|
||||||
CHECK);
|
CHECK);
|
||||||
|
@ -128,7 +128,7 @@ klassOop SystemDictionary::handle_resolution_exception(symbolHandle class_name,
|
||||||
// in which case we have to check whether the pending exception is a ClassNotFoundException,
|
// in which case we have to check whether the pending exception is a ClassNotFoundException,
|
||||||
// and if so convert it to a NoClassDefFoundError
|
// and if so convert it to a NoClassDefFoundError
|
||||||
// And chain the original ClassNotFoundException
|
// And chain the original ClassNotFoundException
|
||||||
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) {
|
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
assert(klass_h() == NULL, "Should not have result with exception pending");
|
assert(klass_h() == NULL, "Should not have result with exception pending");
|
||||||
Handle e(THREAD, PENDING_EXCEPTION);
|
Handle e(THREAD, PENDING_EXCEPTION);
|
||||||
|
@ -359,7 +359,7 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass,
|
||||||
|
|
||||||
assert(class_loader() != NULL, "should not have non-null protection domain for null classloader");
|
assert(class_loader() != NULL, "should not have non-null protection domain for null classloader");
|
||||||
|
|
||||||
KlassHandle system_loader(THREAD, SystemDictionary::classloader_klass());
|
KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass());
|
||||||
JavaCalls::call_special(&result,
|
JavaCalls::call_special(&result,
|
||||||
class_loader,
|
class_loader,
|
||||||
system_loader,
|
system_loader,
|
||||||
|
@ -743,7 +743,7 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam
|
||||||
// Bootstrap goes through here to allow for an extra guarantee check
|
// Bootstrap goes through here to allow for an extra guarantee check
|
||||||
if (UnsyncloadClass || (class_loader.is_null())) {
|
if (UnsyncloadClass || (class_loader.is_null())) {
|
||||||
if (k.is_null() && HAS_PENDING_EXCEPTION
|
if (k.is_null() && HAS_PENDING_EXCEPTION
|
||||||
&& PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) {
|
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
|
||||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||||
klassOop check = find_class(d_index, d_hash, name, class_loader);
|
klassOop check = find_class(d_index, d_hash, name, class_loader);
|
||||||
if (check != NULL) {
|
if (check != NULL) {
|
||||||
|
@ -1367,7 +1367,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam
|
||||||
|
|
||||||
JavaValue result(T_OBJECT);
|
JavaValue result(T_OBJECT);
|
||||||
|
|
||||||
KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass());
|
KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass());
|
||||||
|
|
||||||
// Call public unsynchronized loadClass(String) directly for all class loaders
|
// Call public unsynchronized loadClass(String) directly for all class loaders
|
||||||
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will
|
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will
|
||||||
|
@ -1944,13 +1944,13 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
|
||||||
|
|
||||||
|
|
||||||
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once");
|
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
|
||||||
// Preload commonly used klasses
|
// Preload commonly used klasses
|
||||||
WKID scan = FIRST_WKID;
|
WKID scan = FIRST_WKID;
|
||||||
// first do Object, String, Class
|
// first do Object, String, Class
|
||||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK);
|
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
|
||||||
|
|
||||||
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass)));
|
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass)));
|
||||||
|
|
||||||
// Fixup mirrors for classes loaded before java.lang.Class.
|
// Fixup mirrors for classes loaded before java.lang.Class.
|
||||||
// These calls iterate over the objects currently in the perm gen
|
// These calls iterate over the objects currently in the perm gen
|
||||||
|
@ -1961,17 +1961,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
Universe::fixup_mirrors(CHECK);
|
Universe::fixup_mirrors(CHECK);
|
||||||
|
|
||||||
// do a bunch more:
|
// do a bunch more:
|
||||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK);
|
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK);
|
||||||
|
|
||||||
// Preload ref klasses and set reference types
|
// Preload ref klasses and set reference types
|
||||||
instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER);
|
instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
|
||||||
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass));
|
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
|
||||||
|
|
||||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK);
|
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
|
||||||
instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT);
|
instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
|
||||||
instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK);
|
instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
|
||||||
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
|
||||||
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
|
||||||
|
|
||||||
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
||||||
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
||||||
|
@ -1984,7 +1984,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
scan = WKID(meth_group_end+1);
|
scan = WKID(meth_group_end+1);
|
||||||
}
|
}
|
||||||
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
|
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
|
||||||
WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
|
WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass);
|
||||||
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
|
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
|
||||||
if (EnableInvokeDynamic) {
|
if (EnableInvokeDynamic) {
|
||||||
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
|
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
|
||||||
|
@ -1996,14 +1996,14 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
|
|
||||||
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
||||||
|
|
||||||
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
_box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
|
||||||
_box_klasses[T_CHAR] = WK_KLASS(char_klass);
|
_box_klasses[T_CHAR] = WK_KLASS(Character_klass);
|
||||||
_box_klasses[T_FLOAT] = WK_KLASS(float_klass);
|
_box_klasses[T_FLOAT] = WK_KLASS(Float_klass);
|
||||||
_box_klasses[T_DOUBLE] = WK_KLASS(double_klass);
|
_box_klasses[T_DOUBLE] = WK_KLASS(Double_klass);
|
||||||
_box_klasses[T_BYTE] = WK_KLASS(byte_klass);
|
_box_klasses[T_BYTE] = WK_KLASS(Byte_klass);
|
||||||
_box_klasses[T_SHORT] = WK_KLASS(short_klass);
|
_box_klasses[T_SHORT] = WK_KLASS(Short_klass);
|
||||||
_box_klasses[T_INT] = WK_KLASS(int_klass);
|
_box_klasses[T_INT] = WK_KLASS(Integer_klass);
|
||||||
_box_klasses[T_LONG] = WK_KLASS(long_klass);
|
_box_klasses[T_LONG] = WK_KLASS(Long_klass);
|
||||||
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
|
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
|
||||||
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
|
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
|
||||||
|
|
||||||
|
@ -2014,11 +2014,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
#endif // KERNEL
|
#endif // KERNEL
|
||||||
|
|
||||||
{ // Compute whether we should use loadClass or loadClassInternal when loading classes.
|
{ // Compute whether we should use loadClass or loadClassInternal when loading classes.
|
||||||
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
|
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
|
||||||
_has_loadClassInternal = (method != NULL);
|
_has_loadClassInternal = (method != NULL);
|
||||||
}
|
}
|
||||||
{ // Compute whether we should use checkPackageAccess or NOT
|
{ // Compute whether we should use checkPackageAccess or NOT
|
||||||
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
|
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
|
||||||
_has_checkPackageAccess = (method != NULL);
|
_has_checkPackageAccess = (method != NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2340,6 +2340,8 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
||||||
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||||
if (spe == NULL || spe->property_oop() == NULL) {
|
if (spe == NULL || spe->property_oop() == NULL) {
|
||||||
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||||
|
if (THREAD->is_Compiler_thread())
|
||||||
|
return NULL; // do not attempt from within compiler
|
||||||
Handle mt = compute_method_handle_type(signature(),
|
Handle mt = compute_method_handle_type(signature(),
|
||||||
class_loader, protection_domain,
|
class_loader, protection_domain,
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
@ -2372,7 +2374,7 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
Handle empty;
|
Handle empty;
|
||||||
int npts = ArgumentCount(signature()).size();
|
int npts = ArgumentCount(signature()).size();
|
||||||
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
|
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
|
||||||
int arg = 0;
|
int arg = 0;
|
||||||
Handle rt; // the return type from the signature
|
Handle rt; // the return type from the signature
|
||||||
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
|
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -82,55 +82,55 @@ class SymbolPropertyTable;
|
||||||
|
|
||||||
#define WK_KLASSES_DO(template) \
|
#define WK_KLASSES_DO(template) \
|
||||||
/* well-known classes */ \
|
/* well-known classes */ \
|
||||||
template(object_klass, java_lang_Object, Pre) \
|
template(Object_klass, java_lang_Object, Pre) \
|
||||||
template(string_klass, java_lang_String, Pre) \
|
template(String_klass, java_lang_String, Pre) \
|
||||||
template(class_klass, java_lang_Class, Pre) \
|
template(Class_klass, java_lang_Class, Pre) \
|
||||||
template(cloneable_klass, java_lang_Cloneable, Pre) \
|
template(Cloneable_klass, java_lang_Cloneable, Pre) \
|
||||||
template(classloader_klass, java_lang_ClassLoader, Pre) \
|
template(ClassLoader_klass, java_lang_ClassLoader, Pre) \
|
||||||
template(serializable_klass, java_io_Serializable, Pre) \
|
template(Serializable_klass, java_io_Serializable, Pre) \
|
||||||
template(system_klass, java_lang_System, Pre) \
|
template(System_klass, java_lang_System, Pre) \
|
||||||
template(throwable_klass, java_lang_Throwable, Pre) \
|
template(Throwable_klass, java_lang_Throwable, Pre) \
|
||||||
template(error_klass, java_lang_Error, Pre) \
|
template(Error_klass, java_lang_Error, Pre) \
|
||||||
template(threaddeath_klass, java_lang_ThreadDeath, Pre) \
|
template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \
|
||||||
template(exception_klass, java_lang_Exception, Pre) \
|
template(Exception_klass, java_lang_Exception, Pre) \
|
||||||
template(runtime_exception_klass, java_lang_RuntimeException, Pre) \
|
template(RuntimeException_klass, java_lang_RuntimeException, Pre) \
|
||||||
template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \
|
template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \
|
||||||
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \
|
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \
|
||||||
template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
|
template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
|
||||||
template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
|
template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
|
||||||
template(linkageError_klass, java_lang_LinkageError, Pre) \
|
template(LinkageError_klass, java_lang_LinkageError, Pre) \
|
||||||
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \
|
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \
|
||||||
template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \
|
template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \
|
||||||
template(virtualMachineError_klass, java_lang_VirtualMachineError, Pre) \
|
template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \
|
||||||
template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \
|
template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \
|
||||||
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \
|
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \
|
||||||
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \
|
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \
|
||||||
template(reference_klass, java_lang_ref_Reference, Pre) \
|
template(Reference_klass, java_lang_ref_Reference, Pre) \
|
||||||
\
|
\
|
||||||
/* Preload ref klasses and set reference types */ \
|
/* Preload ref klasses and set reference types */ \
|
||||||
template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \
|
template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \
|
||||||
template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \
|
template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \
|
||||||
template(final_reference_klass, java_lang_ref_FinalReference, Pre) \
|
template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \
|
||||||
template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \
|
template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \
|
||||||
template(finalizer_klass, java_lang_ref_Finalizer, Pre) \
|
template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \
|
||||||
\
|
\
|
||||||
template(thread_klass, java_lang_Thread, Pre) \
|
template(Thread_klass, java_lang_Thread, Pre) \
|
||||||
template(threadGroup_klass, java_lang_ThreadGroup, Pre) \
|
template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \
|
||||||
template(properties_klass, java_util_Properties, Pre) \
|
template(Properties_klass, java_util_Properties, Pre) \
|
||||||
template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \
|
template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \
|
||||||
template(reflect_field_klass, java_lang_reflect_Field, Pre) \
|
template(reflect_Field_klass, java_lang_reflect_Field, Pre) \
|
||||||
template(reflect_method_klass, java_lang_reflect_Method, Pre) \
|
template(reflect_Method_klass, java_lang_reflect_Method, Pre) \
|
||||||
template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \
|
template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \
|
||||||
\
|
\
|
||||||
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
||||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||||
template(reflect_magic_klass, sun_reflect_MagicAccessorImpl, Opt) \
|
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
|
||||||
template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||||
template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||||
template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \
|
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
|
||||||
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||||
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||||
\
|
\
|
||||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||||
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
|
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
|
||||||
|
@ -144,16 +144,14 @@ class SymbolPropertyTable;
|
||||||
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
||||||
template(Linkage_klass, java_dyn_Linkage, Opt) \
|
template(Linkage_klass, java_dyn_Linkage, Opt) \
|
||||||
template(CallSite_klass, java_dyn_CallSite, Opt) \
|
template(CallSite_klass, java_dyn_CallSite, Opt) \
|
||||||
template(Dynamic_klass, java_dyn_Dynamic, Opt) \
|
template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \
|
||||||
/* Note: MethodHandle must be first, and Dynamic last in group */ \
|
/* Note: MethodHandle must be first, and InvokeDynamic last in group */ \
|
||||||
\
|
\
|
||||||
template(vector_klass, java_util_Vector, Pre) \
|
template(StringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||||
template(hashtable_klass, java_util_Hashtable, Pre) \
|
|
||||||
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
|
||||||
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
|
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
|
||||||
\
|
\
|
||||||
/* It's NULL in non-1.4 JDKs. */ \
|
/* It's NULL in non-1.4 JDKs. */ \
|
||||||
template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \
|
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \
|
||||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||||
template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \
|
template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \
|
||||||
|
@ -164,14 +162,14 @@ class SymbolPropertyTable;
|
||||||
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
|
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
|
||||||
\
|
\
|
||||||
/* Preload boxing klasses */ \
|
/* Preload boxing klasses */ \
|
||||||
template(boolean_klass, java_lang_Boolean, Pre) \
|
template(Boolean_klass, java_lang_Boolean, Pre) \
|
||||||
template(char_klass, java_lang_Character, Pre) \
|
template(Character_klass, java_lang_Character, Pre) \
|
||||||
template(float_klass, java_lang_Float, Pre) \
|
template(Float_klass, java_lang_Float, Pre) \
|
||||||
template(double_klass, java_lang_Double, Pre) \
|
template(Double_klass, java_lang_Double, Pre) \
|
||||||
template(byte_klass, java_lang_Byte, Pre) \
|
template(Byte_klass, java_lang_Byte, Pre) \
|
||||||
template(short_klass, java_lang_Short, Pre) \
|
template(Short_klass, java_lang_Short, Pre) \
|
||||||
template(int_klass, java_lang_Integer, Pre) \
|
template(Integer_klass, java_lang_Integer, Pre) \
|
||||||
template(long_klass, java_lang_Long, Pre) \
|
template(Long_klass, java_lang_Long, Pre) \
|
||||||
/*end*/
|
/*end*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -438,8 +436,8 @@ public:
|
||||||
// Tells whether ClassLoader.checkPackageAccess is present
|
// Tells whether ClassLoader.checkPackageAccess is present
|
||||||
static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
|
static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
|
||||||
|
|
||||||
static bool class_klass_loaded() { return WK_KLASS(class_klass) != NULL; }
|
static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
|
||||||
static bool cloneable_klass_loaded() { return WK_KLASS(cloneable_klass) != NULL; }
|
static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
|
||||||
|
|
||||||
// Returns default system loader
|
// Returns default system loader
|
||||||
static oop java_system_loader();
|
static oop java_system_loader();
|
||||||
|
|
|
@ -143,7 +143,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
|
||||||
|
|
||||||
bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
|
bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
|
||||||
symbolOop name = klass->name();
|
symbolOop name = klass->name();
|
||||||
klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass();
|
klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass();
|
||||||
|
|
||||||
return (should_verify_for(klass->class_loader(), should_verify_class) &&
|
return (should_verify_for(klass->class_loader(), should_verify_class) &&
|
||||||
// return if the class is a bootstrapping class
|
// return if the class is a bootstrapping class
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -70,6 +70,7 @@ static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGN
|
||||||
void vmSymbols::initialize(TRAPS) {
|
void vmSymbols::initialize(TRAPS) {
|
||||||
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
|
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
|
||||||
assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
|
assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
|
||||||
|
assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield");
|
||||||
|
|
||||||
if (!UseSharedSpaces) {
|
if (!UseSharedSpaces) {
|
||||||
const char* string = &vm_symbol_bodies[0];
|
const char* string = &vm_symbol_bodies[0];
|
||||||
|
@ -271,6 +272,58 @@ vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) {
|
||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) {
|
||||||
|
#define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0))
|
||||||
|
switch (TYPE2(type, unboxing)) {
|
||||||
|
#define BASIC_TYPE_CASE(type, box, unbox) \
|
||||||
|
case TYPE2(type, false): return vmIntrinsics::box; \
|
||||||
|
case TYPE2(type, true): return vmIntrinsics::unbox
|
||||||
|
BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue);
|
||||||
|
BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue);
|
||||||
|
BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue);
|
||||||
|
BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue);
|
||||||
|
BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue);
|
||||||
|
BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue);
|
||||||
|
BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue);
|
||||||
|
BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue);
|
||||||
|
#undef BASIC_TYPE_CASE
|
||||||
|
}
|
||||||
|
#undef TYPE2
|
||||||
|
return vmIntrinsics::_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) {
|
||||||
|
return wrapper_intrinsic(type, false);
|
||||||
|
}
|
||||||
|
vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) {
|
||||||
|
return wrapper_intrinsic(type, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) {
|
||||||
|
#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
|
||||||
|
switch (SRC_DEST(src, dest)) {
|
||||||
|
case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat;
|
||||||
|
case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits;
|
||||||
|
|
||||||
|
case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble;
|
||||||
|
case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits;
|
||||||
|
}
|
||||||
|
#undef SRC_DEST
|
||||||
|
|
||||||
|
return vmIntrinsics::_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) {
|
||||||
|
if (id == _none) return NULL;
|
||||||
|
symbolOop cname = vmSymbols::symbol_at(class_for(id));
|
||||||
|
symbolOop mname = vmSymbols::symbol_at(name_for(id));
|
||||||
|
symbolOop msig = vmSymbols::symbol_at(signature_for(id));
|
||||||
|
if (cname == NULL || mname == NULL || msig == NULL) return NULL;
|
||||||
|
klassOop k = SystemDictionary::find_well_known_klass(cname);
|
||||||
|
if (k == NULL) return NULL;
|
||||||
|
return instanceKlass::cast(k)->find_method(mname, msig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
|
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
|
||||||
static const char* vm_intrinsic_name_bodies =
|
static const char* vm_intrinsic_name_bodies =
|
||||||
|
@ -330,12 +383,12 @@ inline bool match_F_RNY(jshort flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are for forming case labels:
|
// These are for forming case labels:
|
||||||
#define ID3(x, y, z) (( jint)(z) + \
|
#define ID3(x, y, z) (( jlong)(z) + \
|
||||||
((jint)(y) << vmSymbols::log2_SID_LIMIT) + \
|
((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \
|
||||||
((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
|
((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
|
||||||
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
|
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
|
||||||
|
|
||||||
vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder,
|
vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder,
|
||||||
vmSymbols::SID name,
|
vmSymbols::SID name,
|
||||||
vmSymbols::SID sig,
|
vmSymbols::SID sig,
|
||||||
jshort flags) {
|
jshort flags) {
|
||||||
|
@ -383,62 +436,50 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// These are for friendly printouts of intrinsics:
|
// These are to get information about intrinsics.
|
||||||
|
|
||||||
|
#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f))
|
||||||
|
|
||||||
|
static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = {
|
||||||
|
#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \
|
||||||
|
ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode),
|
||||||
|
|
||||||
|
0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO,
|
||||||
|
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
|
||||||
|
0
|
||||||
|
#undef VM_INTRINSIC_INFO
|
||||||
|
};
|
||||||
|
|
||||||
|
inline jlong intrinsic_info(vmIntrinsics::ID id) {
|
||||||
|
return intrinsic_info_array[vmIntrinsics::ID_from((int)id)];
|
||||||
|
}
|
||||||
|
|
||||||
vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
|
vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
|
||||||
#ifndef PRODUCT
|
jlong info = intrinsic_info(id);
|
||||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||||
case id: return SID_ENUM(klass);
|
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "");
|
||||||
|
return vmSymbols::SID( (info >> shift) & mask );
|
||||||
switch (id) {
|
|
||||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
|
||||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
|
||||||
}
|
|
||||||
#undef VM_INTRINSIC_CASE
|
|
||||||
#endif //PRODUCT
|
|
||||||
return vmSymbols::NO_SID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
|
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
|
||||||
#ifndef PRODUCT
|
jlong info = intrinsic_info(id);
|
||||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||||
case id: return SID_ENUM(name);
|
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "");
|
||||||
|
return vmSymbols::SID( (info >> shift) & mask );
|
||||||
switch (id) {
|
|
||||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
|
||||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
|
||||||
}
|
|
||||||
#undef VM_INTRINSIC_CASE
|
|
||||||
#endif //PRODUCT
|
|
||||||
return vmSymbols::NO_SID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
|
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
|
||||||
#ifndef PRODUCT
|
jlong info = intrinsic_info(id);
|
||||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||||
case id: return SID_ENUM(sig);
|
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "");
|
||||||
|
return vmSymbols::SID( (info >> shift) & mask );
|
||||||
switch (id) {
|
|
||||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
|
||||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
|
||||||
}
|
|
||||||
#undef VM_INTRINSIC_CASE
|
|
||||||
#endif //PRODUCT
|
|
||||||
return vmSymbols::NO_SID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
|
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
|
||||||
#ifndef PRODUCT
|
jlong info = intrinsic_info(id);
|
||||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT);
|
||||||
case id: return fcode;
|
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "");
|
||||||
|
return Flags( (info >> shift) & mask );
|
||||||
switch (id) {
|
|
||||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
|
||||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
|
||||||
}
|
|
||||||
#undef VM_INTRINSIC_CASE
|
|
||||||
#endif //PRODUCT
|
|
||||||
return F_none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@
|
||||||
template(base_name, "base") \
|
template(base_name, "base") \
|
||||||
\
|
\
|
||||||
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||||
template(java_dyn_Dynamic, "java/dyn/Dynamic") \
|
template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \
|
||||||
template(java_dyn_Linkage, "java/dyn/Linkage") \
|
template(java_dyn_Linkage, "java/dyn/Linkage") \
|
||||||
template(java_dyn_CallSite, "java/dyn/CallSite") \
|
template(java_dyn_CallSite, "java/dyn/CallSite") \
|
||||||
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
||||||
|
@ -347,9 +347,14 @@
|
||||||
\
|
\
|
||||||
/* common signatures names */ \
|
/* common signatures names */ \
|
||||||
template(void_method_signature, "()V") \
|
template(void_method_signature, "()V") \
|
||||||
|
template(void_boolean_signature, "()Z") \
|
||||||
|
template(void_byte_signature, "()B") \
|
||||||
|
template(void_char_signature, "()C") \
|
||||||
|
template(void_short_signature, "()S") \
|
||||||
template(void_int_signature, "()I") \
|
template(void_int_signature, "()I") \
|
||||||
template(void_long_signature, "()J") \
|
template(void_long_signature, "()J") \
|
||||||
template(void_boolean_signature, "()Z") \
|
template(void_float_signature, "()F") \
|
||||||
|
template(void_double_signature, "()D") \
|
||||||
template(int_void_signature, "(I)V") \
|
template(int_void_signature, "(I)V") \
|
||||||
template(int_int_signature, "(I)I") \
|
template(int_int_signature, "(I)I") \
|
||||||
template(int_bool_signature, "(I)Z") \
|
template(int_bool_signature, "(I)Z") \
|
||||||
|
@ -854,6 +859,46 @@
|
||||||
\
|
\
|
||||||
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
|
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
|
||||||
/* (symbols invoke_name and invoke_signature defined above) */ \
|
/* (symbols invoke_name and invoke_signature defined above) */ \
|
||||||
|
do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \
|
||||||
|
do_name( checkSpreadArgument_name, "checkSpreadArgument") \
|
||||||
|
do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \
|
||||||
|
\
|
||||||
|
/* unboxing methods: */ \
|
||||||
|
do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \
|
||||||
|
do_name( booleanValue_name, "booleanValue") \
|
||||||
|
do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \
|
||||||
|
do_name( byteValue_name, "byteValue") \
|
||||||
|
do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \
|
||||||
|
do_name( charValue_name, "charValue") \
|
||||||
|
do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \
|
||||||
|
do_name( shortValue_name, "shortValue") \
|
||||||
|
do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \
|
||||||
|
do_name( intValue_name, "intValue") \
|
||||||
|
do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \
|
||||||
|
do_name( longValue_name, "longValue") \
|
||||||
|
do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \
|
||||||
|
do_name( floatValue_name, "floatValue") \
|
||||||
|
do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \
|
||||||
|
do_name( doubleValue_name, "doubleValue") \
|
||||||
|
\
|
||||||
|
/* boxing methods: */ \
|
||||||
|
do_name( valueOf_name, "valueOf") \
|
||||||
|
do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \
|
||||||
|
do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \
|
||||||
|
do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \
|
||||||
|
do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \
|
||||||
|
do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \
|
||||||
|
do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \
|
||||||
|
do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \
|
||||||
|
do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \
|
||||||
|
do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \
|
||||||
|
do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \
|
||||||
|
do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \
|
||||||
|
do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \
|
||||||
|
do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \
|
||||||
|
do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \
|
||||||
|
do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \
|
||||||
|
do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \
|
||||||
\
|
\
|
||||||
/*end*/
|
/*end*/
|
||||||
|
|
||||||
|
@ -984,7 +1029,12 @@ class vmIntrinsics: AllStatic {
|
||||||
F_Y, // !static ?native synchronized
|
F_Y, // !static ?native synchronized
|
||||||
F_RN, // !static native !synchronized
|
F_RN, // !static native !synchronized
|
||||||
F_SN, // static native !synchronized
|
F_SN, // static native !synchronized
|
||||||
F_RNY // !static native synchronized
|
F_RNY, // !static native synchronized
|
||||||
|
|
||||||
|
FLAG_LIMIT
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
log2_FLAG_LIMIT = 4 // checked by an assert at start-up
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -996,15 +1046,32 @@ public:
|
||||||
|
|
||||||
static const char* name_at(ID id);
|
static const char* name_at(ID id);
|
||||||
|
|
||||||
// Given a method's class, name, signature, and access flags, report its ID.
|
private:
|
||||||
static ID find_id(vmSymbols::SID holder,
|
static ID find_id_impl(vmSymbols::SID holder,
|
||||||
vmSymbols::SID name,
|
vmSymbols::SID name,
|
||||||
vmSymbols::SID sig,
|
vmSymbols::SID sig,
|
||||||
jshort flags);
|
jshort flags);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Given a method's class, name, signature, and access flags, report its ID.
|
||||||
|
static ID find_id(vmSymbols::SID holder,
|
||||||
|
vmSymbols::SID name,
|
||||||
|
vmSymbols::SID sig,
|
||||||
|
jshort flags) {
|
||||||
|
ID id = find_id_impl(holder, name, sig, flags);
|
||||||
|
#ifdef ASSERT
|
||||||
|
// ID _none does not hold the following asserts.
|
||||||
|
if (id == _none) return id;
|
||||||
|
#endif
|
||||||
|
assert( class_for(id) == holder, "correct id");
|
||||||
|
assert( name_for(id) == name, "correct id");
|
||||||
|
assert(signature_for(id) == sig, "correct id");
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN;
|
static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN;
|
||||||
|
|
||||||
// No need for these in the product:
|
// Find out the symbols behind an intrinsic:
|
||||||
static vmSymbols::SID class_for(ID id);
|
static vmSymbols::SID class_for(ID id);
|
||||||
static vmSymbols::SID name_for(ID id);
|
static vmSymbols::SID name_for(ID id);
|
||||||
static vmSymbols::SID signature_for(ID id);
|
static vmSymbols::SID signature_for(ID id);
|
||||||
|
@ -1014,4 +1081,11 @@ public:
|
||||||
|
|
||||||
// Access to intrinsic methods:
|
// Access to intrinsic methods:
|
||||||
static methodOop method_for(ID id);
|
static methodOop method_for(ID id);
|
||||||
|
|
||||||
|
// Wrapper object methods:
|
||||||
|
static ID for_boxing(BasicType type);
|
||||||
|
static ID for_unboxing(BasicType type);
|
||||||
|
|
||||||
|
// Raw conversion:
|
||||||
|
static ID for_raw_conversion(BasicType src, BasicType dest);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -102,6 +102,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||||
virtual bool is_compiled_by_c2() const { return false; }
|
virtual bool is_compiled_by_c2() const { return false; }
|
||||||
virtual bool is_compiled_by_c1() const { return false; }
|
virtual bool is_compiled_by_c1() const { return false; }
|
||||||
|
|
||||||
|
// Casting
|
||||||
|
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
|
||||||
|
|
||||||
// Boundaries
|
// Boundaries
|
||||||
address header_begin() const { return (address) this; }
|
address header_begin() const { return (address) this; }
|
||||||
address header_end() const { return ((address) this) + _header_size; };
|
address header_end() const { return ((address) this) + _header_size; };
|
||||||
|
@ -201,7 +204,8 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||||
virtual void print_value_on(outputStream* st) const PRODUCT_RETURN;
|
virtual void print_value_on(outputStream* st) const PRODUCT_RETURN;
|
||||||
|
|
||||||
// Print the comment associated with offset on stream, if there is one
|
// Print the comment associated with offset on stream, if there is one
|
||||||
void print_block_comment(outputStream* stream, intptr_t offset) {
|
virtual void print_block_comment(outputStream* stream, address block_begin) {
|
||||||
|
intptr_t offset = (intptr_t)(block_begin - instructions_begin());
|
||||||
_comments.print_block_comment(stream, offset);
|
_comments.print_block_comment(stream, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||||
ciMethod* method,
|
ciMethod* method,
|
||||||
int bci,
|
int bci,
|
||||||
bool reexecute,
|
bool reexecute,
|
||||||
|
bool is_method_handle_invoke,
|
||||||
DebugToken* locals,
|
DebugToken* locals,
|
||||||
DebugToken* expressions,
|
DebugToken* expressions,
|
||||||
DebugToken* monitors) {
|
DebugToken* monitors) {
|
||||||
|
@ -292,8 +293,9 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||||
int stream_offset = stream()->position();
|
int stream_offset = stream()->position();
|
||||||
last_pd->set_scope_decode_offset(stream_offset);
|
last_pd->set_scope_decode_offset(stream_offset);
|
||||||
|
|
||||||
// Record reexecute bit into pcDesc
|
// Record flags into pcDesc.
|
||||||
last_pd->set_should_reexecute(reexecute);
|
last_pd->set_should_reexecute(reexecute);
|
||||||
|
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
|
||||||
|
|
||||||
// serialize sender stream offest
|
// serialize sender stream offest
|
||||||
stream()->write_int(sender_stream_offset);
|
stream()->write_int(sender_stream_offset);
|
||||||
|
|
|
@ -88,6 +88,7 @@ class DebugInformationRecorder: public ResourceObj {
|
||||||
ciMethod* method,
|
ciMethod* method,
|
||||||
int bci,
|
int bci,
|
||||||
bool reexecute,
|
bool reexecute,
|
||||||
|
bool is_method_handle_invoke = false,
|
||||||
DebugToken* locals = NULL,
|
DebugToken* locals = NULL,
|
||||||
DebugToken* expressions = NULL,
|
DebugToken* expressions = NULL,
|
||||||
DebugToken* monitors = NULL);
|
DebugToken* monitors = NULL);
|
||||||
|
|
|
@ -56,13 +56,13 @@ HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool nmethod::is_compiled_by_c1() const {
|
bool nmethod::is_compiled_by_c1() const {
|
||||||
|
if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing
|
||||||
if (is_native_method()) return false;
|
if (is_native_method()) return false;
|
||||||
assert(compiler() != NULL, "must be");
|
|
||||||
return compiler()->is_c1();
|
return compiler()->is_c1();
|
||||||
}
|
}
|
||||||
bool nmethod::is_compiled_by_c2() const {
|
bool nmethod::is_compiled_by_c2() const {
|
||||||
|
if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing
|
||||||
if (is_native_method()) return false;
|
if (is_native_method()) return false;
|
||||||
assert(compiler() != NULL, "must be");
|
|
||||||
return compiler()->is_c2();
|
return compiler()->is_c2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1170,7 +1170,7 @@ void nmethod::log_state_change() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common functionality for both make_not_entrant and make_zombie
|
// Common functionality for both make_not_entrant and make_zombie
|
||||||
bool nmethod::make_not_entrant_or_zombie(int state) {
|
bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
||||||
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
|
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
|
||||||
|
|
||||||
// If the method is already zombie there is nothing to do
|
// If the method is already zombie there is nothing to do
|
||||||
|
@ -1724,9 +1724,9 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map
|
||||||
if (!method()->is_native()) {
|
if (!method()->is_native()) {
|
||||||
SimpleScopeDesc ssd(this, fr.pc());
|
SimpleScopeDesc ssd(this, fr.pc());
|
||||||
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
|
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
|
||||||
bool is_static = call->is_invokestatic();
|
bool has_receiver = call->has_receiver();
|
||||||
symbolOop signature = call->signature();
|
symbolOop signature = call->signature();
|
||||||
fr.oops_compiled_arguments_do(signature, is_static, reg_map, f);
|
fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,6 +1763,14 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
|
||||||
"must end with a sentinel");
|
"must end with a sentinel");
|
||||||
#endif //ASSERT
|
#endif //ASSERT
|
||||||
|
|
||||||
|
// Search for MethodHandle invokes and tag the nmethod.
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (pcs[i].is_method_handle_invoke()) {
|
||||||
|
set_has_method_handle_invokes(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int size = count * sizeof(PcDesc);
|
int size = count * sizeof(PcDesc);
|
||||||
assert(scopes_pcs_size() >= size, "oob");
|
assert(scopes_pcs_size() >= size, "oob");
|
||||||
memcpy(scopes_pcs_begin(), pcs, size);
|
memcpy(scopes_pcs_begin(), pcs, size);
|
||||||
|
@ -2029,6 +2037,18 @@ bool nmethod::is_deopt_pc(address pc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// MethodHandle
|
||||||
|
|
||||||
|
bool nmethod::is_method_handle_return(address return_pc) {
|
||||||
|
if (!has_method_handle_invokes()) return false;
|
||||||
|
PcDesc* pd = pc_desc_at(return_pc);
|
||||||
|
if (pd == NULL)
|
||||||
|
return false;
|
||||||
|
return pd->is_method_handle_invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Verification
|
// Verification
|
||||||
|
|
||||||
|
@ -2379,6 +2399,107 @@ ScopeDesc* nmethod::scope_desc_in(address begin, address end) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) {
|
||||||
|
if (block_begin == entry_point()) stream->print_cr("[Entry Point]");
|
||||||
|
if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]");
|
||||||
|
if (block_begin == exception_begin()) stream->print_cr("[Exception Handler]");
|
||||||
|
if (block_begin == stub_begin()) stream->print_cr("[Stub Code]");
|
||||||
|
if (block_begin == consts_begin()) stream->print_cr("[Constants]");
|
||||||
|
if (block_begin == entry_point()) {
|
||||||
|
methodHandle m = method();
|
||||||
|
if (m.not_null()) {
|
||||||
|
stream->print(" # ");
|
||||||
|
m->print_value_on(stream);
|
||||||
|
stream->cr();
|
||||||
|
}
|
||||||
|
if (m.not_null() && !is_osr_method()) {
|
||||||
|
ResourceMark rm;
|
||||||
|
int sizeargs = m->size_of_parameters();
|
||||||
|
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs);
|
||||||
|
VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs);
|
||||||
|
{
|
||||||
|
int sig_index = 0;
|
||||||
|
if (!m->is_static())
|
||||||
|
sig_bt[sig_index++] = T_OBJECT; // 'this'
|
||||||
|
for (SignatureStream ss(m->signature()); !ss.at_return_type(); ss.next()) {
|
||||||
|
BasicType t = ss.type();
|
||||||
|
sig_bt[sig_index++] = t;
|
||||||
|
if (type2size[t] == 2) {
|
||||||
|
sig_bt[sig_index++] = T_VOID;
|
||||||
|
} else {
|
||||||
|
assert(type2size[t] == 1, "size is 1 or 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(sig_index == sizeargs, "");
|
||||||
|
}
|
||||||
|
const char* spname = "sp"; // make arch-specific?
|
||||||
|
intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs, false);
|
||||||
|
int stack_slot_offset = this->frame_size() * wordSize;
|
||||||
|
int tab1 = 14, tab2 = 24;
|
||||||
|
int sig_index = 0;
|
||||||
|
int arg_index = (m->is_static() ? 0 : -1);
|
||||||
|
bool did_old_sp = false;
|
||||||
|
for (SignatureStream ss(m->signature()); !ss.at_return_type(); ) {
|
||||||
|
bool at_this = (arg_index == -1);
|
||||||
|
bool at_old_sp = false;
|
||||||
|
BasicType t = (at_this ? T_OBJECT : ss.type());
|
||||||
|
assert(t == sig_bt[sig_index], "sigs in sync");
|
||||||
|
if (at_this)
|
||||||
|
stream->print(" # this: ");
|
||||||
|
else
|
||||||
|
stream->print(" # parm%d: ", arg_index);
|
||||||
|
stream->move_to(tab1);
|
||||||
|
VMReg fst = regs[sig_index].first();
|
||||||
|
VMReg snd = regs[sig_index].second();
|
||||||
|
if (fst->is_reg()) {
|
||||||
|
stream->print("%s", fst->name());
|
||||||
|
if (snd->is_valid()) {
|
||||||
|
stream->print(":%s", snd->name());
|
||||||
|
}
|
||||||
|
} else if (fst->is_stack()) {
|
||||||
|
int offset = fst->reg2stack() * VMRegImpl::stack_slot_size + stack_slot_offset;
|
||||||
|
if (offset == stack_slot_offset) at_old_sp = true;
|
||||||
|
stream->print("[%s+0x%x]", spname, offset);
|
||||||
|
} else {
|
||||||
|
stream->print("reg%d:%d??", (int)(intptr_t)fst, (int)(intptr_t)snd);
|
||||||
|
}
|
||||||
|
stream->print(" ");
|
||||||
|
stream->move_to(tab2);
|
||||||
|
stream->print("= ");
|
||||||
|
if (at_this) {
|
||||||
|
m->method_holder()->print_value_on(stream);
|
||||||
|
} else {
|
||||||
|
bool did_name = false;
|
||||||
|
if (!at_this && ss.is_object()) {
|
||||||
|
symbolOop name = ss.as_symbol_or_null();
|
||||||
|
if (name != NULL) {
|
||||||
|
name->print_value_on(stream);
|
||||||
|
did_name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!did_name)
|
||||||
|
stream->print("%s", type2name(t));
|
||||||
|
}
|
||||||
|
if (at_old_sp) {
|
||||||
|
stream->print(" (%s of caller)", spname);
|
||||||
|
did_old_sp = true;
|
||||||
|
}
|
||||||
|
stream->cr();
|
||||||
|
sig_index += type2size[t];
|
||||||
|
arg_index += 1;
|
||||||
|
if (!at_this) ss.next();
|
||||||
|
}
|
||||||
|
if (!did_old_sp) {
|
||||||
|
stream->print(" # ");
|
||||||
|
stream->move_to(tab1);
|
||||||
|
stream->print("[%s+0x%x]", spname, stack_slot_offset);
|
||||||
|
stream->print(" (%s of caller)", spname);
|
||||||
|
stream->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, u_char* end) {
|
void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, u_char* end) {
|
||||||
// First, find an oopmap in (begin, end].
|
// First, find an oopmap in (begin, end].
|
||||||
// We use the odd half-closed interval so that oop maps and scope descs
|
// We use the odd half-closed interval so that oop maps and scope descs
|
||||||
|
|
|
@ -93,6 +93,7 @@ struct nmFlags {
|
||||||
unsigned int markedForReclamation:1; // Used by NMethodSweeper
|
unsigned int markedForReclamation:1; // Used by NMethodSweeper
|
||||||
|
|
||||||
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
|
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
|
||||||
|
unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
@ -254,7 +255,7 @@ class nmethod : public CodeBlob {
|
||||||
const char* reloc_string_for(u_char* begin, u_char* end);
|
const char* reloc_string_for(u_char* begin, u_char* end);
|
||||||
// Returns true if this thread changed the state of the nmethod or
|
// Returns true if this thread changed the state of the nmethod or
|
||||||
// false if another thread performed the transition.
|
// false if another thread performed the transition.
|
||||||
bool make_not_entrant_or_zombie(int state);
|
bool make_not_entrant_or_zombie(unsigned int state);
|
||||||
void inc_decompile_count();
|
void inc_decompile_count();
|
||||||
|
|
||||||
// used to check that writes to nmFlags are done consistently.
|
// used to check that writes to nmFlags are done consistently.
|
||||||
|
@ -409,6 +410,9 @@ class nmethod : public CodeBlob {
|
||||||
bool has_unsafe_access() const { return flags.has_unsafe_access; }
|
bool has_unsafe_access() const { return flags.has_unsafe_access; }
|
||||||
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
|
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
|
||||||
|
|
||||||
|
bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
|
||||||
|
void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
|
||||||
|
|
||||||
int level() const { return flags.level; }
|
int level() const { return flags.level; }
|
||||||
void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; }
|
void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; }
|
||||||
|
|
||||||
|
@ -541,6 +545,9 @@ class nmethod : public CodeBlob {
|
||||||
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
||||||
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
||||||
|
|
||||||
|
// MethodHandle
|
||||||
|
bool is_method_handle_return(address return_pc);
|
||||||
|
|
||||||
// jvmti support:
|
// jvmti support:
|
||||||
void post_compiled_method_load_event();
|
void post_compiled_method_load_event();
|
||||||
|
|
||||||
|
@ -569,6 +576,13 @@ class nmethod : public CodeBlob {
|
||||||
void log_new_nmethod() const;
|
void log_new_nmethod() const;
|
||||||
void log_state_change() const;
|
void log_state_change() const;
|
||||||
|
|
||||||
|
// Prints block-level comments, including nmethod specific block labels:
|
||||||
|
virtual void print_block_comment(outputStream* stream, address block_begin) {
|
||||||
|
print_nmethod_labels(stream, block_begin);
|
||||||
|
CodeBlob::print_block_comment(stream, block_begin);
|
||||||
|
}
|
||||||
|
void print_nmethod_labels(outputStream* stream, address block_begin);
|
||||||
|
|
||||||
// Prints a comment for one native instruction (reloc info, pc desc)
|
// Prints a comment for one native instruction (reloc info, pc desc)
|
||||||
void print_code_comment_on(outputStream* st, int column, address begin, address end);
|
void print_code_comment_on(outputStream* st, int column, address begin, address end);
|
||||||
static void print_statistics() PRODUCT_RETURN;
|
static void print_statistics() PRODUCT_RETURN;
|
||||||
|
|
|
@ -38,6 +38,7 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
|
||||||
int word;
|
int word;
|
||||||
struct {
|
struct {
|
||||||
unsigned int reexecute: 1;
|
unsigned int reexecute: 1;
|
||||||
|
unsigned int is_method_handle_invoke: 1;
|
||||||
} bits;
|
} bits;
|
||||||
bool operator ==(const PcDescFlags& other) { return word == other.word; }
|
bool operator ==(const PcDescFlags& other) { return word == other.word; }
|
||||||
} _flags;
|
} _flags;
|
||||||
|
@ -72,6 +73,9 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
|
||||||
_flags == pd->_flags;
|
_flags == pd->_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; }
|
||||||
|
void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; }
|
||||||
|
|
||||||
// Returns the real pc
|
// Returns the real pc
|
||||||
address real_pc(const nmethod* code) const;
|
address real_pc(const nmethod* code) const;
|
||||||
|
|
||||||
|
|
|
@ -1820,8 +1820,10 @@ void CompileBroker::print_times() {
|
||||||
CompileBroker::_t_standard_compilation.seconds(),
|
CompileBroker::_t_standard_compilation.seconds(),
|
||||||
CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
|
CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
|
||||||
tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
|
tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
|
||||||
|
|
||||||
|
if (compiler(CompLevel_fast_compile)) {
|
||||||
compiler(CompLevel_fast_compile)->print_timers();
|
compiler(CompLevel_fast_compile)->print_timers();
|
||||||
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) {
|
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier))
|
||||||
compiler(CompLevel_highest_tier)->print_timers();
|
compiler(CompLevel_highest_tier)->print_timers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,18 +392,18 @@ static const char* patterns[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) {
|
static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) {
|
||||||
if (strcmp(name, "*") == 0) return MethodMatcher::Any;
|
|
||||||
|
|
||||||
int match = MethodMatcher::Exact;
|
int match = MethodMatcher::Exact;
|
||||||
if (name[0] == '*') {
|
while (name[0] == '*') {
|
||||||
match |= MethodMatcher::Suffix;
|
match |= MethodMatcher::Suffix;
|
||||||
strcpy(name, name + 1);
|
strcpy(name, name + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "*") == 0) return MethodMatcher::Any;
|
||||||
|
|
||||||
size_t len = strlen(name);
|
size_t len = strlen(name);
|
||||||
if (len > 0 && name[len - 1] == '*') {
|
while (len > 0 && name[len - 1] == '*') {
|
||||||
match |= MethodMatcher::Prefix;
|
match |= MethodMatcher::Prefix;
|
||||||
name[len - 1] = '\0';
|
name[--len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(name, "*") != NULL) {
|
if (strstr(name, "*") != NULL) {
|
||||||
|
@ -610,6 +610,14 @@ void compilerOracle_init() {
|
||||||
CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line);
|
CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line);
|
||||||
CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
|
CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
|
||||||
CompilerOracle::parse_from_file();
|
CompilerOracle::parse_from_file();
|
||||||
|
if (lists[PrintCommand] != NULL) {
|
||||||
|
if (PrintAssembly) {
|
||||||
|
warning("CompileCommand and/or .hotspot_compiler file contains 'print' commands, but PrintAssembly is also enabled");
|
||||||
|
} else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
|
||||||
|
warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output");
|
||||||
|
DebugNonSafepoints = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -151,8 +151,10 @@ class decode_env {
|
||||||
outputStream* st = output();
|
outputStream* st = output();
|
||||||
if (_print_bytes && pc > pc0)
|
if (_print_bytes && pc > pc0)
|
||||||
print_insn_bytes(pc0, pc);
|
print_insn_bytes(pc0, pc);
|
||||||
if (_nm != NULL)
|
if (_nm != NULL) {
|
||||||
_nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
|
_nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
|
||||||
|
// this calls reloc_string_for which calls oop::print_value_on
|
||||||
|
}
|
||||||
|
|
||||||
// Output pc bucket ticks if we have any
|
// Output pc bucket ticks if we have any
|
||||||
if (total_ticks() != 0) {
|
if (total_ticks() != 0) {
|
||||||
|
@ -273,8 +275,15 @@ void decode_env::print_address(address adr) {
|
||||||
oop obj;
|
oop obj;
|
||||||
if (_nm != NULL
|
if (_nm != NULL
|
||||||
&& (obj = _nm->embeddedOop_at(cur_insn())) != NULL
|
&& (obj = _nm->embeddedOop_at(cur_insn())) != NULL
|
||||||
&& (address) obj == adr) {
|
&& (address) obj == adr
|
||||||
|
&& Universe::heap()->is_in(obj)
|
||||||
|
&& Universe::heap()->is_in(obj->klass())) {
|
||||||
|
julong c = st->count();
|
||||||
obj->print_value_on(st);
|
obj->print_value_on(st);
|
||||||
|
if (st->count() == c) {
|
||||||
|
// No output. (Can happen in product builds.)
|
||||||
|
st->print("(a %s)", Klass::cast(obj->klass())->external_name());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,17 +295,9 @@ void decode_env::print_address(address adr) {
|
||||||
void decode_env::print_insn_labels() {
|
void decode_env::print_insn_labels() {
|
||||||
address p = cur_insn();
|
address p = cur_insn();
|
||||||
outputStream* st = output();
|
outputStream* st = output();
|
||||||
nmethod* nm = _nm;
|
|
||||||
if (nm != NULL) {
|
|
||||||
if (p == nm->entry_point()) st->print_cr("[Entry Point]");
|
|
||||||
if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]");
|
|
||||||
if (p == nm->exception_begin()) st->print_cr("[Exception Handler]");
|
|
||||||
if (p == nm->stub_begin()) st->print_cr("[Stub Code]");
|
|
||||||
if (p == nm->consts_begin()) st->print_cr("[Constants]");
|
|
||||||
}
|
|
||||||
CodeBlob* cb = _code;
|
CodeBlob* cb = _code;
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
cb->print_block_comment(st, (intptr_t)(p - cb->instructions_begin()));
|
cb->print_block_comment(st, p);
|
||||||
}
|
}
|
||||||
if (_print_pc) {
|
if (_print_pc) {
|
||||||
st->print(" " INTPTR_FORMAT ": ", (intptr_t) p);
|
st->print(" " INTPTR_FORMAT ": ", (intptr_t) p);
|
||||||
|
|
|
@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute_gen_kill_single(ciBytecodeStream *instr
|
||||||
case Bytecodes::_invokespecial:
|
case Bytecodes::_invokespecial:
|
||||||
case Bytecodes::_invokestatic:
|
case Bytecodes::_invokestatic:
|
||||||
case Bytecodes::_invokeinterface:
|
case Bytecodes::_invokeinterface:
|
||||||
|
case Bytecodes::_invokedynamic:
|
||||||
case Bytecodes::_newarray:
|
case Bytecodes::_newarray:
|
||||||
case Bytecodes::_anewarray:
|
case Bytecodes::_anewarray:
|
||||||
case Bytecodes::_checkcast:
|
case Bytecodes::_checkcast:
|
||||||
|
|
|
@ -62,12 +62,13 @@ TreeList* TreeList::as_TreeList(TreeChunk* tc) {
|
||||||
tl->link_head(tc);
|
tl->link_head(tc);
|
||||||
tl->link_tail(tc);
|
tl->link_tail(tc);
|
||||||
tl->set_count(1);
|
tl->set_count(1);
|
||||||
tl->init_statistics();
|
tl->init_statistics(true /* split_birth */);
|
||||||
tl->setParent(NULL);
|
tl->setParent(NULL);
|
||||||
tl->setLeft(NULL);
|
tl->setLeft(NULL);
|
||||||
tl->setRight(NULL);
|
tl->setRight(NULL);
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) {
|
TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) {
|
||||||
TreeChunk* tc = (TreeChunk*) addr;
|
TreeChunk* tc = (TreeChunk*) addr;
|
||||||
assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
|
assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
|
||||||
|
@ -267,6 +268,31 @@ TreeChunk* TreeList::first_available() {
|
||||||
return retTC;
|
return retTC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the block with the largest heap address amongst
|
||||||
|
// those in the list for this size; potentially slow and expensive,
|
||||||
|
// use with caution!
|
||||||
|
TreeChunk* TreeList::largest_address() {
|
||||||
|
guarantee(head() != NULL, "The head of the list cannot be NULL");
|
||||||
|
FreeChunk* fc = head()->next();
|
||||||
|
TreeChunk* retTC;
|
||||||
|
if (fc == NULL) {
|
||||||
|
retTC = head_as_TreeChunk();
|
||||||
|
} else {
|
||||||
|
// walk down the list and return the one with the highest
|
||||||
|
// heap address among chunks of this size.
|
||||||
|
FreeChunk* last = fc;
|
||||||
|
while (fc->next() != NULL) {
|
||||||
|
if ((HeapWord*)last < (HeapWord*)fc) {
|
||||||
|
last = fc;
|
||||||
|
}
|
||||||
|
fc = fc->next();
|
||||||
|
}
|
||||||
|
retTC = TreeChunk::as_TreeChunk(last);
|
||||||
|
}
|
||||||
|
assert(retTC->list() == this, "Wrong type of chunk.");
|
||||||
|
return retTC;
|
||||||
|
}
|
||||||
|
|
||||||
BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay):
|
BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay):
|
||||||
_splay(splay)
|
_splay(splay)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +405,7 @@ BinaryTreeDictionary::getChunkFromTree(size_t size, Dither dither, bool splay)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// The evm code reset the hint of the candidate as
|
// The evm code reset the hint of the candidate as
|
||||||
// at an interrim point. Why? Seems like this leaves
|
// at an interim point. Why? Seems like this leaves
|
||||||
// the hint pointing to a list that didn't work.
|
// the hint pointing to a list that didn't work.
|
||||||
// curTL->set_hint(hintTL->size());
|
// curTL->set_hint(hintTL->size());
|
||||||
}
|
}
|
||||||
|
@ -436,7 +462,7 @@ FreeChunk* BinaryTreeDictionary::findLargestDict() const {
|
||||||
TreeList *curTL = root();
|
TreeList *curTL = root();
|
||||||
if (curTL != NULL) {
|
if (curTL != NULL) {
|
||||||
while(curTL->right() != NULL) curTL = curTL->right();
|
while(curTL->right() != NULL) curTL = curTL->right();
|
||||||
return curTL->first_available();
|
return curTL->largest_address();
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -664,7 +690,7 @@ void BinaryTreeDictionary::insertChunkInTree(FreeChunk* fc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TreeChunk* tc = TreeChunk::as_TreeChunk(fc);
|
TreeChunk* tc = TreeChunk::as_TreeChunk(fc);
|
||||||
// This chunk is being returned to the binary try. It's embedded
|
// This chunk is being returned to the binary tree. Its embedded
|
||||||
// TreeList should be unused at this point.
|
// TreeList should be unused at this point.
|
||||||
tc->initialize();
|
tc->initialize();
|
||||||
if (curTL != NULL) { // exact match
|
if (curTL != NULL) { // exact match
|
||||||
|
@ -807,6 +833,8 @@ void BinaryTreeDictionary::dictCensusUpdate(size_t size, bool split, bool birth)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) {
|
bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) {
|
||||||
|
if (FLSAlwaysCoalesceLarge) return true;
|
||||||
|
|
||||||
TreeList* list_of_size = findList(size);
|
TreeList* list_of_size = findList(size);
|
||||||
// None of requested size implies overpopulated.
|
// None of requested size implies overpopulated.
|
||||||
return list_of_size == NULL || list_of_size->coalDesired() <= 0 ||
|
return list_of_size == NULL || list_of_size->coalDesired() <= 0 ||
|
||||||
|
@ -854,17 +882,20 @@ class BeginSweepClosure : public AscendTreeCensusClosure {
|
||||||
double _percentage;
|
double _percentage;
|
||||||
float _inter_sweep_current;
|
float _inter_sweep_current;
|
||||||
float _inter_sweep_estimate;
|
float _inter_sweep_estimate;
|
||||||
|
float _intra_sweep_estimate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BeginSweepClosure(double p, float inter_sweep_current,
|
BeginSweepClosure(double p, float inter_sweep_current,
|
||||||
float inter_sweep_estimate) :
|
float inter_sweep_estimate,
|
||||||
|
float intra_sweep_estimate) :
|
||||||
_percentage(p),
|
_percentage(p),
|
||||||
_inter_sweep_current(inter_sweep_current),
|
_inter_sweep_current(inter_sweep_current),
|
||||||
_inter_sweep_estimate(inter_sweep_estimate) { }
|
_inter_sweep_estimate(inter_sweep_estimate),
|
||||||
|
_intra_sweep_estimate(intra_sweep_estimate) { }
|
||||||
|
|
||||||
void do_list(FreeList* fl) {
|
void do_list(FreeList* fl) {
|
||||||
double coalSurplusPercent = _percentage;
|
double coalSurplusPercent = _percentage;
|
||||||
fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate);
|
fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
|
||||||
fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent));
|
fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent));
|
||||||
fl->set_beforeSweep(fl->count());
|
fl->set_beforeSweep(fl->count());
|
||||||
fl->set_bfrSurp(fl->surplus());
|
fl->set_bfrSurp(fl->surplus());
|
||||||
|
@ -939,9 +970,10 @@ FreeChunk* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent,
|
void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent,
|
||||||
float inter_sweep_current, float inter_sweep_estimate) {
|
float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
|
||||||
BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
|
BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
|
||||||
inter_sweep_estimate);
|
inter_sweep_estimate,
|
||||||
|
intra_sweep_estimate);
|
||||||
bsc.do_tree(root());
|
bsc.do_tree(root());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,13 +1109,13 @@ void BinaryTreeDictionary::reportStatistics() const {
|
||||||
// Print census information - counts, births, deaths, etc.
|
// Print census information - counts, births, deaths, etc.
|
||||||
// for each list in the tree. Also print some summary
|
// for each list in the tree. Also print some summary
|
||||||
// information.
|
// information.
|
||||||
class printTreeCensusClosure : public AscendTreeCensusClosure {
|
class PrintTreeCensusClosure : public AscendTreeCensusClosure {
|
||||||
int _print_line;
|
int _print_line;
|
||||||
size_t _totalFree;
|
size_t _totalFree;
|
||||||
FreeList _total;
|
FreeList _total;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
printTreeCensusClosure() {
|
PrintTreeCensusClosure() {
|
||||||
_print_line = 0;
|
_print_line = 0;
|
||||||
_totalFree = 0;
|
_totalFree = 0;
|
||||||
}
|
}
|
||||||
|
@ -1113,7 +1145,7 @@ void BinaryTreeDictionary::printDictCensus(void) const {
|
||||||
|
|
||||||
gclog_or_tty->print("\nBinaryTree\n");
|
gclog_or_tty->print("\nBinaryTree\n");
|
||||||
FreeList::print_labels_on(gclog_or_tty, "size");
|
FreeList::print_labels_on(gclog_or_tty, "size");
|
||||||
printTreeCensusClosure ptc;
|
PrintTreeCensusClosure ptc;
|
||||||
ptc.do_tree(root());
|
ptc.do_tree(root());
|
||||||
|
|
||||||
FreeList* total = ptc.total();
|
FreeList* total = ptc.total();
|
||||||
|
@ -1130,6 +1162,38 @@ void BinaryTreeDictionary::printDictCensus(void) const {
|
||||||
/(total->desired() != 0 ? (double)total->desired() : 1.0));
|
/(total->desired() != 0 ? (double)total->desired() : 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PrintFreeListsClosure : public AscendTreeCensusClosure {
|
||||||
|
outputStream* _st;
|
||||||
|
int _print_line;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrintFreeListsClosure(outputStream* st) {
|
||||||
|
_st = st;
|
||||||
|
_print_line = 0;
|
||||||
|
}
|
||||||
|
void do_list(FreeList* fl) {
|
||||||
|
if (++_print_line >= 40) {
|
||||||
|
FreeList::print_labels_on(_st, "size");
|
||||||
|
_print_line = 0;
|
||||||
|
}
|
||||||
|
fl->print_on(gclog_or_tty);
|
||||||
|
size_t sz = fl->size();
|
||||||
|
for (FreeChunk* fc = fl->head(); fc != NULL;
|
||||||
|
fc = fc->next()) {
|
||||||
|
_st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
|
||||||
|
fc, (HeapWord*)fc + sz,
|
||||||
|
fc->cantCoalesce() ? "\t CC" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void BinaryTreeDictionary::print_free_lists(outputStream* st) const {
|
||||||
|
|
||||||
|
FreeList::print_labels_on(st, "size");
|
||||||
|
PrintFreeListsClosure pflc(st);
|
||||||
|
pflc.do_tree(root());
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the following tree invariants:
|
// Verify the following tree invariants:
|
||||||
// . _root has no parent
|
// . _root has no parent
|
||||||
// . parent and child point to each other
|
// . parent and child point to each other
|
||||||
|
|
|
@ -42,9 +42,6 @@ class TreeList: public FreeList {
|
||||||
friend class AscendTreeCensusClosure;
|
friend class AscendTreeCensusClosure;
|
||||||
friend class DescendTreeCensusClosure;
|
friend class DescendTreeCensusClosure;
|
||||||
friend class DescendTreeSearchClosure;
|
friend class DescendTreeSearchClosure;
|
||||||
TreeList* _parent;
|
|
||||||
TreeList* _left;
|
|
||||||
TreeList* _right;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TreeList* parent() const { return _parent; }
|
TreeList* parent() const { return _parent; }
|
||||||
|
@ -82,6 +79,11 @@ class TreeList: public FreeList {
|
||||||
// to a TreeChunk.
|
// to a TreeChunk.
|
||||||
TreeChunk* first_available();
|
TreeChunk* first_available();
|
||||||
|
|
||||||
|
// Returns the block with the largest heap address amongst
|
||||||
|
// those in the list for this size; potentially slow and expensive,
|
||||||
|
// use with caution!
|
||||||
|
TreeChunk* largest_address();
|
||||||
|
|
||||||
// removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList.
|
// removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList.
|
||||||
// If "tc" is the first chunk in the list, it is also the
|
// If "tc" is the first chunk in the list, it is also the
|
||||||
// TreeList that is the node in the tree. removeChunkReplaceIfNeeded()
|
// TreeList that is the node in the tree. removeChunkReplaceIfNeeded()
|
||||||
|
@ -254,8 +256,9 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
||||||
// Methods called at the beginning of a sweep to prepare the
|
// Methods called at the beginning of a sweep to prepare the
|
||||||
// statistics for the sweep.
|
// statistics for the sweep.
|
||||||
void beginSweepDictCensus(double coalSurplusPercent,
|
void beginSweepDictCensus(double coalSurplusPercent,
|
||||||
float sweep_current,
|
float inter_sweep_current,
|
||||||
float sweep_estimate);
|
float inter_sweep_estimate,
|
||||||
|
float intra_sweep_estimate);
|
||||||
// Methods called after the end of a sweep to modify the
|
// Methods called after the end of a sweep to modify the
|
||||||
// statistics for the sweep.
|
// statistics for the sweep.
|
||||||
void endSweepDictCensus(double splitSurplusPercent);
|
void endSweepDictCensus(double splitSurplusPercent);
|
||||||
|
@ -269,6 +272,7 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
||||||
// Print the statistcis for all the lists in the tree. Also may
|
// Print the statistcis for all the lists in the tree. Also may
|
||||||
// print out summaries.
|
// print out summaries.
|
||||||
void printDictCensus(void) const;
|
void printDictCensus(void) const;
|
||||||
|
void print_free_lists(outputStream* st) const;
|
||||||
|
|
||||||
// For debugging. Returns the sum of the _returnedBytes for
|
// For debugging. Returns the sum of the _returnedBytes for
|
||||||
// all lists in the tree.
|
// all lists in the tree.
|
||||||
|
|
|
@ -32,7 +32,9 @@
|
||||||
// threads. The second argument is in support of an extra locking
|
// threads. The second argument is in support of an extra locking
|
||||||
// check for CFL spaces' free list locks.
|
// check for CFL spaces' free list locks.
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
void CMSLockVerifier::assert_locked(const Mutex* lock,
|
||||||
|
const Mutex* p_lock1,
|
||||||
|
const Mutex* p_lock2) {
|
||||||
if (!Universe::is_fully_initialized()) {
|
if (!Universe::is_fully_initialized()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +42,7 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
||||||
Thread* myThread = Thread::current();
|
Thread* myThread = Thread::current();
|
||||||
|
|
||||||
if (lock == NULL) { // a "lock-free" structure, e.g. MUT, protected by CMS token
|
if (lock == NULL) { // a "lock-free" structure, e.g. MUT, protected by CMS token
|
||||||
assert(p_lock == NULL, "Unexpected state");
|
assert(p_lock1 == NULL && p_lock2 == NULL, "Unexpected caller error");
|
||||||
if (myThread->is_ConcurrentGC_thread()) {
|
if (myThread->is_ConcurrentGC_thread()) {
|
||||||
// This test might have to change in the future, if there can be
|
// This test might have to change in the future, if there can be
|
||||||
// multiple peer CMS threads. But for now, if we're testing the CMS
|
// multiple peer CMS threads. But for now, if we're testing the CMS
|
||||||
|
@ -60,9 +62,6 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParallelGCThreads == 0) {
|
|
||||||
assert_lock_strong(lock);
|
|
||||||
} else {
|
|
||||||
if (myThread->is_VM_thread()
|
if (myThread->is_VM_thread()
|
||||||
|| myThread->is_ConcurrentGC_thread()
|
|| myThread->is_ConcurrentGC_thread()
|
||||||
|| myThread->is_Java_thread()) {
|
|| myThread->is_Java_thread()) {
|
||||||
|
@ -73,11 +72,11 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
||||||
// threads are holding "sub-locks" of freeListLock(). We check only
|
// threads are holding "sub-locks" of freeListLock(). We check only
|
||||||
// the parDictionaryAllocLock because the others are too numerous.
|
// the parDictionaryAllocLock because the others are too numerous.
|
||||||
// This spl case code is somewhat ugly and any improvements
|
// This spl case code is somewhat ugly and any improvements
|
||||||
// are welcome XXX FIX ME!!
|
// are welcome.
|
||||||
if (p_lock != NULL) {
|
assert(p_lock1 == NULL || !p_lock1->is_locked() || p_lock1->owned_by_self(),
|
||||||
assert(!p_lock->is_locked() || p_lock->owned_by_self(),
|
"Possible race between this and parallel GC threads");
|
||||||
|
assert(p_lock2 == NULL || !p_lock2->is_locked() || p_lock2->owned_by_self(),
|
||||||
"Possible race between this and parallel GC threads");
|
"Possible race between this and parallel GC threads");
|
||||||
}
|
|
||||||
} else if (myThread->is_GC_task_thread()) {
|
} else if (myThread->is_GC_task_thread()) {
|
||||||
// Make sure that the VM or CMS thread holds lock on our behalf
|
// Make sure that the VM or CMS thread holds lock on our behalf
|
||||||
// XXX If there were a concept of a gang_master for a (set of)
|
// XXX If there were a concept of a gang_master for a (set of)
|
||||||
|
@ -86,10 +85,16 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
||||||
assert(lock->owner() == VMThread::vm_thread() ||
|
assert(lock->owner() == VMThread::vm_thread() ||
|
||||||
lock->owner() == ConcurrentMarkSweepThread::cmst(),
|
lock->owner() == ConcurrentMarkSweepThread::cmst(),
|
||||||
"Should be locked by VM thread or CMS thread on my behalf");
|
"Should be locked by VM thread or CMS thread on my behalf");
|
||||||
|
if (p_lock1 != NULL) {
|
||||||
|
assert_lock_strong(p_lock1);
|
||||||
|
}
|
||||||
|
if (p_lock2 != NULL) {
|
||||||
|
assert_lock_strong(p_lock2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Make sure we didn't miss some obscure corner case
|
// Make sure we didn't miss some other thread type calling into here;
|
||||||
|
// perhaps as a result of future VM evolution.
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,8 +29,11 @@
|
||||||
// the parallel threads.
|
// the parallel threads.
|
||||||
class CMSLockVerifier: AllStatic {
|
class CMSLockVerifier: AllStatic {
|
||||||
public:
|
public:
|
||||||
static void assert_locked(const Mutex* lock, const Mutex* p_lock)
|
static void assert_locked(const Mutex* lock, const Mutex* p_lock1, const Mutex* p_lock2)
|
||||||
PRODUCT_RETURN;
|
PRODUCT_RETURN;
|
||||||
|
static void assert_locked(const Mutex* lock, const Mutex* p_lock) {
|
||||||
|
assert_locked(lock, p_lock, NULL);
|
||||||
|
}
|
||||||
static void assert_locked(const Mutex* lock) {
|
static void assert_locked(const Mutex* lock) {
|
||||||
assert_locked(lock, NULL);
|
assert_locked(lock, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,18 +62,15 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
|
||||||
// implementation, namely, the simple binary tree (splaying
|
// implementation, namely, the simple binary tree (splaying
|
||||||
// temporarily disabled).
|
// temporarily disabled).
|
||||||
switch (dictionaryChoice) {
|
switch (dictionaryChoice) {
|
||||||
case FreeBlockDictionary::dictionaryBinaryTree:
|
|
||||||
_dictionary = new BinaryTreeDictionary(mr);
|
|
||||||
break;
|
|
||||||
case FreeBlockDictionary::dictionarySplayTree:
|
case FreeBlockDictionary::dictionarySplayTree:
|
||||||
case FreeBlockDictionary::dictionarySkipList:
|
case FreeBlockDictionary::dictionarySkipList:
|
||||||
default:
|
default:
|
||||||
warning("dictionaryChoice: selected option not understood; using"
|
warning("dictionaryChoice: selected option not understood; using"
|
||||||
" default BinaryTreeDictionary implementation instead.");
|
" default BinaryTreeDictionary implementation instead.");
|
||||||
|
case FreeBlockDictionary::dictionaryBinaryTree:
|
||||||
_dictionary = new BinaryTreeDictionary(mr);
|
_dictionary = new BinaryTreeDictionary(mr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
splitBirth(mr.word_size());
|
|
||||||
assert(_dictionary != NULL, "CMS dictionary initialization");
|
assert(_dictionary != NULL, "CMS dictionary initialization");
|
||||||
// The indexed free lists are initially all empty and are lazily
|
// The indexed free lists are initially all empty and are lazily
|
||||||
// filled in on demand. Initialize the array elements to NULL.
|
// filled in on demand. Initialize the array elements to NULL.
|
||||||
|
@ -388,6 +385,105 @@ size_t CompactibleFreeListSpace::max_alloc_in_words() const {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
|
||||||
|
const {
|
||||||
|
reportIndexedFreeListStatistics();
|
||||||
|
gclog_or_tty->print_cr("Layout of Indexed Freelists");
|
||||||
|
gclog_or_tty->print_cr("---------------------------");
|
||||||
|
FreeList::print_labels_on(st, "size");
|
||||||
|
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||||
|
_indexedFreeList[i].print_on(gclog_or_tty);
|
||||||
|
for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
|
||||||
|
fc = fc->next()) {
|
||||||
|
gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
|
||||||
|
fc, (HeapWord*)fc + i,
|
||||||
|
fc->cantCoalesce() ? "\t CC" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st)
|
||||||
|
const {
|
||||||
|
_promoInfo.print_on(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
|
||||||
|
const {
|
||||||
|
_dictionary->reportStatistics();
|
||||||
|
st->print_cr("Layout of Freelists in Tree");
|
||||||
|
st->print_cr("---------------------------");
|
||||||
|
_dictionary->print_free_lists(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BlkPrintingClosure: public BlkClosure {
|
||||||
|
const CMSCollector* _collector;
|
||||||
|
const CompactibleFreeListSpace* _sp;
|
||||||
|
const CMSBitMap* _live_bit_map;
|
||||||
|
const bool _post_remark;
|
||||||
|
outputStream* _st;
|
||||||
|
public:
|
||||||
|
BlkPrintingClosure(const CMSCollector* collector,
|
||||||
|
const CompactibleFreeListSpace* sp,
|
||||||
|
const CMSBitMap* live_bit_map,
|
||||||
|
outputStream* st):
|
||||||
|
_collector(collector),
|
||||||
|
_sp(sp),
|
||||||
|
_live_bit_map(live_bit_map),
|
||||||
|
_post_remark(collector->abstract_state() > CMSCollector::FinalMarking),
|
||||||
|
_st(st) { }
|
||||||
|
size_t do_blk(HeapWord* addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t BlkPrintingClosure::do_blk(HeapWord* addr) {
|
||||||
|
size_t sz = _sp->block_size_no_stall(addr, _collector);
|
||||||
|
assert(sz != 0, "Should always be able to compute a size");
|
||||||
|
if (_sp->block_is_obj(addr)) {
|
||||||
|
const bool dead = _post_remark && !_live_bit_map->isMarked(addr);
|
||||||
|
_st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s",
|
||||||
|
addr,
|
||||||
|
dead ? "dead" : "live",
|
||||||
|
sz,
|
||||||
|
(!dead && CMSPrintObjectsInDump) ? ":" : ".");
|
||||||
|
if (CMSPrintObjectsInDump && !dead) {
|
||||||
|
oop(addr)->print_on(_st);
|
||||||
|
_st->print_cr("--------------------------------------");
|
||||||
|
}
|
||||||
|
} else { // free block
|
||||||
|
_st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s",
|
||||||
|
addr, sz, CMSPrintChunksInDump ? ":" : ".");
|
||||||
|
if (CMSPrintChunksInDump) {
|
||||||
|
((FreeChunk*)addr)->print_on(_st);
|
||||||
|
_st->print_cr("--------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c,
|
||||||
|
outputStream* st) {
|
||||||
|
st->print_cr("\n=========================");
|
||||||
|
st->print_cr("Block layout in CMS Heap:");
|
||||||
|
st->print_cr("=========================");
|
||||||
|
BlkPrintingClosure bpcl(c, this, c->markBitMap(), st);
|
||||||
|
blk_iterate(&bpcl);
|
||||||
|
|
||||||
|
st->print_cr("\n=======================================");
|
||||||
|
st->print_cr("Order & Layout of Promotion Info Blocks");
|
||||||
|
st->print_cr("=======================================");
|
||||||
|
print_promo_info_blocks(st);
|
||||||
|
|
||||||
|
st->print_cr("\n===========================");
|
||||||
|
st->print_cr("Order of Indexed Free Lists");
|
||||||
|
st->print_cr("=========================");
|
||||||
|
print_indexed_free_lists(st);
|
||||||
|
|
||||||
|
st->print_cr("\n=================================");
|
||||||
|
st->print_cr("Order of Free Lists in Dictionary");
|
||||||
|
st->print_cr("=================================");
|
||||||
|
print_dictionary_free_lists(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CompactibleFreeListSpace::reportFreeListStatistics() const {
|
void CompactibleFreeListSpace::reportFreeListStatistics() const {
|
||||||
assert_lock_strong(&_freelistLock);
|
assert_lock_strong(&_freelistLock);
|
||||||
assert(PrintFLSStatistics != 0, "Reporting error");
|
assert(PrintFLSStatistics != 0, "Reporting error");
|
||||||
|
@ -732,7 +828,7 @@ void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) {
|
||||||
|
|
||||||
void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
|
void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
|
||||||
UpwardsObjectClosure* cl) {
|
UpwardsObjectClosure* cl) {
|
||||||
assert_locked();
|
assert_locked(freelistLock());
|
||||||
NOT_PRODUCT(verify_objects_initialized());
|
NOT_PRODUCT(verify_objects_initialized());
|
||||||
Space::object_iterate_mem(mr, cl);
|
Space::object_iterate_mem(mr, cl);
|
||||||
}
|
}
|
||||||
|
@ -1212,12 +1308,15 @@ bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
|
||||||
void CompactibleFreeListSpace::assert_locked() const {
|
void CompactibleFreeListSpace::assert_locked() const {
|
||||||
CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock());
|
CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const {
|
||||||
|
CMSLockVerifier::assert_locked(lock);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) {
|
FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) {
|
||||||
// In the parallel case, the main thread holds the free list lock
|
// In the parallel case, the main thread holds the free list lock
|
||||||
// on behalf the parallel threads.
|
// on behalf the parallel threads.
|
||||||
assert_locked();
|
|
||||||
FreeChunk* fc;
|
FreeChunk* fc;
|
||||||
{
|
{
|
||||||
// If GC is parallel, this might be called by several threads.
|
// If GC is parallel, this might be called by several threads.
|
||||||
|
@ -1298,17 +1397,18 @@ CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk,
|
||||||
res = blk->_ptr;
|
res = blk->_ptr;
|
||||||
_bt.allocated(res, blk->_word_size);
|
_bt.allocated(res, blk->_word_size);
|
||||||
} else if (size + MinChunkSize <= blk->_refillSize) {
|
} else if (size + MinChunkSize <= blk->_refillSize) {
|
||||||
|
size_t sz = blk->_word_size;
|
||||||
// Update _unallocated_block if the size is such that chunk would be
|
// Update _unallocated_block if the size is such that chunk would be
|
||||||
// returned to the indexed free list. All other chunks in the indexed
|
// returned to the indexed free list. All other chunks in the indexed
|
||||||
// free lists are allocated from the dictionary so that _unallocated_block
|
// free lists are allocated from the dictionary so that _unallocated_block
|
||||||
// has already been adjusted for them. Do it here so that the cost
|
// has already been adjusted for them. Do it here so that the cost
|
||||||
// for all chunks added back to the indexed free lists.
|
// for all chunks added back to the indexed free lists.
|
||||||
if (blk->_word_size < SmallForDictionary) {
|
if (sz < SmallForDictionary) {
|
||||||
_bt.allocated(blk->_ptr, blk->_word_size);
|
_bt.allocated(blk->_ptr, sz);
|
||||||
}
|
}
|
||||||
// Return the chunk that isn't big enough, and then refill below.
|
// Return the chunk that isn't big enough, and then refill below.
|
||||||
addChunkToFreeLists(blk->_ptr, blk->_word_size);
|
addChunkToFreeLists(blk->_ptr, sz);
|
||||||
_bt.verify_single_block(blk->_ptr, (blk->_ptr + blk->_word_size));
|
splitBirth(sz);
|
||||||
// Don't keep statistics on adding back chunk from a LinAB.
|
// Don't keep statistics on adding back chunk from a LinAB.
|
||||||
} else {
|
} else {
|
||||||
// A refilled block would not satisfy the request.
|
// A refilled block would not satisfy the request.
|
||||||
|
@ -1376,11 +1476,13 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) {
|
||||||
res = getChunkFromIndexedFreeListHelper(size);
|
res = getChunkFromIndexedFreeListHelper(size);
|
||||||
}
|
}
|
||||||
_bt.verify_not_unallocated((HeapWord*) res, size);
|
_bt.verify_not_unallocated((HeapWord*) res, size);
|
||||||
|
assert(res == NULL || res->size() == size, "Incorrect block size");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeChunk*
|
FreeChunk*
|
||||||
CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
|
CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size,
|
||||||
|
bool replenish) {
|
||||||
assert_locked();
|
assert_locked();
|
||||||
FreeChunk* fc = NULL;
|
FreeChunk* fc = NULL;
|
||||||
if (size < SmallForDictionary) {
|
if (size < SmallForDictionary) {
|
||||||
|
@ -1398,34 +1500,42 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
|
||||||
// and replenishing indexed lists from the small linAB.
|
// and replenishing indexed lists from the small linAB.
|
||||||
//
|
//
|
||||||
FreeChunk* newFc = NULL;
|
FreeChunk* newFc = NULL;
|
||||||
size_t replenish_size = CMSIndexedFreeListReplenish * size;
|
const size_t replenish_size = CMSIndexedFreeListReplenish * size;
|
||||||
if (replenish_size < SmallForDictionary) {
|
if (replenish_size < SmallForDictionary) {
|
||||||
// Do not replenish from an underpopulated size.
|
// Do not replenish from an underpopulated size.
|
||||||
if (_indexedFreeList[replenish_size].surplus() > 0 &&
|
if (_indexedFreeList[replenish_size].surplus() > 0 &&
|
||||||
_indexedFreeList[replenish_size].head() != NULL) {
|
_indexedFreeList[replenish_size].head() != NULL) {
|
||||||
newFc =
|
newFc = _indexedFreeList[replenish_size].getChunkAtHead();
|
||||||
_indexedFreeList[replenish_size].getChunkAtHead();
|
} else if (bestFitFirst()) {
|
||||||
} else {
|
|
||||||
newFc = bestFitSmall(replenish_size);
|
newFc = bestFitSmall(replenish_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newFc != NULL) {
|
if (newFc == NULL && replenish_size > size) {
|
||||||
splitDeath(replenish_size);
|
|
||||||
} else if (replenish_size > size) {
|
|
||||||
assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
|
assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
|
||||||
newFc =
|
newFc = getChunkFromIndexedFreeListHelper(replenish_size, false);
|
||||||
getChunkFromIndexedFreeListHelper(replenish_size);
|
|
||||||
}
|
}
|
||||||
|
// Note: The stats update re split-death of block obtained above
|
||||||
|
// will be recorded below precisely when we know we are going to
|
||||||
|
// be actually splitting it into more than one pieces below.
|
||||||
if (newFc != NULL) {
|
if (newFc != NULL) {
|
||||||
assert(newFc->size() == replenish_size, "Got wrong size");
|
if (replenish || CMSReplenishIntermediate) {
|
||||||
|
// Replenish this list and return one block to caller.
|
||||||
size_t i;
|
size_t i;
|
||||||
FreeChunk *curFc, *nextFc;
|
FreeChunk *curFc, *nextFc;
|
||||||
// carve up and link blocks 0, ..., CMSIndexedFreeListReplenish - 2
|
size_t num_blk = newFc->size() / size;
|
||||||
|
assert(num_blk >= 1, "Smaller than requested?");
|
||||||
|
assert(newFc->size() % size == 0, "Should be integral multiple of request");
|
||||||
|
if (num_blk > 1) {
|
||||||
|
// we are sure we will be splitting the block just obtained
|
||||||
|
// into multiple pieces; record the split-death of the original
|
||||||
|
splitDeath(replenish_size);
|
||||||
|
}
|
||||||
|
// carve up and link blocks 0, ..., num_blk - 2
|
||||||
// The last chunk is not added to the lists but is returned as the
|
// The last chunk is not added to the lists but is returned as the
|
||||||
// free chunk.
|
// free chunk.
|
||||||
for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
|
for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
|
||||||
i = 0;
|
i = 0;
|
||||||
i < (CMSIndexedFreeListReplenish - 1);
|
i < (num_blk - 1);
|
||||||
curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
|
curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
|
||||||
i++) {
|
i++) {
|
||||||
curFc->setSize(size);
|
curFc->setSize(size);
|
||||||
|
@ -1440,12 +1550,16 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the arithmetic was OK above
|
// check that the arithmetic was OK above
|
||||||
assert((HeapWord*)nextFc == (HeapWord*)newFc + replenish_size,
|
assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size,
|
||||||
"inconsistency in carving newFc");
|
"inconsistency in carving newFc");
|
||||||
curFc->setSize(size);
|
curFc->setSize(size);
|
||||||
_bt.mark_block((HeapWord*)curFc, size);
|
_bt.mark_block((HeapWord*)curFc, size);
|
||||||
splitBirth(size);
|
splitBirth(size);
|
||||||
return curFc;
|
fc = curFc;
|
||||||
|
} else {
|
||||||
|
// Return entire block to caller
|
||||||
|
fc = newFc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1453,7 +1567,7 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
|
||||||
// replenish the indexed free list.
|
// replenish the indexed free list.
|
||||||
fc = getChunkFromDictionaryExact(size);
|
fc = getChunkFromDictionaryExact(size);
|
||||||
}
|
}
|
||||||
assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
|
// assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
|
||||||
return fc;
|
return fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1512,6 +1626,11 @@ CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) {
|
||||||
// adjust _unallocated_block downward, as necessary
|
// adjust _unallocated_block downward, as necessary
|
||||||
_bt.freed((HeapWord*)chunk, size);
|
_bt.freed((HeapWord*)chunk, size);
|
||||||
_dictionary->returnChunk(chunk);
|
_dictionary->returnChunk(chunk);
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
|
||||||
|
TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
|
||||||
|
}
|
||||||
|
#endif // PRODUCT
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1525,6 +1644,11 @@ CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) {
|
||||||
} else {
|
} else {
|
||||||
_indexedFreeList[size].returnChunkAtHead(fc);
|
_indexedFreeList[size].returnChunkAtHead(fc);
|
||||||
}
|
}
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
|
||||||
|
_indexedFreeList[size].verify_stats();
|
||||||
|
}
|
||||||
|
#endif // PRODUCT
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add chunk to end of last block -- if it's the largest
|
// Add chunk to end of last block -- if it's the largest
|
||||||
|
@ -1537,7 +1661,6 @@ CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats(
|
||||||
HeapWord* chunk, size_t size) {
|
HeapWord* chunk, size_t size) {
|
||||||
// check that the chunk does lie in this space!
|
// check that the chunk does lie in this space!
|
||||||
assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
|
assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
|
||||||
assert_locked();
|
|
||||||
// One of the parallel gc task threads may be here
|
// One of the parallel gc task threads may be here
|
||||||
// whilst others are allocating.
|
// whilst others are allocating.
|
||||||
Mutex* lock = NULL;
|
Mutex* lock = NULL;
|
||||||
|
@ -1991,24 +2114,26 @@ double CompactibleFreeListSpace::flsFrag() const {
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CoalSurplusPercent 1.05
|
|
||||||
#define SplitSurplusPercent 1.10
|
|
||||||
|
|
||||||
void CompactibleFreeListSpace::beginSweepFLCensus(
|
void CompactibleFreeListSpace::beginSweepFLCensus(
|
||||||
float inter_sweep_current,
|
float inter_sweep_current,
|
||||||
float inter_sweep_estimate) {
|
float inter_sweep_estimate,
|
||||||
|
float intra_sweep_estimate) {
|
||||||
assert_locked();
|
assert_locked();
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||||
FreeList* fl = &_indexedFreeList[i];
|
FreeList* fl = &_indexedFreeList[i];
|
||||||
fl->compute_desired(inter_sweep_current, inter_sweep_estimate);
|
if (PrintFLSStatistics > 1) {
|
||||||
fl->set_coalDesired((ssize_t)((double)fl->desired() * CoalSurplusPercent));
|
gclog_or_tty->print("size[%d] : ", i);
|
||||||
|
}
|
||||||
|
fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
|
||||||
|
fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
|
||||||
fl->set_beforeSweep(fl->count());
|
fl->set_beforeSweep(fl->count());
|
||||||
fl->set_bfrSurp(fl->surplus());
|
fl->set_bfrSurp(fl->surplus());
|
||||||
}
|
}
|
||||||
_dictionary->beginSweepDictCensus(CoalSurplusPercent,
|
_dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent,
|
||||||
inter_sweep_current,
|
inter_sweep_current,
|
||||||
inter_sweep_estimate);
|
inter_sweep_estimate,
|
||||||
|
intra_sweep_estimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompactibleFreeListSpace::setFLSurplus() {
|
void CompactibleFreeListSpace::setFLSurplus() {
|
||||||
|
@ -2017,7 +2142,7 @@ void CompactibleFreeListSpace::setFLSurplus() {
|
||||||
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||||
FreeList *fl = &_indexedFreeList[i];
|
FreeList *fl = &_indexedFreeList[i];
|
||||||
fl->set_surplus(fl->count() -
|
fl->set_surplus(fl->count() -
|
||||||
(ssize_t)((double)fl->desired() * SplitSurplusPercent));
|
(ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2048,6 +2173,11 @@ void CompactibleFreeListSpace::clearFLCensus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
|
void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
|
||||||
|
if (PrintFLSStatistics > 0) {
|
||||||
|
HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict();
|
||||||
|
gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
|
||||||
|
largestAddr);
|
||||||
|
}
|
||||||
setFLSurplus();
|
setFLSurplus();
|
||||||
setFLHints();
|
setFLHints();
|
||||||
if (PrintGC && PrintFLSCensus > 0) {
|
if (PrintGC && PrintFLSCensus > 0) {
|
||||||
|
@ -2055,7 +2185,7 @@ void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
|
||||||
}
|
}
|
||||||
clearFLCensus();
|
clearFLCensus();
|
||||||
assert_locked();
|
assert_locked();
|
||||||
_dictionary->endSweepDictCensus(SplitSurplusPercent);
|
_dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
|
bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
|
||||||
|
@ -2313,12 +2443,17 @@ void CompactibleFreeListSpace::verifyIndexedFreeLists() const {
|
||||||
|
|
||||||
void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
|
void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
|
||||||
FreeChunk* fc = _indexedFreeList[size].head();
|
FreeChunk* fc = _indexedFreeList[size].head();
|
||||||
|
FreeChunk* tail = _indexedFreeList[size].tail();
|
||||||
|
size_t num = _indexedFreeList[size].count();
|
||||||
|
size_t n = 0;
|
||||||
guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
|
guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
|
||||||
for (; fc != NULL; fc = fc->next()) {
|
for (; fc != NULL; fc = fc->next(), n++) {
|
||||||
guarantee(fc->size() == size, "Size inconsistency");
|
guarantee(fc->size() == size, "Size inconsistency");
|
||||||
guarantee(fc->isFree(), "!free?");
|
guarantee(fc->isFree(), "!free?");
|
||||||
guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
|
guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
|
||||||
|
guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail");
|
||||||
}
|
}
|
||||||
|
guarantee(n == num, "Incorrect count");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -2516,11 +2651,41 @@ void PromotionInfo::startTrackingPromotions() {
|
||||||
_tracking = true;
|
_tracking = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PromotionInfo::stopTrackingPromotions() {
|
#define CMSPrintPromoBlockInfo 1
|
||||||
|
|
||||||
|
void PromotionInfo::stopTrackingPromotions(uint worker_id) {
|
||||||
assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
|
assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
|
||||||
"spooling inconsistency?");
|
"spooling inconsistency?");
|
||||||
_firstIndex = _nextIndex = 1;
|
_firstIndex = _nextIndex = 1;
|
||||||
_tracking = false;
|
_tracking = false;
|
||||||
|
if (CMSPrintPromoBlockInfo > 1) {
|
||||||
|
print_statistics(worker_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PromotionInfo::print_statistics(uint worker_id) const {
|
||||||
|
assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
|
||||||
|
"Else will undercount");
|
||||||
|
assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call");
|
||||||
|
// Count the number of blocks and slots in the free pool
|
||||||
|
size_t slots = 0;
|
||||||
|
size_t blocks = 0;
|
||||||
|
for (SpoolBlock* cur_spool = _spareSpool;
|
||||||
|
cur_spool != NULL;
|
||||||
|
cur_spool = cur_spool->nextSpoolBlock) {
|
||||||
|
// the first entry is just a self-pointer; indices 1 through
|
||||||
|
// bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
|
||||||
|
guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr,
|
||||||
|
"first entry of displacedHdr should be self-referential");
|
||||||
|
slots += cur_spool->bufferSize - 1;
|
||||||
|
blocks++;
|
||||||
|
}
|
||||||
|
if (_spoolHead != NULL) {
|
||||||
|
slots += _spoolHead->bufferSize - 1;
|
||||||
|
blocks++;
|
||||||
|
}
|
||||||
|
gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
|
||||||
|
worker_id, blocks, slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
|
// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
|
||||||
|
@ -2584,15 +2749,84 @@ void PromotionInfo::verify() const {
|
||||||
guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
|
guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PromotionInfo::print_on(outputStream* st) const {
|
||||||
|
SpoolBlock* curSpool = NULL;
|
||||||
|
size_t i = 0;
|
||||||
|
st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")",
|
||||||
|
_firstIndex, _nextIndex);
|
||||||
|
for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL;
|
||||||
|
curSpool = curSpool->nextSpoolBlock) {
|
||||||
|
curSpool->print_on(st);
|
||||||
|
st->print_cr(" active ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for (curSpool = _spoolTail; curSpool != NULL;
|
||||||
|
curSpool = curSpool->nextSpoolBlock) {
|
||||||
|
curSpool->print_on(st);
|
||||||
|
st->print_cr(" inactive ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for (curSpool = _spareSpool; curSpool != NULL;
|
||||||
|
curSpool = curSpool->nextSpoolBlock) {
|
||||||
|
curSpool->print_on(st);
|
||||||
|
st->print_cr(" free ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
st->print_cr(SIZE_FORMAT " header spooling blocks", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpoolBlock::print_on(outputStream* st) const {
|
||||||
|
st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT,
|
||||||
|
this, (HeapWord*)displacedHdr + bufferSize,
|
||||||
|
bufferSize, nextSpoolBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// CFLS_LAB
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define VECTOR_257(x) \
|
||||||
|
/* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \
|
||||||
|
{ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \
|
||||||
|
x }
|
||||||
|
|
||||||
|
// Initialize with default setting of CMSParPromoteBlocksToClaim, _not_
|
||||||
|
// OldPLABSize, whose static default is different; if overridden at the
|
||||||
|
// command-line, this will get reinitialized via a call to
|
||||||
|
// modify_initialization() below.
|
||||||
|
AdaptiveWeightedAverage CFLS_LAB::_blocks_to_claim[] =
|
||||||
|
VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CMSParPromoteBlocksToClaim));
|
||||||
|
size_t CFLS_LAB::_global_num_blocks[] = VECTOR_257(0);
|
||||||
|
int CFLS_LAB::_global_num_workers[] = VECTOR_257(0);
|
||||||
|
|
||||||
CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) :
|
CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) :
|
||||||
_cfls(cfls)
|
_cfls(cfls)
|
||||||
{
|
{
|
||||||
_blocks_to_claim = CMSParPromoteBlocksToClaim;
|
assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above");
|
||||||
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
||||||
i < CompactibleFreeListSpace::IndexSetSize;
|
i < CompactibleFreeListSpace::IndexSetSize;
|
||||||
i += CompactibleFreeListSpace::IndexSetStride) {
|
i += CompactibleFreeListSpace::IndexSetStride) {
|
||||||
_indexedFreeList[i].set_size(i);
|
_indexedFreeList[i].set_size(i);
|
||||||
|
_num_blocks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _CFLS_LAB_modified = false;
|
||||||
|
|
||||||
|
void CFLS_LAB::modify_initialization(size_t n, unsigned wt) {
|
||||||
|
assert(!_CFLS_LAB_modified, "Call only once");
|
||||||
|
_CFLS_LAB_modified = true;
|
||||||
|
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
||||||
|
i < CompactibleFreeListSpace::IndexSetSize;
|
||||||
|
i += CompactibleFreeListSpace::IndexSetStride) {
|
||||||
|
_blocks_to_claim[i].modify(n, wt, true /* force */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2607,11 +2841,9 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) {
|
||||||
if (res == NULL) return NULL;
|
if (res == NULL) return NULL;
|
||||||
} else {
|
} else {
|
||||||
FreeList* fl = &_indexedFreeList[word_sz];
|
FreeList* fl = &_indexedFreeList[word_sz];
|
||||||
bool filled = false; //TRAP
|
|
||||||
if (fl->count() == 0) {
|
if (fl->count() == 0) {
|
||||||
bool filled = true; //TRAP
|
|
||||||
// Attempt to refill this local free list.
|
// Attempt to refill this local free list.
|
||||||
_cfls->par_get_chunk_of_blocks(word_sz, _blocks_to_claim, fl);
|
get_from_global_pool(word_sz, fl);
|
||||||
// If it didn't work, give up.
|
// If it didn't work, give up.
|
||||||
if (fl->count() == 0) return NULL;
|
if (fl->count() == 0) return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2626,34 +2858,126 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) {
|
||||||
return (HeapWord*)res;
|
return (HeapWord*)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFLS_LAB::retire() {
|
// Get a chunk of blocks of the right size and update related
|
||||||
|
// book-keeping stats
|
||||||
|
void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
|
||||||
|
// Get the #blocks we want to claim
|
||||||
|
size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
|
||||||
|
assert(n_blks > 0, "Error");
|
||||||
|
assert(ResizePLAB || n_blks == OldPLABSize, "Error");
|
||||||
|
// In some cases, when the application has a phase change,
|
||||||
|
// there may be a sudden and sharp shift in the object survival
|
||||||
|
// profile, and updating the counts at the end of a scavenge
|
||||||
|
// may not be quick enough, giving rise to large scavenge pauses
|
||||||
|
// during these phase changes. It is beneficial to detect such
|
||||||
|
// changes on-the-fly during a scavenge and avoid such a phase-change
|
||||||
|
// pothole. The following code is a heuristic attempt to do that.
|
||||||
|
// It is protected by a product flag until we have gained
|
||||||
|
// enough experience with this heuristic and fine-tuned its behaviour.
|
||||||
|
// WARNING: This might increase fragmentation if we overreact to
|
||||||
|
// small spikes, so some kind of historical smoothing based on
|
||||||
|
// previous experience with the greater reactivity might be useful.
|
||||||
|
// Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by
|
||||||
|
// default.
|
||||||
|
if (ResizeOldPLAB && CMSOldPLABResizeQuicker) {
|
||||||
|
size_t multiple = _num_blocks[word_sz]/(CMSOldPLABToleranceFactor*CMSOldPLABNumRefills*n_blks);
|
||||||
|
n_blks += CMSOldPLABReactivityFactor*multiple*n_blks;
|
||||||
|
n_blks = MIN2(n_blks, CMSOldPLABMax);
|
||||||
|
}
|
||||||
|
assert(n_blks > 0, "Error");
|
||||||
|
_cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl);
|
||||||
|
// Update stats table entry for this block size
|
||||||
|
_num_blocks[word_sz] += fl->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFLS_LAB::compute_desired_plab_size() {
|
||||||
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
||||||
i < CompactibleFreeListSpace::IndexSetSize;
|
i < CompactibleFreeListSpace::IndexSetSize;
|
||||||
i += CompactibleFreeListSpace::IndexSetStride) {
|
i += CompactibleFreeListSpace::IndexSetStride) {
|
||||||
if (_indexedFreeList[i].count() > 0) {
|
assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0),
|
||||||
|
"Counter inconsistency");
|
||||||
|
if (_global_num_workers[i] > 0) {
|
||||||
|
// Need to smooth wrt historical average
|
||||||
|
if (ResizeOldPLAB) {
|
||||||
|
_blocks_to_claim[i].sample(
|
||||||
|
MAX2((size_t)CMSOldPLABMin,
|
||||||
|
MIN2((size_t)CMSOldPLABMax,
|
||||||
|
_global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
|
||||||
|
}
|
||||||
|
// Reset counters for next round
|
||||||
|
_global_num_workers[i] = 0;
|
||||||
|
_global_num_blocks[i] = 0;
|
||||||
|
if (PrintOldPLAB) {
|
||||||
|
gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFLS_LAB::retire(int tid) {
|
||||||
|
// We run this single threaded with the world stopped;
|
||||||
|
// so no need for locks and such.
|
||||||
|
#define CFLS_LAB_PARALLEL_ACCESS 0
|
||||||
|
NOT_PRODUCT(Thread* t = Thread::current();)
|
||||||
|
assert(Thread::current()->is_VM_thread(), "Error");
|
||||||
|
assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride,
|
||||||
|
"Will access to uninitialized slot below");
|
||||||
|
#if CFLS_LAB_PARALLEL_ACCESS
|
||||||
|
for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1;
|
||||||
|
i > 0;
|
||||||
|
i -= CompactibleFreeListSpace::IndexSetStride) {
|
||||||
|
#else // CFLS_LAB_PARALLEL_ACCESS
|
||||||
|
for (size_t i = CompactibleFreeListSpace::IndexSetStart;
|
||||||
|
i < CompactibleFreeListSpace::IndexSetSize;
|
||||||
|
i += CompactibleFreeListSpace::IndexSetStride) {
|
||||||
|
#endif // !CFLS_LAB_PARALLEL_ACCESS
|
||||||
|
assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
|
||||||
|
"Can't retire more than what we obtained");
|
||||||
|
if (_num_blocks[i] > 0) {
|
||||||
|
size_t num_retire = _indexedFreeList[i].count();
|
||||||
|
assert(_num_blocks[i] > num_retire, "Should have used at least one");
|
||||||
|
{
|
||||||
|
#if CFLS_LAB_PARALLEL_ACCESS
|
||||||
MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
|
MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
|
#endif // CFLS_LAB_PARALLEL_ACCESS
|
||||||
|
// Update globals stats for num_blocks used
|
||||||
|
_global_num_blocks[i] += (_num_blocks[i] - num_retire);
|
||||||
|
_global_num_workers[i]++;
|
||||||
|
assert(_global_num_workers[i] <= (ssize_t)ParallelGCThreads, "Too big");
|
||||||
|
if (num_retire > 0) {
|
||||||
_cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
|
_cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
|
||||||
// Reset this list.
|
// Reset this list.
|
||||||
_indexedFreeList[i] = FreeList();
|
_indexedFreeList[i] = FreeList();
|
||||||
_indexedFreeList[i].set_size(i);
|
_indexedFreeList[i].set_size(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (PrintOldPLAB) {
|
||||||
|
gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
|
||||||
|
tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
|
||||||
|
}
|
||||||
|
// Reset stats for next round
|
||||||
|
_num_blocks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
CompactibleFreeListSpace::
|
|
||||||
par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
|
||||||
assert(fl->count() == 0, "Precondition.");
|
assert(fl->count() == 0, "Precondition.");
|
||||||
assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
|
assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
|
||||||
"Precondition");
|
"Precondition");
|
||||||
|
|
||||||
// We'll try all multiples of word_sz in the indexed set (starting with
|
// We'll try all multiples of word_sz in the indexed set, starting with
|
||||||
// word_sz itself), then try getting a big chunk and splitting it.
|
// word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples,
|
||||||
int k = 1;
|
// then try getting a big chunk and splitting it.
|
||||||
size_t cur_sz = k * word_sz;
|
{
|
||||||
bool found = false;
|
bool found;
|
||||||
while (cur_sz < CompactibleFreeListSpace::IndexSetSize && k == 1) {
|
int k;
|
||||||
|
size_t cur_sz;
|
||||||
|
for (k = 1, cur_sz = k * word_sz, found = false;
|
||||||
|
(cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
|
||||||
|
(CMSSplitIndexedFreeListBlocks || k <= 1);
|
||||||
|
k++, cur_sz = k * word_sz) {
|
||||||
FreeList* gfl = &_indexedFreeList[cur_sz];
|
FreeList* gfl = &_indexedFreeList[cur_sz];
|
||||||
FreeList fl_for_cur_sz; // Empty.
|
FreeList fl_for_cur_sz; // Empty.
|
||||||
fl_for_cur_sz.set_size(cur_sz);
|
fl_for_cur_sz.set_size(cur_sz);
|
||||||
|
@ -2661,9 +2985,21 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
|
MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
if (gfl->count() != 0) {
|
if (gfl->count() != 0) {
|
||||||
size_t nn = MAX2(n/k, (size_t)1);
|
// nn is the number of chunks of size cur_sz that
|
||||||
|
// we'd need to split k-ways each, in order to create
|
||||||
|
// "n" chunks of size word_sz each.
|
||||||
|
const size_t nn = MAX2(n/k, (size_t)1);
|
||||||
gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
|
gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
|
||||||
found = true;
|
found = true;
|
||||||
|
if (k > 1) {
|
||||||
|
// Update split death stats for the cur_sz-size blocks list:
|
||||||
|
// we increment the split death count by the number of blocks
|
||||||
|
// we just took from the cur_sz-size blocks list and which
|
||||||
|
// we will be splitting below.
|
||||||
|
ssize_t deaths = _indexedFreeList[cur_sz].splitDeaths() +
|
||||||
|
fl_for_cur_sz.count();
|
||||||
|
_indexedFreeList[cur_sz].set_splitDeaths(deaths);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1.
|
// Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1.
|
||||||
|
@ -2697,9 +3033,15 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
assert(fl->tail()->next() == NULL, "List invariant.");
|
assert(fl->tail()->next() == NULL, "List invariant.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Update birth stats for this block size.
|
||||||
|
size_t num = fl->count();
|
||||||
|
MutexLockerEx x(_indexedFreeListParLocks[word_sz],
|
||||||
|
Mutex::_no_safepoint_check_flag);
|
||||||
|
ssize_t births = _indexedFreeList[word_sz].splitBirths() + num;
|
||||||
|
_indexedFreeList[word_sz].set_splitBirths(births);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
k++; cur_sz = k * word_sz;
|
}
|
||||||
}
|
}
|
||||||
// Otherwise, we'll split a block from the dictionary.
|
// Otherwise, we'll split a block from the dictionary.
|
||||||
FreeChunk* fc = NULL;
|
FreeChunk* fc = NULL;
|
||||||
|
@ -2723,17 +3065,31 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fc == NULL) return;
|
if (fc == NULL) return;
|
||||||
|
assert((ssize_t)n >= 1, "Control point invariant");
|
||||||
// Otherwise, split up that block.
|
// Otherwise, split up that block.
|
||||||
size_t nn = fc->size() / word_sz;
|
const size_t nn = fc->size() / word_sz;
|
||||||
n = MIN2(nn, n);
|
n = MIN2(nn, n);
|
||||||
|
assert((ssize_t)n >= 1, "Control point invariant");
|
||||||
rem = fc->size() - n * word_sz;
|
rem = fc->size() - n * word_sz;
|
||||||
// If there is a remainder, and it's too small, allocate one fewer.
|
// If there is a remainder, and it's too small, allocate one fewer.
|
||||||
if (rem > 0 && rem < MinChunkSize) {
|
if (rem > 0 && rem < MinChunkSize) {
|
||||||
n--; rem += word_sz;
|
n--; rem += word_sz;
|
||||||
}
|
}
|
||||||
|
// Note that at this point we may have n == 0.
|
||||||
|
assert((ssize_t)n >= 0, "Control point invariant");
|
||||||
|
|
||||||
|
// If n is 0, the chunk fc that was found is not large
|
||||||
|
// enough to leave a viable remainder. We are unable to
|
||||||
|
// allocate even one block. Return fc to the
|
||||||
|
// dictionary and return, leaving "fl" empty.
|
||||||
|
if (n == 0) {
|
||||||
|
returnChunkToDictionary(fc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// First return the remainder, if any.
|
// First return the remainder, if any.
|
||||||
// Note that we hold the lock until we decide if we're going to give
|
// Note that we hold the lock until we decide if we're going to give
|
||||||
// back the remainder to the dictionary, since a contending allocator
|
// back the remainder to the dictionary, since a concurrent allocation
|
||||||
// may otherwise see the heap as empty. (We're willing to take that
|
// may otherwise see the heap as empty. (We're willing to take that
|
||||||
// hit if the block is a small block.)
|
// hit if the block is a small block.)
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
|
@ -2743,18 +3099,16 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
rem_fc->linkNext(NULL);
|
rem_fc->linkNext(NULL);
|
||||||
rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
|
rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
|
||||||
// Above must occur before BOT is updated below.
|
// Above must occur before BOT is updated below.
|
||||||
|
assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error");
|
||||||
_bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
|
_bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
|
||||||
if (rem >= IndexSetSize) {
|
if (rem >= IndexSetSize) {
|
||||||
returnChunkToDictionary(rem_fc);
|
returnChunkToDictionary(rem_fc);
|
||||||
dictionary()->dictCensusUpdate(fc->size(),
|
dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/);
|
||||||
true /*split*/,
|
|
||||||
true /*birth*/);
|
|
||||||
rem_fc = NULL;
|
rem_fc = NULL;
|
||||||
}
|
}
|
||||||
// Otherwise, return it to the small list below.
|
// Otherwise, return it to the small list below.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
if (rem_fc != NULL) {
|
if (rem_fc != NULL) {
|
||||||
MutexLockerEx x(_indexedFreeListParLocks[rem],
|
MutexLockerEx x(_indexedFreeListParLocks[rem],
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
|
@ -2762,7 +3116,7 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
_indexedFreeList[rem].returnChunkAtHead(rem_fc);
|
_indexedFreeList[rem].returnChunkAtHead(rem_fc);
|
||||||
smallSplitBirth(rem);
|
smallSplitBirth(rem);
|
||||||
}
|
}
|
||||||
|
assert((ssize_t)n > 0 && fc != NULL, "Consistency");
|
||||||
// Now do the splitting up.
|
// Now do the splitting up.
|
||||||
// Must do this in reverse order, so that anybody attempting to
|
// Must do this in reverse order, so that anybody attempting to
|
||||||
// access the main chunk sees it as a single free block until we
|
// access the main chunk sees it as a single free block until we
|
||||||
|
@ -2792,13 +3146,15 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||||
_bt.verify_single_block((HeapWord*)fc, fc->size());
|
_bt.verify_single_block((HeapWord*)fc, fc->size());
|
||||||
fl->returnChunkAtHead(fc);
|
fl->returnChunkAtHead(fc);
|
||||||
|
|
||||||
|
assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
|
||||||
{
|
{
|
||||||
|
// Update the stats for this block size.
|
||||||
MutexLockerEx x(_indexedFreeListParLocks[word_sz],
|
MutexLockerEx x(_indexedFreeListParLocks[word_sz],
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
ssize_t new_births = _indexedFreeList[word_sz].splitBirths() + n;
|
const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n;
|
||||||
_indexedFreeList[word_sz].set_splitBirths(new_births);
|
_indexedFreeList[word_sz].set_splitBirths(births);
|
||||||
ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
|
// ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
|
||||||
_indexedFreeList[word_sz].set_surplus(new_surplus);
|
// _indexedFreeList[word_sz].set_surplus(new_surplus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRAP
|
// TRAP
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
// Classes in support of keeping track of promotions into a non-Contiguous
|
// Classes in support of keeping track of promotions into a non-Contiguous
|
||||||
// space, in this case a CompactibleFreeListSpace.
|
// space, in this case a CompactibleFreeListSpace.
|
||||||
|
|
||||||
#define CFLS_LAB_REFILL_STATS 0
|
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class CompactibleFreeListSpace;
|
class CompactibleFreeListSpace;
|
||||||
class BlkClosure;
|
class BlkClosure;
|
||||||
|
@ -89,6 +87,9 @@ class SpoolBlock: public FreeChunk {
|
||||||
displacedHdr = (markOop*)&displacedHdr;
|
displacedHdr = (markOop*)&displacedHdr;
|
||||||
nextSpoolBlock = NULL;
|
nextSpoolBlock = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_on(outputStream* st) const;
|
||||||
|
void print() const { print_on(gclog_or_tty); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PromotionInfo VALUE_OBJ_CLASS_SPEC {
|
class PromotionInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
|
@ -121,7 +122,7 @@ class PromotionInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
return _promoHead == NULL;
|
return _promoHead == NULL;
|
||||||
}
|
}
|
||||||
void startTrackingPromotions();
|
void startTrackingPromotions();
|
||||||
void stopTrackingPromotions();
|
void stopTrackingPromotions(uint worker_id = 0);
|
||||||
bool tracking() const { return _tracking; }
|
bool tracking() const { return _tracking; }
|
||||||
void track(PromotedObject* trackOop); // keep track of a promoted oop
|
void track(PromotedObject* trackOop); // keep track of a promoted oop
|
||||||
// The following variant must be used when trackOop is not fully
|
// The following variant must be used when trackOop is not fully
|
||||||
|
@ -161,6 +162,9 @@ class PromotionInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
_nextIndex = 0;
|
_nextIndex = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_on(outputStream* st) const;
|
||||||
|
void print_statistics(uint worker_id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LinearAllocBlock VALUE_OBJ_CLASS_SPEC {
|
class LinearAllocBlock VALUE_OBJ_CLASS_SPEC {
|
||||||
|
@ -243,6 +247,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
mutable Mutex _freelistLock;
|
mutable Mutex _freelistLock;
|
||||||
// locking verifier convenience function
|
// locking verifier convenience function
|
||||||
void assert_locked() const PRODUCT_RETURN;
|
void assert_locked() const PRODUCT_RETURN;
|
||||||
|
void assert_locked(const Mutex* lock) const PRODUCT_RETURN;
|
||||||
|
|
||||||
// Linear allocation blocks
|
// Linear allocation blocks
|
||||||
LinearAllocBlock _smallLinearAllocBlock;
|
LinearAllocBlock _smallLinearAllocBlock;
|
||||||
|
@ -281,13 +286,6 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
// Locks protecting the exact lists during par promotion allocation.
|
// Locks protecting the exact lists during par promotion allocation.
|
||||||
Mutex* _indexedFreeListParLocks[IndexSetSize];
|
Mutex* _indexedFreeListParLocks[IndexSetSize];
|
||||||
|
|
||||||
#if CFLS_LAB_REFILL_STATS
|
|
||||||
// Some statistics.
|
|
||||||
jint _par_get_chunk_from_small;
|
|
||||||
jint _par_get_chunk_from_large;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Attempt to obtain up to "n" blocks of the size "word_sz" (which is
|
// Attempt to obtain up to "n" blocks of the size "word_sz" (which is
|
||||||
// required to be smaller than "IndexSetSize".) If successful,
|
// required to be smaller than "IndexSetSize".) If successful,
|
||||||
// adds them to "fl", which is required to be an empty free list.
|
// adds them to "fl", which is required to be an empty free list.
|
||||||
|
@ -320,7 +318,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
// Helper function for getChunkFromIndexedFreeList.
|
// Helper function for getChunkFromIndexedFreeList.
|
||||||
// Replenish the indexed free list for this "size". Do not take from an
|
// Replenish the indexed free list for this "size". Do not take from an
|
||||||
// underpopulated size.
|
// underpopulated size.
|
||||||
FreeChunk* getChunkFromIndexedFreeListHelper(size_t size);
|
FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true);
|
||||||
|
|
||||||
// Get a chunk from the indexed free list. If the indexed free list
|
// Get a chunk from the indexed free list. If the indexed free list
|
||||||
// does not have a free chunk, try to replenish the indexed free list
|
// does not have a free chunk, try to replenish the indexed free list
|
||||||
|
@ -430,10 +428,6 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
void initialize_sequential_subtasks_for_marking(int n_threads,
|
void initialize_sequential_subtasks_for_marking(int n_threads,
|
||||||
HeapWord* low = NULL);
|
HeapWord* low = NULL);
|
||||||
|
|
||||||
#if CFLS_LAB_REFILL_STATS
|
|
||||||
void print_par_alloc_stats();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Space enquiries
|
// Space enquiries
|
||||||
size_t used() const;
|
size_t used() const;
|
||||||
size_t free() const;
|
size_t free() const;
|
||||||
|
@ -617,6 +611,12 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
// Do some basic checks on the the free lists.
|
// Do some basic checks on the the free lists.
|
||||||
void checkFreeListConsistency() const PRODUCT_RETURN;
|
void checkFreeListConsistency() const PRODUCT_RETURN;
|
||||||
|
|
||||||
|
// Printing support
|
||||||
|
void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st);
|
||||||
|
void print_indexed_free_lists(outputStream* st) const;
|
||||||
|
void print_dictionary_free_lists(outputStream* st) const;
|
||||||
|
void print_promo_info_blocks(outputStream* st) const;
|
||||||
|
|
||||||
NOT_PRODUCT (
|
NOT_PRODUCT (
|
||||||
void initializeIndexedFreeListArrayReturnedBytes();
|
void initializeIndexedFreeListArrayReturnedBytes();
|
||||||
size_t sumIndexedFreeListArrayReturnedBytes();
|
size_t sumIndexedFreeListArrayReturnedBytes();
|
||||||
|
@ -638,8 +638,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||||
|
|
||||||
// Statistics functions
|
// Statistics functions
|
||||||
// Initialize census for lists before the sweep.
|
// Initialize census for lists before the sweep.
|
||||||
void beginSweepFLCensus(float sweep_current,
|
void beginSweepFLCensus(float inter_sweep_current,
|
||||||
float sweep_estimate);
|
float inter_sweep_estimate,
|
||||||
|
float intra_sweep_estimate);
|
||||||
// Set the surplus for each of the free lists.
|
// Set the surplus for each of the free lists.
|
||||||
void setFLSurplus();
|
void setFLSurplus();
|
||||||
// Set the hint for each of the free lists.
|
// Set the hint for each of the free lists.
|
||||||
|
@ -730,16 +731,17 @@ class CFLS_LAB : public CHeapObj {
|
||||||
FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
|
FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
|
||||||
|
|
||||||
// Initialized from a command-line arg.
|
// Initialized from a command-line arg.
|
||||||
size_t _blocks_to_claim;
|
|
||||||
|
|
||||||
#if CFLS_LAB_REFILL_STATS
|
// Allocation statistics in support of dynamic adjustment of
|
||||||
// Some statistics.
|
// #blocks to claim per get_from_global_pool() call below.
|
||||||
int _refills;
|
static AdaptiveWeightedAverage
|
||||||
int _blocksTaken;
|
_blocks_to_claim [CompactibleFreeListSpace::IndexSetSize];
|
||||||
static int _tot_refills;
|
static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize];
|
||||||
static int _tot_blocksTaken;
|
static int _global_num_workers[CompactibleFreeListSpace::IndexSetSize];
|
||||||
static int _next_threshold;
|
size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize];
|
||||||
#endif
|
|
||||||
|
// Internal work method
|
||||||
|
void get_from_global_pool(size_t word_sz, FreeList* fl);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CFLS_LAB(CompactibleFreeListSpace* cfls);
|
CFLS_LAB(CompactibleFreeListSpace* cfls);
|
||||||
|
@ -748,7 +750,12 @@ public:
|
||||||
HeapWord* alloc(size_t word_sz);
|
HeapWord* alloc(size_t word_sz);
|
||||||
|
|
||||||
// Return any unused portions of the buffer to the global pool.
|
// Return any unused portions of the buffer to the global pool.
|
||||||
void retire();
|
void retire(int tid);
|
||||||
|
|
||||||
|
// Dynamic OldPLABSize sizing
|
||||||
|
static void compute_desired_plab_size();
|
||||||
|
// When the settings are modified from default static initialization
|
||||||
|
static void modify_initialization(size_t n, unsigned wt);
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t PromotionInfo::refillSize() const {
|
size_t PromotionInfo::refillSize() const {
|
||||||
|
|
|
@ -253,7 +253,6 @@ void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConcurrentMarkSweepGeneration::ref_processor_init() {
|
void ConcurrentMarkSweepGeneration::ref_processor_init() {
|
||||||
assert(collector() != NULL, "no collector");
|
assert(collector() != NULL, "no collector");
|
||||||
collector()->ref_processor_init();
|
collector()->ref_processor_init();
|
||||||
|
@ -341,6 +340,14 @@ CMSStats::CMSStats(ConcurrentMarkSweepGeneration* cms_gen, unsigned int alpha):
|
||||||
_icms_duty_cycle = CMSIncrementalDutyCycle;
|
_icms_duty_cycle = CMSIncrementalDutyCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double CMSStats::cms_free_adjustment_factor(size_t free) const {
|
||||||
|
// TBD: CR 6909490
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMSStats::adjust_cms_free_adjustment_factor(bool fail, size_t free) {
|
||||||
|
}
|
||||||
|
|
||||||
// If promotion failure handling is on use
|
// If promotion failure handling is on use
|
||||||
// the padded average size of the promotion for each
|
// the padded average size of the promotion for each
|
||||||
// young generation collection.
|
// young generation collection.
|
||||||
|
@ -361,7 +368,11 @@ double CMSStats::time_until_cms_gen_full() const {
|
||||||
|
|
||||||
// Adjust by the safety factor.
|
// Adjust by the safety factor.
|
||||||
double cms_free_dbl = (double)cms_free;
|
double cms_free_dbl = (double)cms_free;
|
||||||
cms_free_dbl = cms_free_dbl * (100.0 - CMSIncrementalSafetyFactor) / 100.0;
|
double cms_adjustment = (100.0 - CMSIncrementalSafetyFactor)/100.0;
|
||||||
|
// Apply a further correction factor which tries to adjust
|
||||||
|
// for recent occurance of concurrent mode failures.
|
||||||
|
cms_adjustment = cms_adjustment * cms_free_adjustment_factor(cms_free);
|
||||||
|
cms_free_dbl = cms_free_dbl * cms_adjustment;
|
||||||
|
|
||||||
if (PrintGCDetails && Verbose) {
|
if (PrintGCDetails && Verbose) {
|
||||||
gclog_or_tty->print_cr("CMSStats::time_until_cms_gen_full: cms_free "
|
gclog_or_tty->print_cr("CMSStats::time_until_cms_gen_full: cms_free "
|
||||||
|
@ -395,6 +406,8 @@ double CMSStats::time_until_cms_start() const {
|
||||||
// late.
|
// late.
|
||||||
double work = cms_duration() + gc0_period();
|
double work = cms_duration() + gc0_period();
|
||||||
double deadline = time_until_cms_gen_full();
|
double deadline = time_until_cms_gen_full();
|
||||||
|
// If a concurrent mode failure occurred recently, we want to be
|
||||||
|
// more conservative and halve our expected time_until_cms_gen_full()
|
||||||
if (work > deadline) {
|
if (work > deadline) {
|
||||||
if (Verbose && PrintGCDetails) {
|
if (Verbose && PrintGCDetails) {
|
||||||
gclog_or_tty->print(
|
gclog_or_tty->print(
|
||||||
|
@ -556,7 +569,8 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
|
||||||
_should_unload_classes(false),
|
_should_unload_classes(false),
|
||||||
_concurrent_cycles_since_last_unload(0),
|
_concurrent_cycles_since_last_unload(0),
|
||||||
_roots_scanning_options(0),
|
_roots_scanning_options(0),
|
||||||
_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding)
|
_inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
|
||||||
|
_intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding)
|
||||||
{
|
{
|
||||||
if (ExplicitGCInvokesConcurrentAndUnloadsClasses) {
|
if (ExplicitGCInvokesConcurrentAndUnloadsClasses) {
|
||||||
ExplicitGCInvokesConcurrent = true;
|
ExplicitGCInvokesConcurrent = true;
|
||||||
|
@ -773,7 +787,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
|
||||||
NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;)
|
NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;)
|
||||||
_gc_counters = new CollectorCounters("CMS", 1);
|
_gc_counters = new CollectorCounters("CMS", 1);
|
||||||
_completed_initialization = true;
|
_completed_initialization = true;
|
||||||
_sweep_timer.start(); // start of time
|
_inter_sweep_timer.start(); // start of time
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ConcurrentMarkSweepGeneration::name() const {
|
const char* ConcurrentMarkSweepGeneration::name() const {
|
||||||
|
@ -900,6 +914,14 @@ bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At a promotion failure dump information on block layout in heap
|
||||||
|
// (cms old generation).
|
||||||
|
void ConcurrentMarkSweepGeneration::promotion_failure_occurred() {
|
||||||
|
if (CMSDumpAtPromotionFailure) {
|
||||||
|
cmsSpace()->dump_at_safepoint_with_locks(collector(), gclog_or_tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CompactibleSpace*
|
CompactibleSpace*
|
||||||
ConcurrentMarkSweepGeneration::first_compaction_space() const {
|
ConcurrentMarkSweepGeneration::first_compaction_space() const {
|
||||||
return _cmsSpace;
|
return _cmsSpace;
|
||||||
|
@ -1368,12 +1390,7 @@ void
|
||||||
ConcurrentMarkSweepGeneration::
|
ConcurrentMarkSweepGeneration::
|
||||||
par_promote_alloc_done(int thread_num) {
|
par_promote_alloc_done(int thread_num) {
|
||||||
CMSParGCThreadState* ps = _par_gc_thread_states[thread_num];
|
CMSParGCThreadState* ps = _par_gc_thread_states[thread_num];
|
||||||
ps->lab.retire();
|
ps->lab.retire(thread_num);
|
||||||
#if CFLS_LAB_REFILL_STATS
|
|
||||||
if (thread_num == 0) {
|
|
||||||
_cmsSpace->print_par_alloc_stats();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1974,11 +1991,14 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
|
||||||
// We must adjust the allocation statistics being maintained
|
// We must adjust the allocation statistics being maintained
|
||||||
// in the free list space. We do so by reading and clearing
|
// in the free list space. We do so by reading and clearing
|
||||||
// the sweep timer and updating the block flux rate estimates below.
|
// the sweep timer and updating the block flux rate estimates below.
|
||||||
assert(_sweep_timer.is_active(), "We should never see the timer inactive");
|
assert(!_intra_sweep_timer.is_active(), "_intra_sweep_timer should be inactive");
|
||||||
_sweep_timer.stop();
|
if (_inter_sweep_timer.is_active()) {
|
||||||
// Note that we do not use this sample to update the _sweep_estimate.
|
_inter_sweep_timer.stop();
|
||||||
_cmsGen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()),
|
// Note that we do not use this sample to update the _inter_sweep_estimate.
|
||||||
_sweep_estimate.padded_average());
|
_cmsGen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()),
|
||||||
|
_inter_sweep_estimate.padded_average(),
|
||||||
|
_intra_sweep_estimate.padded_average());
|
||||||
|
}
|
||||||
|
|
||||||
GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
|
GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
|
||||||
ref_processor(), clear_all_soft_refs);
|
ref_processor(), clear_all_soft_refs);
|
||||||
|
@ -2015,10 +2035,10 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the per-size allocation stats for the next epoch.
|
// Adjust the per-size allocation stats for the next epoch.
|
||||||
_cmsGen->cmsSpace()->endSweepFLCensus(sweepCount() /* fake */);
|
_cmsGen->cmsSpace()->endSweepFLCensus(sweep_count() /* fake */);
|
||||||
// Restart the "sweep timer" for next epoch.
|
// Restart the "inter sweep timer" for the next epoch.
|
||||||
_sweep_timer.reset();
|
_inter_sweep_timer.reset();
|
||||||
_sweep_timer.start();
|
_inter_sweep_timer.start();
|
||||||
|
|
||||||
// Sample collection pause time and reset for collection interval.
|
// Sample collection pause time and reset for collection interval.
|
||||||
if (UseAdaptiveSizePolicy) {
|
if (UseAdaptiveSizePolicy) {
|
||||||
|
@ -2676,7 +2696,7 @@ void ConcurrentMarkSweepGeneration::gc_epilogue(bool full) {
|
||||||
// Also reset promotion tracking in par gc thread states.
|
// Also reset promotion tracking in par gc thread states.
|
||||||
if (ParallelGCThreads > 0) {
|
if (ParallelGCThreads > 0) {
|
||||||
for (uint i = 0; i < ParallelGCThreads; i++) {
|
for (uint i = 0; i < ParallelGCThreads; i++) {
|
||||||
_par_gc_thread_states[i]->promo.stopTrackingPromotions();
|
_par_gc_thread_states[i]->promo.stopTrackingPromotions(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2771,7 +2791,7 @@ class VerifyMarkedClosure: public BitMapClosure {
|
||||||
bool do_bit(size_t offset) {
|
bool do_bit(size_t offset) {
|
||||||
HeapWord* addr = _marks->offsetToHeapWord(offset);
|
HeapWord* addr = _marks->offsetToHeapWord(offset);
|
||||||
if (!_marks->isMarked(addr)) {
|
if (!_marks->isMarked(addr)) {
|
||||||
oop(addr)->print();
|
oop(addr)->print_on(gclog_or_tty);
|
||||||
gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr);
|
gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
}
|
}
|
||||||
|
@ -2820,7 +2840,7 @@ bool CMSCollector::verify_after_remark() {
|
||||||
// Clear any marks from a previous round
|
// Clear any marks from a previous round
|
||||||
verification_mark_bm()->clear_all();
|
verification_mark_bm()->clear_all();
|
||||||
assert(verification_mark_stack()->isEmpty(), "markStack should be empty");
|
assert(verification_mark_stack()->isEmpty(), "markStack should be empty");
|
||||||
assert(overflow_list_is_empty(), "overflow list should be empty");
|
verify_work_stacks_empty();
|
||||||
|
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
gch->ensure_parsability(false); // fill TLABs, but no need to retire them
|
gch->ensure_parsability(false); // fill TLABs, but no need to retire them
|
||||||
|
@ -2893,8 +2913,8 @@ void CMSCollector::verify_after_remark_work_1() {
|
||||||
verification_mark_bm()->iterate(&vcl);
|
verification_mark_bm()->iterate(&vcl);
|
||||||
if (vcl.failed()) {
|
if (vcl.failed()) {
|
||||||
gclog_or_tty->print("Verification failed");
|
gclog_or_tty->print("Verification failed");
|
||||||
Universe::heap()->print();
|
Universe::heap()->print_on(gclog_or_tty);
|
||||||
fatal(" ... aborting");
|
fatal("CMS: failed marking verification after remark");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3314,7 +3334,7 @@ bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) {
|
||||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||||
// Hmmmm... why doesn't CFLS::set_end verify locking?
|
// Hmmmm... why doesn't CFLS::set_end verify locking?
|
||||||
// This is quite ugly; FIX ME XXX
|
// This is quite ugly; FIX ME XXX
|
||||||
_cmsSpace->assert_locked();
|
_cmsSpace->assert_locked(freelistLock());
|
||||||
_cmsSpace->set_end((HeapWord*)_virtual_space.high());
|
_cmsSpace->set_end((HeapWord*)_virtual_space.high());
|
||||||
|
|
||||||
// update the space and generation capacity counters
|
// update the space and generation capacity counters
|
||||||
|
@ -5868,9 +5888,9 @@ void CMSCollector::sweep(bool asynch) {
|
||||||
check_correct_thread_executing();
|
check_correct_thread_executing();
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
verify_overflow_empty();
|
verify_overflow_empty();
|
||||||
incrementSweepCount();
|
increment_sweep_count();
|
||||||
_sweep_timer.stop();
|
_inter_sweep_timer.stop();
|
||||||
_sweep_estimate.sample(_sweep_timer.seconds());
|
_inter_sweep_estimate.sample(_inter_sweep_timer.seconds());
|
||||||
size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free());
|
size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free());
|
||||||
|
|
||||||
// PermGen verification support: If perm gen sweeping is disabled in
|
// PermGen verification support: If perm gen sweeping is disabled in
|
||||||
|
@ -5893,6 +5913,9 @@ void CMSCollector::sweep(bool asynch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!_intra_sweep_timer.is_active(), "Should not be active");
|
||||||
|
_intra_sweep_timer.reset();
|
||||||
|
_intra_sweep_timer.start();
|
||||||
if (asynch) {
|
if (asynch) {
|
||||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||||
CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails);
|
CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails);
|
||||||
|
@ -5937,8 +5960,11 @@ void CMSCollector::sweep(bool asynch) {
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
verify_overflow_empty();
|
verify_overflow_empty();
|
||||||
|
|
||||||
_sweep_timer.reset();
|
_intra_sweep_timer.stop();
|
||||||
_sweep_timer.start();
|
_intra_sweep_estimate.sample(_intra_sweep_timer.seconds());
|
||||||
|
|
||||||
|
_inter_sweep_timer.reset();
|
||||||
|
_inter_sweep_timer.start();
|
||||||
|
|
||||||
update_time_of_last_gc(os::javaTimeMillis());
|
update_time_of_last_gc(os::javaTimeMillis());
|
||||||
|
|
||||||
|
@ -5981,11 +6007,11 @@ void CMSCollector::sweep(bool asynch) {
|
||||||
// FIX ME!!! Looks like this belongs in CFLSpace, with
|
// FIX ME!!! Looks like this belongs in CFLSpace, with
|
||||||
// CMSGen merely delegating to it.
|
// CMSGen merely delegating to it.
|
||||||
void ConcurrentMarkSweepGeneration::setNearLargestChunk() {
|
void ConcurrentMarkSweepGeneration::setNearLargestChunk() {
|
||||||
double nearLargestPercent = 0.999;
|
double nearLargestPercent = FLSLargestBlockCoalesceProximity;
|
||||||
HeapWord* minAddr = _cmsSpace->bottom();
|
HeapWord* minAddr = _cmsSpace->bottom();
|
||||||
HeapWord* largestAddr =
|
HeapWord* largestAddr =
|
||||||
(HeapWord*) _cmsSpace->dictionary()->findLargestDict();
|
(HeapWord*) _cmsSpace->dictionary()->findLargestDict();
|
||||||
if (largestAddr == 0) {
|
if (largestAddr == NULL) {
|
||||||
// The dictionary appears to be empty. In this case
|
// The dictionary appears to be empty. In this case
|
||||||
// try to coalesce at the end of the heap.
|
// try to coalesce at the end of the heap.
|
||||||
largestAddr = _cmsSpace->end();
|
largestAddr = _cmsSpace->end();
|
||||||
|
@ -5993,6 +6019,13 @@ void ConcurrentMarkSweepGeneration::setNearLargestChunk() {
|
||||||
size_t largestOffset = pointer_delta(largestAddr, minAddr);
|
size_t largestOffset = pointer_delta(largestAddr, minAddr);
|
||||||
size_t nearLargestOffset =
|
size_t nearLargestOffset =
|
||||||
(size_t)((double)largestOffset * nearLargestPercent) - MinChunkSize;
|
(size_t)((double)largestOffset * nearLargestPercent) - MinChunkSize;
|
||||||
|
if (PrintFLSStatistics != 0) {
|
||||||
|
gclog_or_tty->print_cr(
|
||||||
|
"CMS: Large Block: " PTR_FORMAT ";"
|
||||||
|
" Proximity: " PTR_FORMAT " -> " PTR_FORMAT,
|
||||||
|
largestAddr,
|
||||||
|
_cmsSpace->nearLargestChunk(), minAddr + nearLargestOffset);
|
||||||
|
}
|
||||||
_cmsSpace->set_nearLargestChunk(minAddr + nearLargestOffset);
|
_cmsSpace->set_nearLargestChunk(minAddr + nearLargestOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6072,9 +6105,11 @@ void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen,
|
||||||
assert_lock_strong(gen->freelistLock());
|
assert_lock_strong(gen->freelistLock());
|
||||||
assert_lock_strong(bitMapLock());
|
assert_lock_strong(bitMapLock());
|
||||||
|
|
||||||
assert(!_sweep_timer.is_active(), "Was switched off in an outer context");
|
assert(!_inter_sweep_timer.is_active(), "Was switched off in an outer context");
|
||||||
gen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()),
|
assert(_intra_sweep_timer.is_active(), "Was switched on in an outer context");
|
||||||
_sweep_estimate.padded_average());
|
gen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()),
|
||||||
|
_inter_sweep_estimate.padded_average(),
|
||||||
|
_intra_sweep_estimate.padded_average());
|
||||||
gen->setNearLargestChunk();
|
gen->setNearLargestChunk();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -6087,7 +6122,7 @@ void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen,
|
||||||
// end-of-sweep-census below will be off by a little bit.
|
// end-of-sweep-census below will be off by a little bit.
|
||||||
}
|
}
|
||||||
gen->cmsSpace()->sweep_completed();
|
gen->cmsSpace()->sweep_completed();
|
||||||
gen->cmsSpace()->endSweepFLCensus(sweepCount());
|
gen->cmsSpace()->endSweepFLCensus(sweep_count());
|
||||||
if (should_unload_classes()) { // unloaded classes this cycle,
|
if (should_unload_classes()) { // unloaded classes this cycle,
|
||||||
_concurrent_cycles_since_last_unload = 0; // ... reset count
|
_concurrent_cycles_since_last_unload = 0; // ... reset count
|
||||||
} else { // did not unload classes,
|
} else { // did not unload classes,
|
||||||
|
|
|
@ -355,6 +355,11 @@ class CMSStats VALUE_OBJ_CLASS_SPEC {
|
||||||
unsigned int new_duty_cycle);
|
unsigned int new_duty_cycle);
|
||||||
unsigned int icms_update_duty_cycle_impl();
|
unsigned int icms_update_duty_cycle_impl();
|
||||||
|
|
||||||
|
// In support of adjusting of cms trigger ratios based on history
|
||||||
|
// of concurrent mode failure.
|
||||||
|
double cms_free_adjustment_factor(size_t free) const;
|
||||||
|
void adjust_cms_free_adjustment_factor(bool fail, size_t free);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMSStats(ConcurrentMarkSweepGeneration* cms_gen,
|
CMSStats(ConcurrentMarkSweepGeneration* cms_gen,
|
||||||
unsigned int alpha = CMSExpAvgFactor);
|
unsigned int alpha = CMSExpAvgFactor);
|
||||||
|
@ -570,8 +575,11 @@ class CMSCollector: public CHeapObj {
|
||||||
// appropriately.
|
// appropriately.
|
||||||
void check_gc_time_limit();
|
void check_gc_time_limit();
|
||||||
// XXX Move these to CMSStats ??? FIX ME !!!
|
// XXX Move these to CMSStats ??? FIX ME !!!
|
||||||
elapsedTimer _sweep_timer;
|
elapsedTimer _inter_sweep_timer; // time between sweeps
|
||||||
AdaptivePaddedAverage _sweep_estimate;
|
elapsedTimer _intra_sweep_timer; // time _in_ sweeps
|
||||||
|
// padded decaying average estimates of the above
|
||||||
|
AdaptivePaddedAverage _inter_sweep_estimate;
|
||||||
|
AdaptivePaddedAverage _intra_sweep_estimate;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConcurrentMarkSweepGeneration* _cmsGen; // old gen (CMS)
|
ConcurrentMarkSweepGeneration* _cmsGen; // old gen (CMS)
|
||||||
|
@ -625,6 +633,7 @@ class CMSCollector: public CHeapObj {
|
||||||
// . _collectorState <= Idling == post-sweep && pre-mark
|
// . _collectorState <= Idling == post-sweep && pre-mark
|
||||||
// . _collectorState in (Idling, Sweeping) == {initial,final}marking ||
|
// . _collectorState in (Idling, Sweeping) == {initial,final}marking ||
|
||||||
// precleaning || abortablePrecleanb
|
// precleaning || abortablePrecleanb
|
||||||
|
public:
|
||||||
enum CollectorState {
|
enum CollectorState {
|
||||||
Resizing = 0,
|
Resizing = 0,
|
||||||
Resetting = 1,
|
Resetting = 1,
|
||||||
|
@ -636,6 +645,7 @@ class CMSCollector: public CHeapObj {
|
||||||
FinalMarking = 7,
|
FinalMarking = 7,
|
||||||
Sweeping = 8
|
Sweeping = 8
|
||||||
};
|
};
|
||||||
|
protected:
|
||||||
static CollectorState _collectorState;
|
static CollectorState _collectorState;
|
||||||
|
|
||||||
// State related to prologue/epilogue invocation for my generations
|
// State related to prologue/epilogue invocation for my generations
|
||||||
|
@ -655,7 +665,7 @@ class CMSCollector: public CHeapObj {
|
||||||
|
|
||||||
int _numYields;
|
int _numYields;
|
||||||
size_t _numDirtyCards;
|
size_t _numDirtyCards;
|
||||||
uint _sweepCount;
|
size_t _sweep_count;
|
||||||
// number of full gc's since the last concurrent gc.
|
// number of full gc's since the last concurrent gc.
|
||||||
uint _full_gcs_since_conc_gc;
|
uint _full_gcs_since_conc_gc;
|
||||||
|
|
||||||
|
@ -905,7 +915,7 @@ class CMSCollector: public CHeapObj {
|
||||||
|
|
||||||
// Check that the currently executing thread is the expected
|
// Check that the currently executing thread is the expected
|
||||||
// one (foreground collector or background collector).
|
// one (foreground collector or background collector).
|
||||||
void check_correct_thread_executing() PRODUCT_RETURN;
|
static void check_correct_thread_executing() PRODUCT_RETURN;
|
||||||
// XXXPERM void print_statistics() PRODUCT_RETURN;
|
// XXXPERM void print_statistics() PRODUCT_RETURN;
|
||||||
|
|
||||||
bool is_cms_reachable(HeapWord* addr);
|
bool is_cms_reachable(HeapWord* addr);
|
||||||
|
@ -930,8 +940,8 @@ class CMSCollector: public CHeapObj {
|
||||||
static void set_foregroundGCShouldWait(bool v) { _foregroundGCShouldWait = v; }
|
static void set_foregroundGCShouldWait(bool v) { _foregroundGCShouldWait = v; }
|
||||||
static bool foregroundGCIsActive() { return _foregroundGCIsActive; }
|
static bool foregroundGCIsActive() { return _foregroundGCIsActive; }
|
||||||
static void set_foregroundGCIsActive(bool v) { _foregroundGCIsActive = v; }
|
static void set_foregroundGCIsActive(bool v) { _foregroundGCIsActive = v; }
|
||||||
uint sweepCount() const { return _sweepCount; }
|
size_t sweep_count() const { return _sweep_count; }
|
||||||
void incrementSweepCount() { _sweepCount++; }
|
void increment_sweep_count() { _sweep_count++; }
|
||||||
|
|
||||||
// Timers/stats for gc scheduling and incremental mode pacing.
|
// Timers/stats for gc scheduling and incremental mode pacing.
|
||||||
CMSStats& stats() { return _stats; }
|
CMSStats& stats() { return _stats; }
|
||||||
|
@ -1165,6 +1175,11 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||||
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
|
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
|
||||||
bool younger_handles_promotion_failure) const;
|
bool younger_handles_promotion_failure) const;
|
||||||
|
|
||||||
|
// Inform this (non-young) generation that a promotion failure was
|
||||||
|
// encountered during a collection of a younger generation that
|
||||||
|
// promotes into this generation.
|
||||||
|
virtual void promotion_failure_occurred();
|
||||||
|
|
||||||
bool should_collect(bool full, size_t size, bool tlab);
|
bool should_collect(bool full, size_t size, bool tlab);
|
||||||
virtual bool should_concurrent_collect() const;
|
virtual bool should_concurrent_collect() const;
|
||||||
virtual bool is_too_full() const;
|
virtual bool is_too_full() const;
|
||||||
|
|
|
@ -55,7 +55,8 @@ class FreeBlockDictionary: public CHeapObj {
|
||||||
virtual void dictCensusUpdate(size_t size, bool split, bool birth) = 0;
|
virtual void dictCensusUpdate(size_t size, bool split, bool birth) = 0;
|
||||||
virtual bool coalDictOverPopulated(size_t size) = 0;
|
virtual bool coalDictOverPopulated(size_t size) = 0;
|
||||||
virtual void beginSweepDictCensus(double coalSurplusPercent,
|
virtual void beginSweepDictCensus(double coalSurplusPercent,
|
||||||
float sweep_current, float sweep_ewstimate) = 0;
|
float inter_sweep_current, float inter_sweep_estimate,
|
||||||
|
float intra__sweep_current) = 0;
|
||||||
virtual void endSweepDictCensus(double splitSurplusPercent) = 0;
|
virtual void endSweepDictCensus(double splitSurplusPercent) = 0;
|
||||||
virtual FreeChunk* findLargestDict() const = 0;
|
virtual FreeChunk* findLargestDict() const = 0;
|
||||||
// verify that the given chunk is in the dictionary.
|
// verify that the given chunk is in the dictionary.
|
||||||
|
@ -79,6 +80,7 @@ class FreeBlockDictionary: public CHeapObj {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void printDictCensus() const = 0;
|
virtual void printDictCensus() const = 0;
|
||||||
|
virtual void print_free_lists(outputStream* st) const = 0;
|
||||||
|
|
||||||
virtual void verify() const = 0;
|
virtual void verify() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -67,3 +67,8 @@ void FreeChunk::verifyList() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void FreeChunk::print_on(outputStream* st) {
|
||||||
|
st->print_cr("Next: " PTR_FORMAT " Prev: " PTR_FORMAT " %s",
|
||||||
|
next(), prev(), cantCoalesce() ? "[can't coalesce]" : "");
|
||||||
|
}
|
||||||
|
|
|
@ -129,6 +129,8 @@ class FreeChunk VALUE_OBJ_CLASS_SPEC {
|
||||||
void verifyList() const PRODUCT_RETURN;
|
void verifyList() const PRODUCT_RETURN;
|
||||||
void mangleAllocated(size_t size) PRODUCT_RETURN;
|
void mangleAllocated(size_t size) PRODUCT_RETURN;
|
||||||
void mangleFreed(size_t size) PRODUCT_RETURN;
|
void mangleFreed(size_t size) PRODUCT_RETURN;
|
||||||
|
|
||||||
|
void print_on(outputStream* st);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Alignment helpers etc.
|
// Alignment helpers etc.
|
||||||
|
|
|
@ -81,8 +81,8 @@ void FreeList::reset(size_t hint) {
|
||||||
set_hint(hint);
|
set_hint(hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeList::init_statistics() {
|
void FreeList::init_statistics(bool split_birth) {
|
||||||
_allocation_stats.initialize();
|
_allocation_stats.initialize(split_birth);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeChunk* FreeList::getChunkAtHead() {
|
FreeChunk* FreeList::getChunkAtHead() {
|
||||||
|
@ -292,14 +292,31 @@ bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void FreeList::assert_proper_lock_protection_work() const {
|
void FreeList::verify_stats() const {
|
||||||
#ifdef ASSERT
|
// The +1 of the LH comparand is to allow some "looseness" in
|
||||||
if (_protecting_lock != NULL &&
|
// checking: we usually call this interface when adding a block
|
||||||
SharedHeap::heap()->n_par_threads() > 0) {
|
// and we'll subsequently update the stats; we cannot update the
|
||||||
// Should become an assert.
|
// stats beforehand because in the case of the large-block BT
|
||||||
guarantee(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
|
// dictionary for example, this might be the first block and
|
||||||
|
// in that case there would be no place that we could record
|
||||||
|
// the stats (which are kept in the block itself).
|
||||||
|
assert(_allocation_stats.prevSweep() + _allocation_stats.splitBirths() + 1 // Total Stock + 1
|
||||||
|
>= _allocation_stats.splitDeaths() + (ssize_t)count(), "Conservation Principle");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeList::assert_proper_lock_protection_work() const {
|
||||||
|
assert(_protecting_lock != NULL, "Don't call this directly");
|
||||||
|
assert(ParallelGCThreads > 0, "Don't call this directly");
|
||||||
|
Thread* thr = Thread::current();
|
||||||
|
if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
|
||||||
|
// assert that we are holding the freelist lock
|
||||||
|
} else if (thr->is_GC_task_thread()) {
|
||||||
|
assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
|
||||||
|
} else if (thr->is_Java_thread()) {
|
||||||
|
assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
|
||||||
|
} else {
|
||||||
|
ShouldNotReachHere(); // unaccounted thread type?
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -35,18 +35,26 @@ class CompactibleFreeListSpace;
|
||||||
// for that implementation.
|
// for that implementation.
|
||||||
|
|
||||||
class Mutex;
|
class Mutex;
|
||||||
|
class TreeList;
|
||||||
|
|
||||||
class FreeList VALUE_OBJ_CLASS_SPEC {
|
class FreeList VALUE_OBJ_CLASS_SPEC {
|
||||||
friend class CompactibleFreeListSpace;
|
friend class CompactibleFreeListSpace;
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class printTreeCensusClosure;
|
friend class PrintTreeCensusClosure;
|
||||||
FreeChunk* _head; // List of free chunks
|
|
||||||
|
protected:
|
||||||
|
TreeList* _parent;
|
||||||
|
TreeList* _left;
|
||||||
|
TreeList* _right;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FreeChunk* _head; // Head of list of free chunks
|
||||||
FreeChunk* _tail; // Tail of list of free chunks
|
FreeChunk* _tail; // Tail of list of free chunks
|
||||||
size_t _size; // Size in Heap words of each chunks
|
size_t _size; // Size in Heap words of each chunk
|
||||||
ssize_t _count; // Number of entries in list
|
ssize_t _count; // Number of entries in list
|
||||||
size_t _hint; // next larger size list with a positive surplus
|
size_t _hint; // next larger size list with a positive surplus
|
||||||
|
|
||||||
AllocationStats _allocation_stats; // statistics for smart allocation
|
AllocationStats _allocation_stats; // allocation-related statistics
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
Mutex* _protecting_lock;
|
Mutex* _protecting_lock;
|
||||||
|
@ -63,9 +71,12 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
// Initialize the allocation statistics.
|
// Initialize the allocation statistics.
|
||||||
protected:
|
protected:
|
||||||
void init_statistics();
|
void init_statistics(bool split_birth = false);
|
||||||
void set_count(ssize_t v) { _count = v;}
|
void set_count(ssize_t v) { _count = v;}
|
||||||
void increment_count() { _count++; }
|
void increment_count() {
|
||||||
|
_count++;
|
||||||
|
}
|
||||||
|
|
||||||
void decrement_count() {
|
void decrement_count() {
|
||||||
_count--;
|
_count--;
|
||||||
assert(_count >= 0, "Count should not be negative");
|
assert(_count >= 0, "Count should not be negative");
|
||||||
|
@ -167,11 +178,13 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
||||||
_allocation_stats.set_desired(v);
|
_allocation_stats.set_desired(v);
|
||||||
}
|
}
|
||||||
void compute_desired(float inter_sweep_current,
|
void compute_desired(float inter_sweep_current,
|
||||||
float inter_sweep_estimate) {
|
float inter_sweep_estimate,
|
||||||
|
float intra_sweep_estimate) {
|
||||||
assert_proper_lock_protection();
|
assert_proper_lock_protection();
|
||||||
_allocation_stats.compute_desired(_count,
|
_allocation_stats.compute_desired(_count,
|
||||||
inter_sweep_current,
|
inter_sweep_current,
|
||||||
inter_sweep_estimate);
|
inter_sweep_estimate,
|
||||||
|
intra_sweep_estimate);
|
||||||
}
|
}
|
||||||
ssize_t coalDesired() const {
|
ssize_t coalDesired() const {
|
||||||
return _allocation_stats.coalDesired();
|
return _allocation_stats.coalDesired();
|
||||||
|
@ -306,6 +319,9 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
||||||
// found. Return NULL if "fc" is not found.
|
// found. Return NULL if "fc" is not found.
|
||||||
bool verifyChunkInFreeLists(FreeChunk* fc) const;
|
bool verifyChunkInFreeLists(FreeChunk* fc) const;
|
||||||
|
|
||||||
|
// Stats verification
|
||||||
|
void verify_stats() const PRODUCT_RETURN;
|
||||||
|
|
||||||
// Printing support
|
// Printing support
|
||||||
static void print_labels_on(outputStream* st, const char* c);
|
static void print_labels_on(outputStream* st, const char* c);
|
||||||
void print_on(outputStream* st, const char* c = NULL) const;
|
void print_on(outputStream* st, const char* c = NULL) const;
|
||||||
|
|
|
@ -1441,6 +1441,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||||
}
|
}
|
||||||
|
|
||||||
jint G1CollectedHeap::initialize() {
|
jint G1CollectedHeap::initialize() {
|
||||||
|
CollectedHeap::pre_initialize();
|
||||||
os::enable_vtime();
|
os::enable_vtime();
|
||||||
|
|
||||||
// Necessary to satisfy locking discipline assertions.
|
// Necessary to satisfy locking discipline assertions.
|
||||||
|
|
|
@ -1007,6 +1007,10 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool card_mark_must_follow_store() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_in_young(oop obj) {
|
bool is_in_young(oop obj) {
|
||||||
HeapRegion* hr = heap_region_containing(obj);
|
HeapRegion* hr = heap_region_containing(obj);
|
||||||
return hr != NULL && hr->is_young();
|
return hr != NULL && hr->is_young();
|
||||||
|
|
|
@ -73,7 +73,12 @@ void PtrQueue::enqueue_known_active(void* ptr) {
|
||||||
|
|
||||||
void PtrQueue::locking_enqueue_completed_buffer(void** buf) {
|
void PtrQueue::locking_enqueue_completed_buffer(void** buf) {
|
||||||
assert(_lock->owned_by_self(), "Required.");
|
assert(_lock->owned_by_self(), "Required.");
|
||||||
|
|
||||||
|
// We have to unlock _lock (which may be Shared_DirtyCardQ_lock) before
|
||||||
|
// we acquire DirtyCardQ_CBL_mon inside enqeue_complete_buffer as they
|
||||||
|
// have the same rank and we may get the "possible deadlock" message
|
||||||
_lock->unlock();
|
_lock->unlock();
|
||||||
|
|
||||||
qset()->enqueue_complete_buffer(buf);
|
qset()->enqueue_complete_buffer(buf);
|
||||||
// We must relock only because the caller will unlock, for the normal
|
// We must relock only because the caller will unlock, for the normal
|
||||||
// case.
|
// case.
|
||||||
|
@ -140,7 +145,36 @@ void PtrQueue::handle_zero_index() {
|
||||||
// holding the lock if there is one).
|
// holding the lock if there is one).
|
||||||
if (_buf != NULL) {
|
if (_buf != NULL) {
|
||||||
if (_lock) {
|
if (_lock) {
|
||||||
locking_enqueue_completed_buffer(_buf);
|
assert(_lock->owned_by_self(), "Required.");
|
||||||
|
|
||||||
|
// The current PtrQ may be the shared dirty card queue and
|
||||||
|
// may be being manipulated by more than one worker thread
|
||||||
|
// during a pause. Since the enqueuing of the completed
|
||||||
|
// buffer unlocks the Shared_DirtyCardQ_lock more than one
|
||||||
|
// worker thread can 'race' on reading the shared queue attributes
|
||||||
|
// (_buf and _index) and multiple threads can call into this
|
||||||
|
// routine for the same buffer. This will cause the completed
|
||||||
|
// buffer to be added to the CBL multiple times.
|
||||||
|
|
||||||
|
// We "claim" the current buffer by caching value of _buf in
|
||||||
|
// a local and clearing the field while holding _lock. When
|
||||||
|
// _lock is released (while enqueueing the completed buffer)
|
||||||
|
// the thread that acquires _lock will skip this code,
|
||||||
|
// preventing the subsequent the multiple enqueue, and
|
||||||
|
// install a newly allocated buffer below.
|
||||||
|
|
||||||
|
void** buf = _buf; // local pointer to completed buffer
|
||||||
|
_buf = NULL; // clear shared _buf field
|
||||||
|
|
||||||
|
locking_enqueue_completed_buffer(buf); // enqueue completed buffer
|
||||||
|
|
||||||
|
// While the current thread was enqueuing the buffer another thread
|
||||||
|
// may have a allocated a new buffer and inserted it into this pointer
|
||||||
|
// queue. If that happens then we just return so that the current
|
||||||
|
// thread doesn't overwrite the buffer allocated by the other thread
|
||||||
|
// and potentially losing some dirtied cards.
|
||||||
|
|
||||||
|
if (_buf != NULL) return;
|
||||||
} else {
|
} else {
|
||||||
if (qset()->process_or_enqueue_complete_buffer(_buf)) {
|
if (qset()->process_or_enqueue_complete_buffer(_buf)) {
|
||||||
// Recycle the buffer. No allocation.
|
// Recycle the buffer. No allocation.
|
||||||
|
|
|
@ -221,6 +221,7 @@ freeList.cpp freeList.hpp
|
||||||
freeList.cpp globals.hpp
|
freeList.cpp globals.hpp
|
||||||
freeList.cpp mutex.hpp
|
freeList.cpp mutex.hpp
|
||||||
freeList.cpp sharedHeap.hpp
|
freeList.cpp sharedHeap.hpp
|
||||||
|
freeList.cpp vmThread.hpp
|
||||||
|
|
||||||
freeList.hpp allocationStats.hpp
|
freeList.hpp allocationStats.hpp
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ gcUtil.cpp gcUtil.hpp
|
||||||
gcUtil.hpp allocation.hpp
|
gcUtil.hpp allocation.hpp
|
||||||
gcUtil.hpp debug.hpp
|
gcUtil.hpp debug.hpp
|
||||||
gcUtil.hpp globalDefinitions.hpp
|
gcUtil.hpp globalDefinitions.hpp
|
||||||
|
gcUtil.hpp ostream.hpp
|
||||||
gcUtil.hpp timer.hpp
|
gcUtil.hpp timer.hpp
|
||||||
|
|
||||||
generationCounters.cpp generationCounters.hpp
|
generationCounters.cpp generationCounters.hpp
|
||||||
|
|
|
@ -50,6 +50,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_,
|
||||||
work_queue_set_, &term_),
|
work_queue_set_, &term_),
|
||||||
_is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
|
_is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
|
||||||
_keep_alive_closure(&_scan_weak_ref_closure),
|
_keep_alive_closure(&_scan_weak_ref_closure),
|
||||||
|
_promotion_failure_size(0),
|
||||||
_pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
|
_pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
|
||||||
_strong_roots_time(0.0), _term_time(0.0)
|
_strong_roots_time(0.0), _term_time(0.0)
|
||||||
{
|
{
|
||||||
|
@ -249,6 +250,16 @@ void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParScanThreadState::print_and_clear_promotion_failure_size() {
|
||||||
|
if (_promotion_failure_size != 0) {
|
||||||
|
if (PrintPromotionFailure) {
|
||||||
|
gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
|
||||||
|
_thread_num, _promotion_failure_size);
|
||||||
|
}
|
||||||
|
_promotion_failure_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ParScanThreadStateSet: private ResourceArray {
|
class ParScanThreadStateSet: private ResourceArray {
|
||||||
public:
|
public:
|
||||||
// Initializes states for the specified number of threads;
|
// Initializes states for the specified number of threads;
|
||||||
|
@ -260,11 +271,11 @@ public:
|
||||||
GrowableArray<oop>** overflow_stacks_,
|
GrowableArray<oop>** overflow_stacks_,
|
||||||
size_t desired_plab_sz,
|
size_t desired_plab_sz,
|
||||||
ParallelTaskTerminator& term);
|
ParallelTaskTerminator& term);
|
||||||
inline ParScanThreadState& thread_sate(int i);
|
inline ParScanThreadState& thread_state(int i);
|
||||||
int pushes() { return _pushes; }
|
int pushes() { return _pushes; }
|
||||||
int pops() { return _pops; }
|
int pops() { return _pops; }
|
||||||
int steals() { return _steals; }
|
int steals() { return _steals; }
|
||||||
void reset();
|
void reset(bool promotion_failed);
|
||||||
void flush();
|
void flush();
|
||||||
private:
|
private:
|
||||||
ParallelTaskTerminator& _term;
|
ParallelTaskTerminator& _term;
|
||||||
|
@ -295,22 +306,31 @@ ParScanThreadStateSet::ParScanThreadStateSet(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ParScanThreadState& ParScanThreadStateSet::thread_sate(int i)
|
inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
|
||||||
{
|
{
|
||||||
assert(i >= 0 && i < length(), "sanity check!");
|
assert(i >= 0 && i < length(), "sanity check!");
|
||||||
return ((ParScanThreadState*)_data)[i];
|
return ((ParScanThreadState*)_data)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ParScanThreadStateSet::reset()
|
void ParScanThreadStateSet::reset(bool promotion_failed)
|
||||||
{
|
{
|
||||||
_term.reset_for_reuse();
|
_term.reset_for_reuse();
|
||||||
|
if (promotion_failed) {
|
||||||
|
for (int i = 0; i < length(); ++i) {
|
||||||
|
thread_state(i).print_and_clear_promotion_failure_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParScanThreadStateSet::flush()
|
void ParScanThreadStateSet::flush()
|
||||||
{
|
{
|
||||||
|
// Work in this loop should be kept as lightweight as
|
||||||
|
// possible since this might otherwise become a bottleneck
|
||||||
|
// to scaling. Should we add heavy-weight work into this
|
||||||
|
// loop, consider parallelizing the loop into the worker threads.
|
||||||
for (int i = 0; i < length(); ++i) {
|
for (int i = 0; i < length(); ++i) {
|
||||||
ParScanThreadState& par_scan_state = thread_sate(i);
|
ParScanThreadState& par_scan_state = thread_state(i);
|
||||||
|
|
||||||
// Flush stats related to To-space PLAB activity and
|
// Flush stats related to To-space PLAB activity and
|
||||||
// retire the last buffer.
|
// retire the last buffer.
|
||||||
|
@ -362,6 +382,14 @@ void ParScanThreadStateSet::flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (UseConcMarkSweepGC && ParallelGCThreads > 0) {
|
||||||
|
// We need to call this even when ResizeOldPLAB is disabled
|
||||||
|
// so as to avoid breaking some asserts. While we may be able
|
||||||
|
// to avoid this by reorganizing the code a bit, I am loathe
|
||||||
|
// to do that unless we find cases where ergo leads to bad
|
||||||
|
// performance.
|
||||||
|
CFLS_LAB::compute_desired_plab_size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ParScanClosure::ParScanClosure(ParNewGeneration* g,
|
ParScanClosure::ParScanClosure(ParNewGeneration* g,
|
||||||
|
@ -475,7 +503,7 @@ void ParNewGenTask::work(int i) {
|
||||||
|
|
||||||
Generation* old_gen = gch->next_gen(_gen);
|
Generation* old_gen = gch->next_gen(_gen);
|
||||||
|
|
||||||
ParScanThreadState& par_scan_state = _state_set->thread_sate(i);
|
ParScanThreadState& par_scan_state = _state_set->thread_state(i);
|
||||||
par_scan_state.set_young_old_boundary(_young_old_boundary);
|
par_scan_state.set_young_old_boundary(_young_old_boundary);
|
||||||
|
|
||||||
par_scan_state.start_strong_roots();
|
par_scan_state.start_strong_roots();
|
||||||
|
@ -659,7 +687,7 @@ void ParNewRefProcTaskProxy::work(int i)
|
||||||
{
|
{
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
ParScanThreadState& par_scan_state = _state_set.thread_sate(i);
|
ParScanThreadState& par_scan_state = _state_set.thread_state(i);
|
||||||
par_scan_state.set_young_old_boundary(_young_old_boundary);
|
par_scan_state.set_young_old_boundary(_young_old_boundary);
|
||||||
_task.work(i, par_scan_state.is_alive_closure(),
|
_task.work(i, par_scan_state.is_alive_closure(),
|
||||||
par_scan_state.keep_alive_closure(),
|
par_scan_state.keep_alive_closure(),
|
||||||
|
@ -693,7 +721,7 @@ void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
|
||||||
ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
|
ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
|
||||||
_generation.reserved().end(), _state_set);
|
_generation.reserved().end(), _state_set);
|
||||||
workers->run_task(&rp_task);
|
workers->run_task(&rp_task);
|
||||||
_state_set.reset();
|
_state_set.reset(_generation.promotion_failed());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
|
void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
|
||||||
|
@ -813,7 +841,7 @@ void ParNewGeneration::collect(bool full,
|
||||||
GenCollectedHeap::StrongRootsScope srs(gch);
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
tsk.work(0);
|
tsk.work(0);
|
||||||
}
|
}
|
||||||
thread_state_set.reset();
|
thread_state_set.reset(promotion_failed());
|
||||||
|
|
||||||
if (PAR_STATS_ENABLED && ParallelGCVerbose) {
|
if (PAR_STATS_ENABLED && ParallelGCVerbose) {
|
||||||
gclog_or_tty->print("Thread totals:\n"
|
gclog_or_tty->print("Thread totals:\n"
|
||||||
|
@ -882,6 +910,8 @@ void ParNewGeneration::collect(bool full,
|
||||||
swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
|
swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
|
||||||
from()->set_next_compaction_space(to());
|
from()->set_next_compaction_space(to());
|
||||||
gch->set_incremental_collection_will_fail();
|
gch->set_incremental_collection_will_fail();
|
||||||
|
// Inform the next generation that a promotion failure occurred.
|
||||||
|
_next_gen->promotion_failure_occurred();
|
||||||
|
|
||||||
// Reset the PromotionFailureALot counters.
|
// Reset the PromotionFailureALot counters.
|
||||||
NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
|
NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
|
||||||
|
@ -1029,6 +1059,8 @@ oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo(
|
||||||
new_obj = old;
|
new_obj = old;
|
||||||
|
|
||||||
preserve_mark_if_necessary(old, m);
|
preserve_mark_if_necessary(old, m);
|
||||||
|
// Log the size of the maiden promotion failure
|
||||||
|
par_scan_state->log_promotion_failure(sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
old->forward_to(new_obj);
|
old->forward_to(new_obj);
|
||||||
|
@ -1150,6 +1182,8 @@ oop ParNewGeneration::copy_to_survivor_space_with_undo(
|
||||||
failed_to_promote = true;
|
failed_to_promote = true;
|
||||||
|
|
||||||
preserve_mark_if_necessary(old, m);
|
preserve_mark_if_necessary(old, m);
|
||||||
|
// Log the size of the maiden promotion failure
|
||||||
|
par_scan_state->log_promotion_failure(sz);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Is in to-space; do copying ourselves.
|
// Is in to-space; do copying ourselves.
|
||||||
|
|
|
@ -97,6 +97,9 @@ class ParScanThreadState {
|
||||||
int _pushes, _pops, _steals, _steal_attempts, _term_attempts;
|
int _pushes, _pops, _steals, _steal_attempts, _term_attempts;
|
||||||
int _overflow_pushes, _overflow_refills, _overflow_refill_objs;
|
int _overflow_pushes, _overflow_refills, _overflow_refill_objs;
|
||||||
|
|
||||||
|
// Stats for promotion failure
|
||||||
|
size_t _promotion_failure_size;
|
||||||
|
|
||||||
// Timing numbers.
|
// Timing numbers.
|
||||||
double _start;
|
double _start;
|
||||||
double _start_strong_roots;
|
double _start_strong_roots;
|
||||||
|
@ -169,6 +172,15 @@ class ParScanThreadState {
|
||||||
// Undo the most recent allocation ("obj", of "word_sz").
|
// Undo the most recent allocation ("obj", of "word_sz").
|
||||||
void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz);
|
void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz);
|
||||||
|
|
||||||
|
// Promotion failure stats
|
||||||
|
size_t promotion_failure_size() { return promotion_failure_size(); }
|
||||||
|
void log_promotion_failure(size_t sz) {
|
||||||
|
if (_promotion_failure_size == 0) {
|
||||||
|
_promotion_failure_size = sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void print_and_clear_promotion_failure_size();
|
||||||
|
|
||||||
int pushes() { return _pushes; }
|
int pushes() { return _pushes; }
|
||||||
int pops() { return _pops; }
|
int pops() { return _pops; }
|
||||||
int steals() { return _steals; }
|
int steals() { return _steals; }
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue