This commit is contained in:
Lana Steuck 2012-07-27 22:26:19 -07:00
commit 44ce09ba1f
105 changed files with 3458 additions and 1838 deletions

View File

@ -169,3 +169,5 @@ c029c972396cea042a0dc67c0f7ccf2fe68007d4 jdk8-b41
9b19b2302c28f4da6d4078f66234abecfed5688a jdk8-b45
600c9a1feb01633cbcf2341a43d1d21e6497ecd0 jdk8-b46
b820143a6f1ce993c6e6f31db4d64de990f42654 jdk8-b47
086271e35b0a419b38e8bda9bebd70693811df0a jdk8-b48
cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49

View File

@ -169,3 +169,5 @@ e4f81a817447c3a4f6868f083c81c2fb1b15d44c jdk8-b44
633f2378c904c92bb922a6e19e9f62fe8eac14af jdk8-b45
27fa766a2298ba8347dc198f0cf85ba6618e17db jdk8-b46
1dcb4b7b9373e64e135c12fe1f8699f1f80e51e8 jdk8-b47
3f6c72d1c2a6e5c9e7d81c3dc984886678a128ad jdk8-b48
c97b99424815c43818e3cc3ffcdd1a60f3198b52 jdk8-b49

View File

@ -3383,3 +3383,397 @@ included with JRE 7, JDK 7, and OpenJDK 7, except where noted:
-------------------------------------------------------------------------------
%% This notice is provided with respect to Mozilla Network Security
Services (NSS), which is supplied with the JDK test suite in the OpenJDK
source code repository. It is licensed under Mozilla Public License (MPL),
version 2.0.
The NSS libraries are supplied in executable form, built from unmodified
NSS source code labeled with the "NSS_3.13.1_RTM" release tag.
The NSS source code is available in the OpenJDK source code repository at:
jdk/test/sun/security/pkcs11/nss/src
The NSS libraries are available in the OpenJDK source code repository at:
jdk/test/sun/security/pkcs11/nss/lib
--- begin of LICENSE ---
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
--- end of LICENSE ---
-------------------------------------------------------------------------------

View File

@ -169,3 +169,5 @@ cd879aff5d3cc1f58829aab3116880aa19525b78 jdk8-b43
747dad9e9d37d244a5c765a1afe9194f7ddae118 jdk8-b45
30141e598d72a6146126cb86b034ed6d0bd191b3 jdk8-b46
21e46ea21c6a26246fb7a1926ac7fe8d580d0518 jdk8-b47
7e2b179a5b4dbd3f097e28daa00abfcc72ba3e0b jdk8-b48
fe44e58a6bdbeae350ce96aafb49770a5dca5d8a jdk8-b49

View File

@ -261,3 +261,7 @@ e77b8e0ed1f84e3e268239e276c7ab64fa573baa jdk8-b43
cf37a594c38db2ea926954154636f9f81da2e032 jdk8-b46
0c7bb1f4f9c8062b5c5bfa56b3bdca44839b4109 jdk8-b47
66b0450071c1534e014b131892cc86b63f1d009c hs24-b16
1e26f61bbb521642639f56fae11326f1932f5a7d jdk8-b48
bd54fe36b5e50f9ef1e30a5047b27fee5297e268 hs24-b17
e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49
72e0362c3f0cfacbbac8af8a5b9d2e182f21c17b hs24-b18

View File

@ -47,14 +47,11 @@ public class ConstMethod extends Oop {
private static int HAS_LINENUMBER_TABLE;
private static int HAS_CHECKED_EXCEPTIONS;
private static int HAS_LOCALVARIABLE_TABLE;
private static int HAS_EXCEPTION_TABLE;
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("constMethodOopDesc");
constants = new OopField(type.getOopField("_constants"), 0);
// The exception handler table. 4-tuples of ints [start_pc, end_pc,
// handler_pc, catch_type index] For methods with no exceptions the
// table is pointing to Universe::the_empty_int_array
exceptionTable = new OopField(type.getOopField("_exception_table"), 0);
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
flags = new ByteField(type.getJByteField("_flags"), 0);
@ -62,6 +59,7 @@ public class ConstMethod extends Oop {
HAS_LINENUMBER_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_linenumber_table").intValue();
HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("constMethodOopDesc::_has_checked_exceptions").intValue();
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_localvariable_table").intValue();
HAS_EXCEPTION_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_exception_table").intValue();
// Size of Java bytecodes allocated immediately after constMethodOop.
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
@ -78,6 +76,9 @@ public class ConstMethod extends Oop {
type = db.lookupType("LocalVariableTableElement");
localVariableTableElementSize = type.getSize();
type = db.lookupType("ExceptionTableElement");
exceptionTableElementSize = type.getSize();
}
ConstMethod(OopHandle handle, ObjectHeap heap) {
@ -86,7 +87,6 @@ public class ConstMethod extends Oop {
// Fields
private static OopField constants;
private static OopField exceptionTable;
private static CIntField constMethodSize;
private static ByteField flags;
private static CIntField codeSize;
@ -100,6 +100,7 @@ public class ConstMethod extends Oop {
private static long checkedExceptionElementSize;
private static long localVariableTableElementSize;
private static long exceptionTableElementSize;
public Method getMethod() {
InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder();
@ -112,10 +113,6 @@ public class ConstMethod extends Oop {
return (ConstantPool) constants.getValue(this);
}
public TypeArray getExceptionTable() {
return (TypeArray) exceptionTable.getValue(this);
}
public long getConstMethodSize() {
return constMethodSize.getValue(this);
}
@ -235,7 +232,6 @@ public class ConstMethod extends Oop {
super.iterateFields(visitor, doVMFields);
if (doVMFields) {
visitor.doOop(constants, true);
visitor.doOop(exceptionTable, true);
visitor.doCInt(constMethodSize, true);
visitor.doByte(flags, true);
visitor.doCInt(codeSize, true);
@ -326,6 +322,23 @@ public class ConstMethod extends Oop {
return ret;
}
public boolean hasExceptionTable() {
return (getFlags() & HAS_EXCEPTION_TABLE) != 0;
}
public ExceptionTableElement[] getExceptionTable() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(hasExceptionTable(), "should only be called if table is present");
}
ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()];
long offset = offsetOfExceptionTable();
for (int i = 0; i < ret.length; i++) {
ret[i] = new ExceptionTableElement(getHandle(), offset);
offset += exceptionTableElementSize;
}
return ret;
}
public boolean hasCheckedExceptions() {
return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0;
}
@ -415,7 +428,10 @@ public class ConstMethod extends Oop {
if (Assert.ASSERTS_ENABLED) {
Assert.that(hasLocalVariableTable(), "should only be called if table is present");
}
if (hasCheckedExceptions()) {
if (hasExceptionTable()) {
return offsetOfExceptionTable() - 2;
} else if (hasCheckedExceptions()) {
return offsetOfCheckedExceptions() - 2;
} else {
return offsetOfLastU2Element();
@ -432,4 +448,33 @@ public class ConstMethod extends Oop {
return offset;
}
private int getExceptionTableLength() {
if (hasExceptionTable()) {
return (int) getHandle().getCIntegerAt(offsetOfExceptionTableLength(), 2, true);
} else {
return 0;
}
}
private long offsetOfExceptionTableLength() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(hasExceptionTable(), "should only be called if table is present");
}
if (hasCheckedExceptions()) {
return offsetOfCheckedExceptions() - 2;
} else {
return offsetOfLastU2Element();
}
}
private long offsetOfExceptionTable() {
long offset = offsetOfExceptionTableLength();
long length = getExceptionTableLength();
if (Assert.ASSERTS_ENABLED) {
Assert.that(length > 0, "should only be called if table is present");
}
offset -= length * exceptionTableElementSize;
return offset;
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.oops;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
public class ExceptionTableElement {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ExceptionTableElement");
offsetOfStartPC = type.getCIntegerField("start_pc").getOffset();
offsetOfEndPC = type.getCIntegerField("end_pc").getOffset();
offsetOfHandlerPC = type.getCIntegerField("handler_pc").getOffset();
offsetOfCatchTypeIndex = type.getCIntegerField("catch_type_index").getOffset();
}
private static long offsetOfStartPC;
private static long offsetOfEndPC;
private static long offsetOfHandlerPC;
private static long offsetOfCatchTypeIndex;
private OopHandle handle;
private long offset;
public ExceptionTableElement(OopHandle handle, long offset) {
this.handle = handle;
this.offset = offset;
}
public int getStartPC() {
return (int) handle.getCIntegerAt(offset + offsetOfStartPC, 2, true);
}
public int getEndPC() {
return (int) handle.getCIntegerAt(offset + offsetOfEndPC, 2, true);
}
public int getHandlerPC() {
return (int) handle.getCIntegerAt(offset + offsetOfHandlerPC, 2, true);
}
public int getCatchTypeIndex() {
return (int) handle.getCIntegerAt(offset + offsetOfCatchTypeIndex, 2, true);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -651,10 +651,11 @@ public class GenerateOopMap {
boolean fellThrough = false; // False to get first BB marked.
// First mark all exception handlers as start of a basic-block
TypeArray excps = method().getExceptionTable();
for(int i = 0; i < excps.getLength(); i += 4) {
int handler_pc_idx = i+2;
markBB(excps.getIntAt(handler_pc_idx), null);
if (method().hasExceptionTable()) {
ExceptionTableElement[] excps = method().getExceptionTable();
for(int i = 0; i < excps.length; i++) {
markBB(excps[i].getHandlerPC(), null);
}
}
// Then iterate through the code
@ -891,14 +892,15 @@ public class GenerateOopMap {
// Mark entry basic block as alive and all exception handlers
_basic_blocks[0].markAsAlive();
TypeArray excps = method().getExceptionTable();
for(int i = 0; i < excps.getLength(); i += 4) {
int handler_pc_idx = i+2;
BasicBlock bb = getBasicBlockAt(excps.getIntAt(handler_pc_idx));
// If block is not already alive (due to multiple exception handlers to same bb), then
// make it alive
if (bb.isDead())
bb.markAsAlive();
if (method().hasExceptionTable()) {
ExceptionTableElement[] excps = method().getExceptionTable();
for(int i = 0; i < excps.length; i ++) {
BasicBlock bb = getBasicBlockAt(excps[i].getHandlerPC());
// If block is not already alive (due to multiple exception handlers to same bb), then
// make it alive
if (bb.isDead())
bb.markAsAlive();
}
}
BytecodeStream bcs = new BytecodeStream(_method);
@ -1468,12 +1470,12 @@ public class GenerateOopMap {
if (_has_exceptions) {
int bci = itr.bci();
TypeArray exct = method().getExceptionTable();
for(int i = 0; i< exct.getLength(); i+=4) {
int start_pc = exct.getIntAt(i);
int end_pc = exct.getIntAt(i+1);
int handler_pc = exct.getIntAt(i+2);
int catch_type = exct.getIntAt(i+3);
ExceptionTableElement[] exct = method().getExceptionTable();
for(int i = 0; i< exct.length; i++) {
int start_pc = exct[i].getStartPC();
int end_pc = exct[i].getEndPC();
int handler_pc = exct[i].getHandlerPC();
int catch_type = exct[i].getCatchTypeIndex();
if (start_pc <= bci && bci < end_pc) {
BasicBlock excBB = getBasicBlockAt(handler_pc);
@ -2151,7 +2153,7 @@ public class GenerateOopMap {
_conflict = false;
_max_locals = (int) method().getMaxLocals();
_max_stack = (int) method().getMaxStack();
_has_exceptions = (method().getExceptionTable().getLength() > 0);
_has_exceptions = (method().hasExceptionTable());
_nof_refval_conflicts = 0;
_init_vars = new ArrayList(5); // There are seldom more than 5 init_vars
_report_result = false;

View File

@ -127,7 +127,6 @@ public class Method extends Oop {
return getConstMethod().getConstants();
}
public MethodData getMethodData() { return (MethodData) methodData.getValue(this); }
public TypeArray getExceptionTable() { return getConstMethod().getExceptionTable(); }
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
public long getMethodSize() { return methodSize.getValue(this); }
public long getMaxStack() { return maxStack.getValue(this); }
@ -328,6 +327,14 @@ public class Method extends Oop {
return null;
}
public boolean hasExceptionTable() {
return getConstMethod().hasExceptionTable();
}
public ExceptionTableElement[] getExceptionTable() {
return getConstMethod().getExceptionTable();
}
public boolean hasCheckedExceptions() {
return getConstMethod().hasCheckedExceptions();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -504,11 +504,14 @@ public class ClassWriter implements /* imports */ ClassConstants
2 /* exp. table len. */ +
2 /* code attr. count */;
TypeArray exceptionTable = m.getExceptionTable();
final int exceptionTableLen = (int) exceptionTable.getLength();
if (exceptionTableLen != 0) {
boolean hasExceptionTable = m.hasExceptionTable();
ExceptionTableElement[] exceptionTable = null;
int exceptionTableLen = 0;
if (hasExceptionTable) {
exceptionTable = m.getExceptionTable();
exceptionTableLen = exceptionTable.length;
if (DEBUG) debugMessage("\tmethod has exception table");
codeSize += (exceptionTableLen / 4) /* exception table is 4-tuple array */
codeSize += exceptionTableLen /* exception table is 4-tuple array */
* (2 /* start_pc */ +
2 /* end_pc */ +
2 /* handler_pc */ +
@ -586,15 +589,15 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.write(code);
// write exception table size
dos.writeShort((short) (exceptionTableLen / 4));
if (DEBUG) debugMessage("\texception table length = " + (exceptionTableLen / 4));
dos.writeShort((short) exceptionTableLen);
if (DEBUG) debugMessage("\texception table length = " + exceptionTableLen);
if (exceptionTableLen != 0) {
for (int e = 0; e < exceptionTableLen; e += 4) {
dos.writeShort((short) exceptionTable.getIntAt(e));
dos.writeShort((short) exceptionTable.getIntAt(e + 1));
dos.writeShort((short) exceptionTable.getIntAt(e + 2));
dos.writeShort((short) exceptionTable.getIntAt(e + 3));
for (int e = 0; e < exceptionTableLen; e++) {
dos.writeShort((short) exceptionTable[e].getStartPC());
dos.writeShort((short) exceptionTable[e].getEndPC());
dos.writeShort((short) exceptionTable[e].getHandlerPC());
dos.writeShort((short) exceptionTable[e].getCatchTypeIndex());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -783,37 +783,39 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
});
// display exception table for this method
TypeArray exceptionTable = method.getExceptionTable();
// exception table is 4 tuple array of shorts
int numEntries = (int)exceptionTable.getLength() / 4;
if (numEntries != 0) {
buf.h4("Exception Table");
buf.beginTable(1);
buf.beginTag("tr");
buf.headerCell("start bci");
buf.headerCell("end bci");
buf.headerCell("handler bci");
buf.headerCell("catch type");
buf.endTag("tr");
for (int e = 0; e < numEntries; e += 4) {
boolean hasException = method.hasExceptionTable();
if (hasException) {
ExceptionTableElement[] exceptionTable = method.getExceptionTable();
int numEntries = exceptionTable.length;
if (numEntries != 0) {
buf.h4("Exception Table");
buf.beginTable(1);
buf.beginTag("tr");
buf.cell(Integer.toString(exceptionTable.getIntAt(e)));
buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1)));
buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2)));
short cpIndex = (short) exceptionTable.getIntAt(e + 3);
ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex);
if (obj == null) {
buf.cell("Any");
} else if (obj.isMetaData()) {
buf.cell(obj.getSymbol().asString().replace('/', '.'));
} else {
buf.cell(genKlassLink((InstanceKlass)obj.getOop()));
}
buf.headerCell("start bci");
buf.headerCell("end bci");
buf.headerCell("handler bci");
buf.headerCell("catch type");
buf.endTag("tr");
}
buf.endTable();
for (int e = 0; e < numEntries; e ++) {
buf.beginTag("tr");
buf.cell(Integer.toString(exceptionTable[e].getStartPC()));
buf.cell(Integer.toString(exceptionTable[e].getEndPC()));
buf.cell(Integer.toString(exceptionTable[e].getHandlerPC()));
short cpIndex = (short) exceptionTable[e].getCatchTypeIndex();
ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex);
if (obj == null) {
buf.cell("Any");
} else if (obj.isMetaData()) {
buf.cell(obj.getSymbol().asString().replace('/', '.'));
} else {
buf.cell(genKlassLink((InstanceKlass)obj.getOop()));
}
buf.endTag("tr");
}
buf.endTable();
}
}
// display constant pool hyperlink

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
HS_MAJOR_VER=24
HS_MINOR_VER=0
HS_BUILD_NUMBER=16
HS_BUILD_NUMBER=18
JDK_MAJOR_VER=1
JDK_MINOR_VER=8

View File

@ -36,6 +36,11 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
ifeq ("${Platform_compiler}", "sparcWorks")
OPT_CFLAGS/SLOWER = -xO2
ifeq ($(COMPILER_REV_NUMERIC), 510)
# CC 5.10 has bug XXXXX with -xO4
OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/SLOWER)
endif # COMPILER_REV_NUMERIC == 510
ifeq ($(COMPILER_REV_NUMERIC), 509)
# To avoid jvm98 crash
OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER)

View File

@ -32,6 +32,11 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(COMPILER_REV_NUMERIC), 510)
# CC 5.10 has bug XXXXX with -xO4
OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/O2)
endif # COMPILER_REV_NUMERIC == 510
ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
# dtrace cannot handle tail call optimization (6672627, 6693876)
OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT)

View File

@ -40,6 +40,11 @@ endif
# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(COMPILER_REV_NUMERIC), 510)
# CC 5.10 has bug XXXXX with -xO4
OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/O2)
endif # COMPILER_REV_NUMERIC == 510
ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
# dtrace cannot handle tail call optimization (6672627, 6693876)
OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT)

View File

@ -2573,6 +2573,13 @@ void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
emit_byte(0xC0 | encode);
}
void Assembler::punpcklqdq(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66);
emit_byte(0x6C);
emit_byte(0xC0 | encode);
}
void Assembler::push(int32_t imm32) {
// in 64bits we push 64bits onto the stack but only
// take a 32bit immediate
@ -3178,6 +3185,13 @@ void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool v
emit_byte(0xC0 | encode);
}
void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) {
assert(VM_Version::supports_avx2() || (!vector256) && VM_Version::supports_avx(), "");
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256);
emit_byte(0xEF);
emit_byte(0xC0 | encode);
}
void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
bool vector256 = true;
@ -3189,6 +3203,17 @@ void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src)
emit_byte(0x01);
}
void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx2(), "");
bool vector256 = true;
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_3A);
emit_byte(0x38);
emit_byte(0xC0 | encode);
// 0x00 - insert into lower 128 bits
// 0x01 - insert into upper 128 bits
emit_byte(0x01);
}
void Assembler::vzeroupper() {
assert(VM_Version::supports_avx(), "");
(void)vex_prefix_and_encode(xmm0, xmm0, xmm0, VEX_SIMD_NONE);
@ -7480,6 +7505,24 @@ void MacroAssembler::movbyte(ArrayAddress dst, int src) {
movb(as_Address(dst), src);
}
void MacroAssembler::movdl(XMMRegister dst, AddressLiteral src) {
if (reachable(src)) {
movdl(dst, as_Address(src));
} else {
lea(rscratch1, src);
movdl(dst, Address(rscratch1, 0));
}
}
void MacroAssembler::movq(XMMRegister dst, AddressLiteral src) {
if (reachable(src)) {
movq(dst, as_Address(src));
} else {
lea(rscratch1, src);
movq(dst, Address(rscratch1, 0));
}
}
void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) {
if (reachable(src)) {
if (UseXmmLoadAndClearUpper) {

View File

@ -1466,6 +1466,9 @@ private:
void punpckldq(XMMRegister dst, XMMRegister src);
void punpckldq(XMMRegister dst, Address src);
// Interleave Low Quadwords
void punpcklqdq(XMMRegister dst, XMMRegister src);
#ifndef _LP64 // no 32bit push/pop on amd64
void pushl(Address src);
#endif
@ -1606,13 +1609,11 @@ private:
void set_byte_if_not_zero(Register dst); // sets reg to 1 if not zero, otherwise 0
// AVX 3-operands instructions (encoded with VEX prefix)
// AVX 3-operands scalar instructions (encoded with VEX prefix)
void vaddsd(XMMRegister dst, XMMRegister nds, Address src);
void vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vaddss(XMMRegister dst, XMMRegister nds, Address src);
void vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vandpd(XMMRegister dst, XMMRegister nds, Address src);
void vandps(XMMRegister dst, XMMRegister nds, Address src);
void vdivsd(XMMRegister dst, XMMRegister nds, Address src);
void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vdivss(XMMRegister dst, XMMRegister nds, Address src);
@ -1625,13 +1626,17 @@ private:
void vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vsubss(XMMRegister dst, XMMRegister nds, Address src);
void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vxorpd(XMMRegister dst, XMMRegister nds, Address src);
void vxorps(XMMRegister dst, XMMRegister nds, Address src);
// AVX Vector instrucitons.
void vandpd(XMMRegister dst, XMMRegister nds, Address src);
void vandps(XMMRegister dst, XMMRegister nds, Address src);
void vxorpd(XMMRegister dst, XMMRegister nds, Address src);
void vxorps(XMMRegister dst, XMMRegister nds, Address src);
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src);
// AVX instruction which is used to clear upper 128 bits of YMM registers and
// to avoid transaction penalty between AVX and SSE states. There is no
@ -2563,6 +2568,20 @@ public:
void vxorps(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vxorps(dst, nds, src); }
void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) {
if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2
Assembler::vpxor(dst, nds, src, vector256);
else
Assembler::vxorpd(dst, nds, src, vector256);
}
// Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector.
void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
if (UseAVX > 1) // vinserti128h is available only in AVX2
Assembler::vinserti128h(dst, nds, src);
else
Assembler::vinsertf128h(dst, nds, src);
}
// Data
@ -2615,6 +2634,13 @@ public:
// to avoid hiding movb
void movbyte(ArrayAddress dst, int src);
// Import other mov() methods from the parent class or else
// they will be hidden by the following overriding declaration.
using Assembler::movdl;
using Assembler::movq;
void movdl(XMMRegister dst, AddressLiteral src);
void movq(XMMRegister dst, AddressLiteral src);
// Can push value or effective address
void pushptr(AddressLiteral src);

View File

@ -562,7 +562,7 @@ void VM_Version::get_processor_features() {
AllocatePrefetchInstr = 3;
}
// On family 15h processors use XMM and UnalignedLoadStores for Array Copy
if( FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) {
if( supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) {
UseXMMForArrayCopy = true;
}
if( FLAG_IS_DEFAULT(UseUnalignedLoadStores) && UseXMMForArrayCopy ) {

File diff suppressed because it is too large Load Diff

View File

@ -516,7 +516,7 @@ name_for_methodOop(jvm_agent_t* J, uint64_t methodOopPtr, char * result, size_t
err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constMethod, &constMethod);
CHECK_FAIL(err);
err = read_pointer(J->P, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool);
err = read_pointer(J, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool);
CHECK_FAIL(err);
/* To get name string */

View File

@ -3505,8 +3505,10 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBeg
}
// now perform tests that are based on flag settings
if (callee->should_inline()) {
if (callee->force_inline() || callee->should_inline()) {
// ignore heuristic controls on inlining
if (callee->force_inline())
CompileTask::print_inlining(callee, scope()->level(), bci(), "force inline by annotation");
} else {
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining");
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining");
@ -3531,7 +3533,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBeg
}
#ifndef PRODUCT
// printing
// printing
if (PrintInlining) {
print_inline_result(callee, true);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -79,7 +79,7 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
_max_locals = h_m()->max_locals();
_code_size = h_m()->code_size();
_intrinsic_id = h_m()->intrinsic_id();
_handler_count = h_m()->exception_table()->length() / 4;
_handler_count = h_m()->exception_table_length();
_uses_monitors = h_m()->access_flags().has_monitor_bytecodes();
_balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
_is_c1_compilable = !h_m()->is_not_c1_compilable();
@ -198,7 +198,7 @@ void ciMethod::load_code() {
}
// And load the exception table.
typeArrayOop exc_table = me->exception_table();
ExceptionTable exc_table(me);
// Allocate one extra spot in our list of exceptions. This
// last entry will be used to represent the possibility that
@ -209,13 +209,12 @@ void ciMethod::load_code() {
* (_handler_count + 1));
if (_handler_count > 0) {
for (int i=0; i<_handler_count; i++) {
int base = i*4;
_exception_handlers[i] = new (arena) ciExceptionHandler(
holder(),
/* start */ exc_table->int_at(base),
/* limit */ exc_table->int_at(base+1),
/* goto pc */ exc_table->int_at(base+2),
/* cp index */ exc_table->int_at(base+3));
/* start */ exc_table.start_pc(i),
/* limit */ exc_table.end_pc(i),
/* goto pc */ exc_table.handler_pc(i),
/* cp index */ exc_table.catch_type_index(i));
}
}

View File

@ -160,6 +160,8 @@ class ciMethod : public ciObject {
// Code size for inlining decisions.
int code_size_for_inlining();
bool force_inline() { return get_methodOop()->force_inline(); }
int comp_level();
int highest_osr_comp_level();

View File

@ -318,6 +318,13 @@ class ConstantPoolCleaner : public StackObj {
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
if (valid_cp_range(index, cp->length()) && cp->tag_at(index).is_utf8())
return cp->symbol_at(index);
else
return NULL;
}
constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
ClassFileStream* cfs = stream();
constantPoolHandle nullHandle;
@ -902,6 +909,7 @@ void ClassFileParser::parse_field_attributes(constantPoolHandle cp,
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
typeArrayHandle* field_annotations,
ClassFileParser::FieldAnnotationCollector* parsed_annotations,
TRAPS) {
ClassFileStream* cfs = stream();
assert(attributes_count > 0, "length should be greater than 0");
@ -1142,12 +1150,14 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
bool is_synthetic = false;
u2 generic_signature_index = 0;
bool is_static = access_flags.is_static();
FieldAnnotationCollector parsed_annotations;
u2 attributes_count = cfs->get_u2_fast();
if (attributes_count > 0) {
parse_field_attributes(cp, attributes_count, is_static, signature_index,
&constantvalue_index, &is_synthetic,
&generic_signature_index, &field_annotations,
&parsed_annotations,
CHECK_(nullHandle));
if (field_annotations.not_null()) {
if (fields_annotations->is_null()) {
@ -1173,6 +1183,8 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
signature_index,
constantvalue_index,
0);
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(field);
BasicType type = cp->basic_type_for_signature_at(signature_index);
@ -1284,42 +1296,38 @@ static void copy_u2_with_conversion(u2* dest, u2* src, int length) {
}
typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length,
u4 exception_table_length,
constantPoolHandle cp,
TRAPS) {
u2* ClassFileParser::parse_exception_table(u4 code_length,
u4 exception_table_length,
constantPoolHandle cp,
TRAPS) {
ClassFileStream* cfs = stream();
typeArrayHandle nullHandle;
// 4-tuples of ints [start_pc, end_pc, handler_pc, catch_type index]
typeArrayOop eh = oopFactory::new_permanent_intArray(exception_table_length*4, CHECK_(nullHandle));
typeArrayHandle exception_handlers = typeArrayHandle(THREAD, eh);
int index = 0;
cfs->guarantee_more(8 * exception_table_length, CHECK_(nullHandle)); // start_pc, end_pc, handler_pc, catch_type_index
for (unsigned int i = 0; i < exception_table_length; i++) {
u2 start_pc = cfs->get_u2_fast();
u2 end_pc = cfs->get_u2_fast();
u2 handler_pc = cfs->get_u2_fast();
u2 catch_type_index = cfs->get_u2_fast();
// Will check legal target after parsing code array in verifier.
if (_need_verify) {
u2* exception_table_start = cfs->get_u2_buffer();
assert(exception_table_start != NULL, "null exception table");
cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, end_pc, handler_pc, catch_type_index
// Will check legal target after parsing code array in verifier.
if (_need_verify) {
for (unsigned int i = 0; i < exception_table_length; i++) {
u2 start_pc = cfs->get_u2_fast();
u2 end_pc = cfs->get_u2_fast();
u2 handler_pc = cfs->get_u2_fast();
u2 catch_type_index = cfs->get_u2_fast();
guarantee_property((start_pc < end_pc) && (end_pc <= code_length),
"Illegal exception table range in class file %s", CHECK_(nullHandle));
"Illegal exception table range in class file %s",
CHECK_NULL);
guarantee_property(handler_pc < code_length,
"Illegal exception table handler in class file %s", CHECK_(nullHandle));
"Illegal exception table handler in class file %s",
CHECK_NULL);
if (catch_type_index != 0) {
guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
is_klass_reference(cp, catch_type_index),
"Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle));
"Catch type in exception table has bad constant type in class file %s", CHECK_NULL);
}
}
exception_handlers->int_at_put(index++, start_pc);
exception_handlers->int_at_put(index++, end_pc);
exception_handlers->int_at_put(index++, handler_pc);
exception_handlers->int_at_put(index++, catch_type_index);
} else {
cfs->skip_u2_fast(exception_table_length * 4);
}
return exception_handlers;
return exception_table_start;
}
void ClassFileParser::parse_linenumber_table(
@ -1638,12 +1646,158 @@ void ClassFileParser::throwIllegalSignature(
name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
}
// Skip an annotation. Return >=limit if there is any problem.
int ClassFileParser::skip_annotation(u1* buffer, int limit, int index) {
// annotation := atype:u2 do(nmem:u2) {member:u2 value}
// value := switch (tag:u1) { ... }
index += 2; // skip atype
if ((index += 2) >= limit) return limit; // read nmem
int nmem = Bytes::get_Java_u2(buffer+index-2);
while (--nmem >= 0 && index < limit) {
index += 2; // skip member
index = skip_annotation_value(buffer, limit, index);
}
return index;
}
// Skip an annotation value. Return >=limit if there is any problem.
int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
// value := switch (tag:u1) {
// case B, C, I, S, Z, D, F, J, c: con:u2;
// case e: e_class:u2 e_name:u2;
// case s: s_con:u2;
// case [: do(nval:u2) {value};
// case @: annotation;
// case s: s_con:u2;
// }
if ((index += 1) >= limit) return limit; // read tag
u1 tag = buffer[index-1];
switch (tag) {
case 'B': case 'C': case 'I': case 'S': case 'Z':
case 'D': case 'F': case 'J': case 'c': case 's':
index += 2; // skip con or s_con
break;
case 'e':
index += 4; // skip e_class, e_name
break;
case '[':
{
if ((index += 2) >= limit) return limit; // read nval
int nval = Bytes::get_Java_u2(buffer+index-2);
while (--nval >= 0 && index < limit) {
index = skip_annotation_value(buffer, limit, index);
}
}
break;
case '@':
index = skip_annotation(buffer, limit, index);
break;
default:
assert(false, "annotation tag");
return limit; // bad tag byte
}
return index;
}
// Sift through annotations, looking for those significant to the VM:
void ClassFileParser::parse_annotations(u1* buffer, int limit,
constantPoolHandle cp,
ClassFileParser::AnnotationCollector* coll,
TRAPS) {
// annotations := do(nann:u2) {annotation}
int index = 0;
if ((index += 2) >= limit) return; // read nann
int nann = Bytes::get_Java_u2(buffer+index-2);
enum { // initial annotation layout
atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;'
count_off = 2, // u2 such as 1 (one value)
member_off = 4, // utf8 such as 'value'
tag_off = 6, // u1 such as 'c' (type) or 'e' (enum)
e_tag_val = 'e',
e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
e_size = 11, // end of 'e' annotation
c_tag_val = 'c',
c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;'
c_size = 9, // end of 'c' annotation
min_size = 6 // smallest possible size (zero members)
};
while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
int index0 = index;
index = skip_annotation(buffer, limit, index);
u1* abase = buffer + index0;
int atype = Bytes::get_Java_u2(abase + atype_off);
int count = Bytes::get_Java_u2(abase + count_off);
Symbol* aname = check_symbol_at(cp, atype);
if (aname == NULL) break; // invalid annotation name
Symbol* member = NULL;
if (count >= 1) {
int member_index = Bytes::get_Java_u2(abase + member_off);
member = check_symbol_at(cp, member_index);
if (member == NULL) break; // invalid member name
}
// Here is where parsing particular annotations will take place.
AnnotationCollector::ID id = coll->annotation_index(aname);
if (id == AnnotationCollector::_unknown) continue;
coll->set_annotation(id);
// If there are no values, just set the bit and move on:
if (count == 0) continue;
// For the record, here is how annotation payloads can be collected.
// Suppose we want to capture @Retention.value. Here is how:
//if (id == AnnotationCollector::_class_Retention) {
// Symbol* payload = NULL;
// if (count == 1
// && e_size == (index0 - index) // match size
// && e_tag_val == *(abase + tag_off)
// && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off))
// == vmSymbols::RetentionPolicy_signature())
// && member == vmSymbols::value_name()) {
// payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off));
// }
// check_property(payload != NULL,
// "Invalid @Retention annotation at offset %u in class file %s",
// index0, CHECK);
// if (payload != NULL) {
// payload->increment_refcount();
// coll->_class_RetentionPolicy = payload;
// }
//}
}
}
ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) {
vmSymbols::SID sid = vmSymbols::find_sid(name);
switch (sid) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
if (_location != _in_method) break; // only allow for methods
return _method_ForceInline;
default: break;
}
return AnnotationCollector::_unknown;
}
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
fatal("no field annotations yet");
}
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
if (has_annotation(_method_ForceInline))
m->set_force_inline(true);
}
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
fatal("no class annotations yet");
}
#define MAX_ARGS_SIZE 255
#define MAX_CODE_SIZE 65535
#define INITIAL_MAX_LVT_NUMBER 256
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
// attribute is inlined. This is curbersome to avoid since we inline most of the parts in the
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
// methodOop to save footprint, so we only know the size of the resulting methodOop when the
// entire method attribute is parsed.
//
@ -1712,6 +1866,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
u4 code_length = 0;
u1* code_start = 0;
u2 exception_table_length = 0;
u2* exception_table_start = NULL;
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
u2 checked_exceptions_length = 0;
u2* checked_exceptions_start = NULL;
@ -1733,6 +1888,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
// stackmap attribute - JDK1.5
typeArrayHandle stackmap_data;
u2 generic_signature_index = 0;
MethodAnnotationCollector parsed_annotations;
u1* runtime_visible_annotations = NULL;
int runtime_visible_annotations_length = 0;
u1* runtime_invisible_annotations = NULL;
@ -1798,7 +1954,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
cfs->guarantee_more(2, CHECK_(nullHandle)); // exception_table_length
exception_table_length = cfs->get_u2_fast();
if (exception_table_length > 0) {
exception_handlers =
exception_table_start =
parse_exception_table(code_length, exception_table_length, cp, CHECK_(nullHandle));
}
@ -1959,6 +2115,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle));
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = method_attribute_length;
@ -2002,9 +2159,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
}
// All sizing information for a methodOop is finally available, now create it
methodOop m_oop = oopFactory::new_method(code_length, access_flags, linenumber_table_length,
total_lvt_length, checked_exceptions_length,
oopDesc::IsSafeConc, CHECK_(nullHandle));
methodOop m_oop = oopFactory::new_method(code_length, access_flags,
linenumber_table_length,
total_lvt_length,
exception_table_length,
checked_exceptions_length,
oopDesc::IsSafeConc,
CHECK_(nullHandle));
methodHandle m (THREAD, m_oop);
ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize);
@ -2035,16 +2196,15 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
// Fill in code attribute information
m->set_max_stack(max_stack);
m->set_max_locals(max_locals);
m->constMethod()->set_stackmap_data(stackmap_data());
/**
* The exception_table field is the flag used to indicate
* The stackmap_data field is the flag used to indicate
* that the methodOop and it's associated constMethodOop are partially
* initialized and thus are exempt from pre/post GC verification. Once
* the field is set, the oops are considered fully initialized so make
* sure that the oops can pass verification when this field is set.
*/
m->set_exception_table(exception_handlers());
m->constMethod()->set_stackmap_data(stackmap_data());
// Copy byte codes
m->set_code(code_start);
@ -2055,6 +2215,14 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
linenumber_table->buffer(), linenumber_table_length);
}
// Copy exception table
if (exception_table_length > 0) {
int size =
exception_table_length * sizeof(ExceptionTableElement) / sizeof(u2);
copy_u2_with_conversion((u2*) m->exception_table_start(),
exception_table_start, size);
}
// Copy checked exceptions
if (checked_exceptions_length > 0) {
int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
@ -2136,6 +2304,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
clear_hashtable(lvt_Hash);
}
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(m);
*method_annotations = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
@ -2314,7 +2484,7 @@ typeArrayHandle ClassFileParser::sort_methods(objArrayHandle methods,
}
void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK); // sourcefile_index
u2 sourcefile_index = cfs->get_u2_fast();
@ -2323,13 +2493,12 @@ void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp
cp->tag_at(sourcefile_index).is_utf8(),
"Invalid SourceFile attribute at constant pool index %u in class file %s",
sourcefile_index, CHECK);
k->set_source_file_name(cp->symbol_at(sourcefile_index));
set_class_sourcefile(cp->symbol_at(sourcefile_index));
}
void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
instanceKlassHandle k,
int length, TRAPS) {
ClassFileStream* cfs = stream();
u1* sde_buffer = cfs->get_u1_buffer();
@ -2337,7 +2506,13 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP
// Don't bother storing it if there is no way to retrieve it
if (JvmtiExport::can_get_source_debug_extension()) {
k->set_source_debug_extension((char*)sde_buffer, length);
assert((length+1) > length, "Overflow checking");
u1* sde = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, u1, length+1);
for (int i = 0; i < length; i++) {
sde[i] = sde_buffer[i];
}
sde[length] = '\0';
set_class_sde_buffer((char*)sde, length);
}
// Got utf8 string, set stream position forward
cfs->skip_u1(length, CHECK);
@ -2353,7 +2528,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
u2 enclosing_method_class_index,
u2 enclosing_method_method_index,
constantPoolHandle cp,
instanceKlassHandle k, TRAPS) {
TRAPS) {
ClassFileStream* cfs = stream();
u1* current_mark = cfs->current();
u2 length = 0;
@ -2444,7 +2619,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
assert(index == size, "wrong size");
// Update instanceKlass with inner class info.
k->set_inner_classes(inner_classes());
set_class_inner_classes(inner_classes);
// Restore buffer's current position.
cfs->set_current(current_mark);
@ -2452,11 +2627,11 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
return length;
}
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
k->set_is_synthetic();
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) {
set_class_synthetic_flag(true);
}
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) {
ClassFileStream* cfs = stream();
u2 signature_index = cfs->get_u2(CHECK);
check_property(
@ -2464,10 +2639,10 @@ void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp,
cp->tag_at(signature_index).is_utf8(),
"Invalid constant pool index %u in Signature attribute in class file %s",
signature_index, CHECK);
k->set_generic_signature(cp->symbol_at(signature_index));
set_class_generic_signature(cp->symbol_at(signature_index));
}
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k,
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp,
u4 attribute_byte_length, TRAPS) {
ClassFileStream* cfs = stream();
u1* current_start = cfs->current();
@ -2539,10 +2714,12 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHa
}
void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp,
ClassFileParser::ClassAnnotationCollector* parsed_annotations,
TRAPS) {
ClassFileStream* cfs = stream();
// Set inner classes attribute to default sentinel
k->set_inner_classes(Universe::the_empty_short_array());
set_class_inner_classes(typeArrayHandle(THREAD, Universe::the_empty_short_array()));
cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false;
@ -2578,10 +2755,10 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
} else {
parsed_sourcefile_attribute = true;
}
parse_classfile_sourcefile_attribute(cp, k, CHECK);
parse_classfile_sourcefile_attribute(cp, CHECK);
} else if (tag == vmSymbols::tag_source_debug_extension()) {
// Check for SourceDebugExtension tag
parse_classfile_source_debug_extension_attribute(cp, k, (int)attribute_length, CHECK);
parse_classfile_source_debug_extension_attribute(cp, (int)attribute_length, CHECK);
} else if (tag == vmSymbols::tag_inner_classes()) {
// Check for InnerClasses tag
if (parsed_innerclasses_attribute) {
@ -2600,7 +2777,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
"Invalid Synthetic classfile attribute length %u in class file %s",
attribute_length, CHECK);
}
parse_classfile_synthetic_attribute(cp, k, CHECK);
parse_classfile_synthetic_attribute(cp, CHECK);
} else if (tag == vmSymbols::tag_deprecated()) {
// Check for Deprecatd tag - 4276120
if (attribute_length != 0) {
@ -2615,11 +2792,16 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
"Wrong Signature attribute length %u in class file %s",
attribute_length, CHECK);
}
parse_classfile_signature_attribute(cp, k, CHECK);
parse_classfile_signature_attribute(cp, CHECK);
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
cp,
parsed_annotations,
CHECK);
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = attribute_length;
@ -2653,7 +2835,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
if (parsed_bootstrap_methods_attribute)
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
parsed_bootstrap_methods_attribute = true;
parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK);
parse_classfile_bootstrap_methods_attribute(cp, attribute_length, CHECK);
} else {
// Unknown attribute
cfs->skip_u1(attribute_length, CHECK);
@ -2668,7 +2850,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
runtime_invisible_annotations,
runtime_invisible_annotations_length,
CHECK);
k->set_class_annotations(annotations());
set_class_annotations(annotations);
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
u2 num_of_classes = parse_classfile_inner_classes_attribute(
@ -2676,7 +2858,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
parsed_innerclasses_attribute,
enclosing_method_class_index,
enclosing_method_method_index,
cp, k, CHECK);
cp, CHECK);
if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
@ -2690,6 +2872,23 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
}
}
void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
if (_synthetic_flag)
k->set_is_synthetic();
if (_sourcefile != NULL) {
_sourcefile->increment_refcount();
k->set_source_file_name(_sourcefile);
}
if (_generic_signature != NULL) {
_generic_signature->increment_refcount();
k->set_generic_signature(_generic_signature);
}
if (_sde_buffer != NULL) {
k->set_source_debug_extension(_sde_buffer, _sde_length);
}
k->set_inner_classes(_inner_classes());
k->set_class_annotations(_annotations());
}
typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
@ -2740,8 +2939,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::PARSE_CLASS);
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
_max_bootstrap_specifier_index = -1;
init_parsed_class_attributes();
if (JvmtiExport::should_post_class_file_load_hook()) {
// Get the cached class file bytes (if any) from the class that
@ -2974,6 +3172,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop);
objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop);
// Additional attributes
ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(cp, &parsed_annotations, CHECK_(nullHandle));
// Make sure this is the end of class file stream
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
// We check super class after class file is parsed and format is checked
if (super_class_index > 0 && super_klass.is_null()) {
Symbol* sk = cp->klass_name_at(super_class_index);
@ -3462,11 +3667,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass->set_has_miranda_methods(); // then set a flag
}
// Additional attributes
parse_classfile_attributes(cp, this_klass, CHECK_(nullHandle));
// Make sure this is the end of class file stream
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
// Fill in field values obtained by parse_classfile_attributes
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(this_klass);
apply_parsed_class_attributes(this_klass);
// VerifyOops believes that once this has been set, the object is completely loaded.
// Compute transitive closure of interfaces this class implements
@ -3481,6 +3685,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Do final class setup
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
// Fill in has_finalizer, has_vanilla_constructor, and layout_helper
set_precomputed_flags(this_klass);
// reinitialize modifiers, using the InnerClasses attribute

View File

@ -31,8 +31,8 @@
#include "oops/typeArrayOop.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/accessFlags.hpp"
#include "classfile/symbolTable.hpp"
class TempNewSymbol;
class FieldAllocationCount;
@ -50,11 +50,80 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
KlassHandle _host_klass;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
// precomputed flags
bool _has_finalizer;
bool _has_empty_finalizer;
bool _has_vanilla_constructor;
int _max_bootstrap_specifier_index; // detects BSS values
int _max_bootstrap_specifier_index;
// class attributes parsed before the instance klass is created:
bool _synthetic_flag;
Symbol* _sourcefile;
Symbol* _generic_signature;
char* _sde_buffer;
int _sde_length;
typeArrayHandle _inner_classes;
typeArrayHandle _annotations;
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
void set_class_sourcefile(Symbol* x) { _sourcefile = x; }
void set_class_generic_signature(Symbol* x) { _generic_signature = x; }
void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; }
void set_class_inner_classes(typeArrayHandle x) { _inner_classes = x; }
void set_class_annotations(typeArrayHandle x) { _annotations = x; }
void init_parsed_class_attributes() {
_synthetic_flag = false;
_sourcefile = NULL;
_generic_signature = NULL;
_sde_buffer = NULL;
_sde_length = 0;
// initialize the other flags too:
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
_max_bootstrap_specifier_index = -1;
}
void apply_parsed_class_attributes(instanceKlassHandle k); // update k
class AnnotationCollector {
public:
enum Location { _in_field, _in_method, _in_class };
enum ID {
_unknown = 0,
_method_ForceInline,
_annotation_LIMIT
};
const Location _location;
int _annotations_present;
AnnotationCollector(Location location)
: _location(location), _annotations_present(0)
{
assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
}
// If this annotation name has an ID, report it (or _none).
ID annotation_index(Symbol* name);
// Set the annotation name:
void set_annotation(ID id) {
assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
_annotations_present |= nth_bit((int)id);
}
// Report if the annotation is present.
bool has_any_annotations() { return _annotations_present != 0; }
bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
};
class FieldAnnotationCollector: public AnnotationCollector {
public:
FieldAnnotationCollector() : AnnotationCollector(_in_field) { }
void apply_to(FieldInfo* f);
};
class MethodAnnotationCollector: public AnnotationCollector {
public:
MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
void apply_to(methodHandle m);
};
class ClassAnnotationCollector: public AnnotationCollector {
public:
ClassAnnotationCollector() : AnnotationCollector(_in_class) { }
void apply_to(instanceKlassHandle k);
};
enum { fixed_buffer_size = 128 };
u_char linenumbertable_buffer[fixed_buffer_size];
@ -87,7 +156,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2* constantvalue_index_addr,
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
typeArrayHandle* field_annotations, TRAPS);
typeArrayHandle* field_annotations,
FieldAnnotationCollector* parsed_annotations,
TRAPS);
typeArrayHandle parse_fields(Symbol* class_name,
constantPoolHandle cp, bool is_interface,
FieldAllocationCount *fac,
@ -113,8 +184,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
objArrayHandle methods_parameter_annotations,
objArrayHandle methods_default_annotations,
TRAPS);
typeArrayHandle parse_exception_table(u4 code_length, u4 exception_table_length,
constantPoolHandle cp, TRAPS);
u2* parse_exception_table(u4 code_length, u4 exception_table_length,
constantPoolHandle cp, TRAPS);
void parse_linenumber_table(
u4 code_attribute_length, u4 code_length,
CompressedLineNumberWriteStream** write_stream, TRAPS);
@ -128,25 +199,32 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
typeArrayOop parse_stackmap_table(u4 code_attribute_length, TRAPS);
// Classfile attribute parsing
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
instanceKlassHandle k, int length, TRAPS);
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, int length, TRAPS);
u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
bool parsed_enclosingmethod_attribute,
u2 enclosing_method_class_index,
u2 enclosing_method_method_index,
constantPoolHandle cp,
instanceKlassHandle k, TRAPS);
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, u4 attribute_length, TRAPS);
TRAPS);
void parse_classfile_attributes(constantPoolHandle cp,
ClassAnnotationCollector* parsed_annotations,
TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, u4 attribute_length, TRAPS);
// Annotations handling
typeArrayHandle assemble_annotations(u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
u1* runtime_invisible_annotations,
int runtime_invisible_annotations_length, TRAPS);
int skip_annotation(u1* buffer, int limit, int index);
int skip_annotation_value(u1* buffer, int limit, int index);
void parse_annotations(u1* buffer, int limit, constantPoolHandle cp,
/* Results (currently, only one result is supported): */
AnnotationCollector* result,
TRAPS);
// Final setup
unsigned int compute_oop_map_count(instanceKlassHandle super,

View File

@ -2738,17 +2738,6 @@ void java_lang_invoke_CallSite::compute_offsets() {
if (k != NULL) {
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
}
// Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile
// (For C2: keep this until we have throttling logic for uncommon traps.)
if (k != NULL) {
instanceKlass* ik = instanceKlass::cast(k);
methodOop m_normal = ik->lookup_method(vmSymbols::setTargetNormal_name(), vmSymbols::setTarget_signature());
methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature());
guarantee(m_normal != NULL && m_volatile != NULL, "must exist");
m_normal->set_not_compilable_quietly();
m_volatile->set_not_compilable_quietly();
}
}

View File

@ -2771,7 +2771,6 @@ class ClassStatistics: AllStatic {
nmethods++;
method_size += m->size();
// class loader uses same objArray for empty vectors, so don't count these
if (m->exception_table()->length() != 0) method_size += m->exception_table()->size();
if (m->has_stackmap_table()) {
method_size += m->stackmap_data()->size();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1368,47 +1368,48 @@ char* ClassVerifier::generate_code_data(methodHandle m, u4 code_length, TRAPS) {
}
void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) {
typeArrayHandle exhandlers (THREAD, _method->exception_table());
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
constantPoolHandle cp (THREAD, _method->constants());
if (exhandlers() != NULL) {
for(int i = 0; i < exhandlers->length();) {
u2 start_pc = exhandlers->int_at(i++);
u2 end_pc = exhandlers->int_at(i++);
u2 handler_pc = exhandlers->int_at(i++);
if (start_pc >= code_length || code_data[start_pc] == 0) {
class_format_error("Illegal exception table start_pc %d", start_pc);
return;
}
if (end_pc != code_length) { // special case: end_pc == code_length
if (end_pc > code_length || code_data[end_pc] == 0) {
class_format_error("Illegal exception table end_pc %d", end_pc);
return;
}
}
if (handler_pc >= code_length || code_data[handler_pc] == 0) {
class_format_error("Illegal exception table handler_pc %d", handler_pc);
return;
}
int catch_type_index = exhandlers->int_at(i++);
if (catch_type_index != 0) {
VerificationType catch_type = cp_index_to_type(
catch_type_index, cp, CHECK_VERIFY(this));
VerificationType throwable =
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
bool is_subclass = throwable.is_assignable_from(
catch_type, this, CHECK_VERIFY(this));
if (!is_subclass) {
// 4286534: should throw VerifyError according to recent spec change
verify_error(
"Catch type is not a subclass of Throwable in handler %d",
handler_pc);
return;
}
}
if (start_pc < min) min = start_pc;
if (end_pc > max) max = end_pc;
for(int i = 0; i < exlength; i++) {
//reacquire the table in case a GC happened
ExceptionTable exhandlers(_method());
u2 start_pc = exhandlers.start_pc(i);
u2 end_pc = exhandlers.end_pc(i);
u2 handler_pc = exhandlers.handler_pc(i);
if (start_pc >= code_length || code_data[start_pc] == 0) {
class_format_error("Illegal exception table start_pc %d", start_pc);
return;
}
if (end_pc != code_length) { // special case: end_pc == code_length
if (end_pc > code_length || code_data[end_pc] == 0) {
class_format_error("Illegal exception table end_pc %d", end_pc);
return;
}
}
if (handler_pc >= code_length || code_data[handler_pc] == 0) {
class_format_error("Illegal exception table handler_pc %d", handler_pc);
return;
}
int catch_type_index = exhandlers.catch_type_index(i);
if (catch_type_index != 0) {
VerificationType catch_type = cp_index_to_type(
catch_type_index, cp, CHECK_VERIFY(this));
VerificationType throwable =
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
bool is_subclass = throwable.is_assignable_from(
catch_type, this, CHECK_VERIFY(this));
if (!is_subclass) {
// 4286534: should throw VerifyError according to recent spec change
verify_error(
"Catch type is not a subclass of Throwable in handler %d",
handler_pc);
return;
}
}
if (start_pc < min) min = start_pc;
if (end_pc > max) max = end_pc;
}
}
@ -1474,35 +1475,36 @@ u2 ClassVerifier::verify_stackmap_table(u2 stackmap_index, u2 bci,
void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame,
StackMapTable* stackmap_table, TRAPS) {
constantPoolHandle cp (THREAD, _method->constants());
typeArrayHandle exhandlers (THREAD, _method->exception_table());
if (exhandlers() != NULL) {
for(int i = 0; i < exhandlers->length();) {
u2 start_pc = exhandlers->int_at(i++);
u2 end_pc = exhandlers->int_at(i++);
u2 handler_pc = exhandlers->int_at(i++);
int catch_type_index = exhandlers->int_at(i++);
if(bci >= start_pc && bci < end_pc) {
u1 flags = current_frame->flags();
if (this_uninit) { flags |= FLAG_THIS_UNINIT; }
StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
if (catch_type_index != 0) {
// We know that this index refers to a subclass of Throwable
VerificationType catch_type = cp_index_to_type(
catch_type_index, cp, CHECK_VERIFY(this));
new_frame->push_stack(catch_type, CHECK_VERIFY(this));
} else {
VerificationType throwable =
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
new_frame->push_stack(throwable, CHECK_VERIFY(this));
}
bool match = stackmap_table->match_stackmap(
new_frame, handler_pc, true, false, CHECK_VERIFY(this));
if (!match) {
verify_error(bci,
"Stack map does not match the one at exception handler %d",
handler_pc);
return;
}
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
for(int i = 0; i < exlength; i++) {
//reacquire the table in case a GC happened
ExceptionTable exhandlers(_method());
u2 start_pc = exhandlers.start_pc(i);
u2 end_pc = exhandlers.end_pc(i);
u2 handler_pc = exhandlers.handler_pc(i);
int catch_type_index = exhandlers.catch_type_index(i);
if(bci >= start_pc && bci < end_pc) {
u1 flags = current_frame->flags();
if (this_uninit) { flags |= FLAG_THIS_UNINIT; }
StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
if (catch_type_index != 0) {
// We know that this index refers to a subclass of Throwable
VerificationType catch_type = cp_index_to_type(
catch_type_index, cp, CHECK_VERIFY(this));
new_frame->push_stack(catch_type, CHECK_VERIFY(this));
} else {
VerificationType throwable =
VerificationType::reference_type(vmSymbols::java_lang_Throwable());
new_frame->push_stack(throwable, CHECK_VERIFY(this));
}
bool match = stackmap_table->match_stackmap(
new_frame, handler_pc, true, false, CHECK_VERIFY(this));
if (!match) {
verify_error(bci,
"Stack map does not match the one at exception handler %d",
handler_pc);
return;
}
}
}

View File

@ -257,6 +257,7 @@
template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \
template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \

View File

@ -131,6 +131,10 @@ public:
assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be");
return (VMReg)(intptr_t)(value() + 1);
}
VMReg next(int i) {
assert((is_reg() && value() < stack0->value() - i) || is_stack(), "must be");
return (VMReg)(intptr_t)(value() + i);
}
VMReg prev() {
assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be");
return (VMReg)(intptr_t)(value() - 1);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "gc_implementation/g1/concurrentG1RefineThread.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "memory/space.inline.hpp"
@ -500,11 +501,11 @@ bool ConcurrentG1Refine::expand_card_count_cache(int cache_size_idx) {
}
void ConcurrentG1Refine::clear_and_record_card_counts() {
if (G1ConcRSLogCacheSize == 0) return;
if (G1ConcRSLogCacheSize == 0) {
return;
}
#ifndef PRODUCT
double start = os::elapsedTime();
#endif
if (_expand_card_counts) {
int new_idx = _cache_size_index + 1;
@ -523,11 +524,8 @@ void ConcurrentG1Refine::clear_and_record_card_counts() {
assert((this_epoch+1) <= max_jint, "to many periods");
// Update epoch
_n_periods++;
#ifndef PRODUCT
double elapsed = os::elapsedTime() - start;
_g1h->g1_policy()->record_cc_clear_time(elapsed * 1000.0);
#endif
double cc_clear_time_ms = (os::elapsedTime() - start) * 1000;
_g1h->g1_policy()->phase_times()->record_cc_clear_time_ms(cc_clear_time_ms);
}
void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {

View File

@ -3156,9 +3156,6 @@ bool ConcurrentMark::do_yield_check(uint worker_id) {
_g1h->g1_policy()->record_concurrent_pause();
}
cmThread()->yield();
if (worker_id == 0) {
_g1h->g1_policy()->record_concurrent_pause_end();
}
return true;
} else {
return false;

View File

@ -33,6 +33,7 @@
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1ErgoVerbose.hpp"
#include "gc_implementation/g1/g1EvacFailure.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/g1MarkSweep.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
@ -2274,7 +2275,7 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl,
while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) {
n_completed_buffers++;
}
g1_policy()->record_update_rs_processed_buffers(worker_i,
g1_policy()->phase_times()->record_update_rs_processed_buffers(worker_i,
(double) n_completed_buffers);
dcqs.clear_n_completed_buffers();
assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!");
@ -3633,10 +3634,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
.append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)")
.append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
TraceTime t(gc_cause_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
workers()->active_workers() : 1);
g1_policy()->phase_times()->note_gc_start(os::elapsedTime(), active_workers,
g1_policy()->gcs_are_young(), g1_policy()->during_initial_mark_pause(), gc_cause());
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
@ -3699,9 +3700,15 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// before the start GC event.
_hr_printer.start_gc(false /* full */, (size_t) total_collections());
// This timing is only used by the ergonomics to handle our pause target.
// It is unclear why this should not include the full pause. We will
// investigate this in CR 7178365.
//
// Preserving the old comment here if that helps the investigation:
//
// The elapsed time induced by the start time below deliberately elides
// the possible verification above.
double start_time_sec = os::elapsedTime();
double sample_start_time_sec = os::elapsedTime();
size_t start_used_bytes = used();
#if YOUNG_LIST_VERBOSE
@ -3710,7 +3717,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE
g1_policy()->record_collection_pause_start(start_time_sec,
g1_policy()->record_collection_pause_start(sample_start_time_sec,
start_used_bytes);
double scan_wait_start = os::elapsedTime();
@ -3719,11 +3726,12 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// objects on them have been correctly scanned before we start
// moving them during the GC.
bool waited = _cm->root_regions()->wait_until_scan_finished();
double wait_time_ms = 0.0;
if (waited) {
double scan_wait_end = os::elapsedTime();
double wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0;
g1_policy()->record_root_region_scan_wait_time(wait_time_ms);
wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0;
}
g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms);
#if YOUNG_LIST_VERBOSE
gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:");
@ -3877,12 +3885,16 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
true /* verify_fingers */);
_cm->note_end_of_gc();
double end_time_sec = os::elapsedTime();
double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
g1_policy()->record_pause_time_ms(pause_time_ms);
int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
workers()->active_workers() : 1);
g1_policy()->record_collection_pause_end(active_workers);
// Collect thread local data to allow the ergonomics to use
// the collected information
g1_policy()->phase_times()->collapse_par_times();
// This timing is only used by the ergonomics to handle our pause target.
// It is unclear why this should not include the full pause. We will
// investigate this in CR 7178365.
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
g1_policy()->record_collection_pause_end(pause_time_ms);
MemoryService::track_memory_usage();
@ -3929,9 +3941,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// RETIRE events are generated before the end GC event.
_hr_printer.end_gc(false /* full */, (size_t) total_collections());
// We have to do this after we decide whether to expand the heap or not.
g1_policy()->print_heap_transition();
if (mark_in_progress()) {
concurrent_mark()->update_g1_committed();
}
@ -3941,13 +3950,14 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
#endif
gc_epilogue(false);
g1_policy()->phase_times()->note_gc_end(os::elapsedTime());
// We have to do this after we decide whether to expand the heap or not.
g1_policy()->print_heap_transition();
}
// The closing of the inner scope, immediately above, will complete
// logging at the "fine" level. The record_collection_pause_end() call
// above will complete logging at the "finer" level.
//
// It is not yet to safe, however, to tell the concurrent mark to
// It is not yet to safe to tell the concurrent mark to
// start as we have some optional output below. We don't want the
// output from the concurrent mark thread interfering with this
// logging output either.
@ -4695,7 +4705,7 @@ public:
if (worker_id >= _n_workers) return; // no work needed this round
double start_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms);
_g1h->g1_policy()->phase_times()->record_gc_worker_start_time(worker_id, start_time_ms);
{
ResourceMark rm;
@ -4744,8 +4754,8 @@ public:
evac.do_void();
double elapsed_ms = (os::elapsedTime()-start)*1000.0;
double term_ms = pss.term_time()*1000.0;
_g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
_g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts());
_g1h->g1_policy()->phase_times()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
_g1h->g1_policy()->phase_times()->record_termination(worker_id, term_ms, pss.term_attempts());
}
_g1h->g1_policy()->record_thread_age_table(pss.age_table());
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
@ -4763,7 +4773,7 @@ public:
}
double end_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms);
_g1h->g1_policy()->phase_times()->record_gc_worker_end_time(worker_id, end_time_ms);
}
};
@ -4874,15 +4884,15 @@ g1_process_strong_roots(bool collecting_perm_gen,
double ext_roots_end = os::elapsedTime();
g1_policy()->reset_obj_copy_time(worker_i);
g1_policy()->phase_times()->reset_obj_copy_time(worker_i);
double obj_copy_time_sec = buf_scan_perm.closure_app_seconds() +
buf_scan_non_heap_roots.closure_app_seconds();
g1_policy()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
g1_policy()->phase_times()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
double ext_root_time_ms =
((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0;
g1_policy()->record_ext_root_scan_time(worker_i, ext_root_time_ms);
g1_policy()->phase_times()->record_ext_root_scan_time(worker_i, ext_root_time_ms);
// During conc marking we have to filter the per-thread SATB buffers
// to make sure we remove any oops into the CSet (which will show up
@ -4893,7 +4903,7 @@ g1_process_strong_roots(bool collecting_perm_gen,
}
}
double satb_filtering_ms = (os::elapsedTime() - ext_roots_end) * 1000.0;
g1_policy()->record_satb_filtering_time(worker_i, satb_filtering_ms);
g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
// Now scan the complement of the collection set.
if (scan_rs != NULL) {
@ -5393,7 +5403,7 @@ void G1CollectedHeap::process_discovered_references() {
assert(pss.refs()->is_empty(), "both queue and overflow should be empty");
double ref_proc_time = os::elapsedTime() - ref_proc_start;
g1_policy()->record_ref_proc_time(ref_proc_time * 1000.0);
g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0);
}
// Weak Reference processing during an evacuation pause (part 2).
@ -5430,7 +5440,7 @@ void G1CollectedHeap::enqueue_discovered_references() {
// and could signicantly increase the pause time.
double ref_enq_time = os::elapsedTime() - ref_enq_start;
g1_policy()->record_ref_enq_time(ref_enq_time * 1000.0);
g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0);
}
void G1CollectedHeap::evacuate_collection_set() {
@ -5493,11 +5503,11 @@ void G1CollectedHeap::evacuate_collection_set() {
}
double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
g1_policy()->record_par_time(par_time_ms);
g1_policy()->phase_times()->record_par_time(par_time_ms);
double code_root_fixup_time_ms =
(os::elapsedTime() - end_par_time_sec) * 1000.0;
g1_policy()->record_code_root_fixup_time(code_root_fixup_time_ms);
g1_policy()->phase_times()->record_code_root_fixup_time(code_root_fixup_time_ms);
set_par_threads(0);
@ -5759,7 +5769,7 @@ void G1CollectedHeap::cleanUpCardTable() {
}
double elapsed = os::elapsedTime() - start;
g1_policy()->record_clear_ct_time(elapsed * 1000.0);
g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0);
}
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
@ -5868,8 +5878,8 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
NULL /* old_proxy_set */,
NULL /* humongous_proxy_set */,
false /* par */);
policy->record_young_free_cset_time_ms(young_time_ms);
policy->record_non_young_free_cset_time_ms(non_young_time_ms);
policy->phase_times()->record_young_free_cset_time_ms(young_time_ms);
policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms);
}
// This routine is similar to the above but does not record

View File

@ -29,6 +29,7 @@
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1ErgoVerbose.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/shared/gcPolicyCounters.hpp"
@ -77,57 +78,6 @@ static double non_young_other_cost_per_region_ms_defaults[] = {
1.0, 0.7, 0.7, 0.5, 0.5, 0.42, 0.42, 0.30
};
// Help class for avoiding interleaved logging
class LineBuffer: public StackObj {
private:
static const int BUFFER_LEN = 1024;
static const int INDENT_CHARS = 3;
char _buffer[BUFFER_LEN];
int _indent_level;
int _cur;
void vappend(const char* format, va_list ap) {
int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap);
if (res != -1) {
_cur += res;
} else {
DEBUG_ONLY(warning("buffer too small in LineBuffer");)
_buffer[BUFFER_LEN -1] = 0;
_cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again
}
}
public:
explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) {
for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) {
_buffer[_cur] = ' ';
}
}
#ifndef PRODUCT
~LineBuffer() {
assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?");
}
#endif
void append(const char* format, ...) {
va_list ap;
va_start(ap, format);
vappend(format, ap);
va_end(ap);
}
void append_and_print_cr(const char* format, ...) {
va_list ap;
va_start(ap, format);
vappend(format, ap);
va_end(ap);
gclog_or_tty->print_cr("%s", _buffer);
_cur = _indent_level * INDENT_CHARS;
}
};
G1CollectorPolicy::G1CollectorPolicy() :
_parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
? ParallelGCThreads : 1),
@ -135,20 +85,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
_recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_stop_world_start(0.0),
_cur_clear_ct_time_ms(0.0),
_root_region_scan_wait_time_ms(0.0),
_cur_ref_proc_time_ms(0.0),
_cur_ref_enq_time_ms(0.0),
#ifndef PRODUCT
_min_clear_cc_time_ms(-1.0),
_max_clear_cc_time_ms(-1.0),
_cur_clear_cc_time_ms(0.0),
_cum_clear_cc_time_ms(0.0),
_num_cc_clears(0L),
#endif
_concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
@ -257,30 +193,9 @@ G1CollectorPolicy::G1CollectorPolicy() :
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
_par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads];
_par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
_par_last_satb_filtering_times_ms = new double[_parallel_gc_threads];
_phase_times = new G1GCPhaseTimes(_parallel_gc_threads);
_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
_par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
_par_last_termination_times_ms = new double[_parallel_gc_threads];
_par_last_termination_attempts = new double[_parallel_gc_threads];
_par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
_par_last_gc_worker_times_ms = new double[_parallel_gc_threads];
_par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads];
int index;
if (ParallelGCThreads == 0)
index = 0;
else if (ParallelGCThreads > 8)
index = 7;
else
index = ParallelGCThreads - 1;
int index = MIN2(_parallel_gc_threads - 1, 7);
_pending_card_diff_seq->add(0.0);
_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
@ -824,7 +739,7 @@ G1CollectorPolicy::verify_young_ages(HeapRegion* head,
#endif // PRODUCT
void G1CollectorPolicy::record_full_collection_start() {
_cur_collection_start_sec = os::elapsedTime();
_full_collection_start_sec = os::elapsedTime();
// Release the future to-space so that it is available for compaction into.
_g1->set_full_collection();
}
@ -833,7 +748,7 @@ void G1CollectorPolicy::record_full_collection_end() {
// Consider this like a collection pause for the purposes of allocation
// since last pause.
double end_sec = os::elapsedTime();
double full_gc_time_sec = end_sec - _cur_collection_start_sec;
double full_gc_time_sec = end_sec - _full_collection_start_sec;
double full_gc_time_ms = full_gc_time_sec * 1000.0;
_trace_gen1_time_data.record_full_collection(full_gc_time_ms);
@ -869,12 +784,6 @@ void G1CollectorPolicy::record_stop_world_start() {
void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
size_t start_used) {
if (G1Log::finer()) {
gclog_or_tty->stamp(PrintGCTimeStamps);
gclog_or_tty->print("[%s", (const char*)GCCauseString("GC pause", _g1->gc_cause())
.append(gcs_are_young() ? " (young)" : " (mixed)"));
}
// We only need to do this here as the policy will only be applied
// to the GC we're about to start. so, no point is calculating this
// every time we calculate / recalculate the target young length.
@ -888,7 +797,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
_trace_gen0_time_data.record_start_collection(s_w_t_ms);
_stop_world_start = 0.0;
_cur_collection_start_sec = start_time_sec;
phase_times()->_cur_collection_start_sec = start_time_sec;
_cur_collection_pause_used_at_start_bytes = start_used;
_cur_collection_pause_used_regions_at_start = _g1->used_regions();
_pending_cards = _g1->pending_card_num();
@ -902,30 +811,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
_survivor_bytes_before_gc = young_list->survivor_used_bytes();
_capacity_before_gc = _g1->capacity();
#ifdef DEBUG
// initialise these to something well known so that we can spot
// if they are not set properly
for (int i = 0; i < _parallel_gc_threads; ++i) {
_par_last_gc_worker_start_times_ms[i] = -1234.0;
_par_last_ext_root_scan_times_ms[i] = -1234.0;
_par_last_satb_filtering_times_ms[i] = -1234.0;
_par_last_update_rs_times_ms[i] = -1234.0;
_par_last_update_rs_processed_buffers[i] = -1234.0;
_par_last_scan_rs_times_ms[i] = -1234.0;
_par_last_obj_copy_times_ms[i] = -1234.0;
_par_last_termination_times_ms[i] = -1234.0;
_par_last_termination_attempts[i] = -1234.0;
_par_last_gc_worker_end_times_ms[i] = -1234.0;
_par_last_gc_worker_times_ms[i] = -1234.0;
_par_last_gc_worker_other_times_ms[i] = -1234.0;
}
#endif
// This is initialized to zero here and is set during the evacuation
// pause if we actually waited for the root region scanning to finish.
_root_region_scan_wait_time_ms = 0.0;
_last_gc_was_young = false;
// do that for any other surv rate groups
@ -974,127 +859,6 @@ void G1CollectorPolicy::record_concurrent_pause() {
}
}
void G1CollectorPolicy::record_concurrent_pause_end() {
}
template<class T>
T sum_of(T* sum_arr, int start, int n, int N) {
T sum = (T)0;
for (int i = 0; i < n; i++) {
int j = (start + i) % N;
sum += sum_arr[j];
}
return sum;
}
void G1CollectorPolicy::print_par_stats(int level,
const char* str,
double* data,
bool showDecimals) {
double min = data[0], max = data[0];
double total = 0.0;
LineBuffer buf(level);
buf.append("[%s (ms):", str);
for (uint i = 0; i < no_of_gc_threads(); ++i) {
double val = data[i];
if (val < min)
min = val;
if (val > max)
max = val;
total += val;
if (G1Log::finest()) {
if (showDecimals) {
buf.append(" %.1lf", val);
} else {
buf.append(" %d", (int)val);
}
}
}
if (G1Log::finest()) {
buf.append_and_print_cr("");
}
double avg = total / (double) no_of_gc_threads();
if (showDecimals) {
buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]",
min, avg, max, max - min, total);
} else {
buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]",
(int)min, (int)avg, (int)max, (int)max - (int)min, (int)total);
}
}
void G1CollectorPolicy::print_stats(int level,
const char* str,
double value) {
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
}
void G1CollectorPolicy::print_stats(int level,
const char* str,
double value,
int workers) {
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
}
void G1CollectorPolicy::print_stats(int level,
const char* str,
int value) {
LineBuffer(level).append_and_print_cr("[%s: %d]", str, value);
}
double G1CollectorPolicy::avg_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = 0.0;
for (uint i = 0; i < no_of_gc_threads(); ++i) {
ret += data[i];
}
return ret / (double) no_of_gc_threads();
} else {
return data[0];
}
}
double G1CollectorPolicy::max_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = data[0];
for (uint i = 1; i < no_of_gc_threads(); ++i) {
if (data[i] > ret) {
ret = data[i];
}
}
return ret;
} else {
return data[0];
}
}
double G1CollectorPolicy::sum_of_values(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double sum = 0.0;
for (uint i = 0; i < no_of_gc_threads(); i++) {
sum += data[i];
}
return sum;
} else {
return data[0];
}
}
double G1CollectorPolicy::max_sum(double* data1, double* data2) {
double ret = data1[0] + data2[0];
if (G1CollectedHeap::use_parallel_gc_threads()) {
for (uint i = 1; i < no_of_gc_threads(); ++i) {
double data = data1[i] + data2[i];
if (data > ret) {
ret = data;
}
}
}
return ret;
}
bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) {
if (_g1->concurrent_mark()->cmThread()->during_cycle()) {
return false;
@ -1142,10 +906,8 @@ bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) {
double end_time_sec = os::elapsedTime();
double elapsed_ms = _last_pause_time_ms;
bool parallel = G1CollectedHeap::use_parallel_gc_threads();
assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
"otherwise, the subtraction below does not make sense");
size_t rs_size =
@ -1154,7 +916,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
bool last_pause_included_initial_mark = false;
bool update_stats = !_g1->evacuation_failed();
set_no_of_gc_threads(no_of_gc_threads);
#ifndef PRODUCT
if (G1YoungSurvRateVerbose) {
@ -1174,7 +935,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
set_initiate_conc_mark_if_possible();
}
_mmu_tracker->add_pause(end_time_sec - elapsed_ms/1000.0,
_mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0,
end_time_sec, false);
size_t freed_bytes =
@ -1185,58 +946,11 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
(double)surviving_bytes/
(double)_collection_set_bytes_used_before;
// These values are used to update the summary information that is
// displayed when TraceGen0Time is enabled, and are output as part
// of the "finer" output, in the non-parallel case.
double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
double satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms);
double update_rs_time = avg_value(_par_last_update_rs_times_ms);
double update_rs_processed_buffers =
sum_of_values(_par_last_update_rs_processed_buffers);
double scan_rs_time = avg_value(_par_last_scan_rs_times_ms);
double obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
double termination_time = avg_value(_par_last_termination_times_ms);
double known_time = ext_root_scan_time +
satb_filtering_time +
update_rs_time +
scan_rs_time +
obj_copy_time;
double other_time_ms = elapsed_ms;
// Subtract the root region scanning wait time. It's initialized to
// zero at the start of the pause.
other_time_ms -= _root_region_scan_wait_time_ms;
if (parallel) {
other_time_ms -= _cur_collection_par_time_ms;
} else {
other_time_ms -= known_time;
}
// Now subtract the time taken to fix up roots in generated code
other_time_ms -= _cur_collection_code_root_fixup_time_ms;
// Subtract the time taken to clean the card table from the
// current value of "other time"
other_time_ms -= _cur_clear_ct_time_ms;
// TraceGen0Time and TraceGen1Time summary info updating.
if (update_stats) {
double parallel_known_time = known_time + termination_time;
double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
_trace_gen0_time_data.record_end_collection(
elapsed_ms, other_time_ms, _root_region_scan_wait_time_ms, _cur_collection_par_time_ms,
ext_root_scan_time, satb_filtering_time, update_rs_time, scan_rs_time, obj_copy_time,
termination_time, parallel_other_time, _cur_clear_ct_time_ms);
_trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times());
// this is where we update the allocation rate of the application
double app_time_ms =
(_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms);
(phase_times()->_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms);
if (app_time_ms < MIN_TIMER_GRANULARITY) {
// This usually happens due to the timer not having the required
// granularity. Some Linuxes are the usual culprits.
@ -1257,7 +971,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
double interval_ms =
(end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
update_recent_gc_times(end_time_sec, elapsed_ms);
update_recent_gc_times(end_time_sec, pause_time_ms);
_recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms;
if (recent_avg_pause_time_ratio() < 0.0 ||
(recent_avg_pause_time_ratio() - 1.0 > 0.0)) {
@ -1284,90 +998,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
}
}
}
if (G1Log::finer()) {
bool print_marking_info =
_g1->mark_in_progress() && !last_pause_included_initial_mark;
gclog_or_tty->print_cr("%s, %1.8lf secs]",
(last_pause_included_initial_mark) ? " (initial-mark)" : "",
elapsed_ms / 1000.0);
if (_root_region_scan_wait_time_ms > 0.0) {
print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
}
if (parallel) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms, no_of_gc_threads);
print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
if (print_marking_info) {
print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms);
}
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
if (G1Log::finest()) {
print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers,
false /* showDecimals */);
}
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
if (G1Log::finest()) {
print_par_stats(3, "Termination Attempts", _par_last_termination_attempts,
false /* showDecimals */);
}
for (int i = 0; i < _parallel_gc_threads; i++) {
_par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] -
_par_last_gc_worker_start_times_ms[i];
double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
_par_last_satb_filtering_times_ms[i] +
_par_last_update_rs_times_ms[i] +
_par_last_scan_rs_times_ms[i] +
_par_last_obj_copy_times_ms[i] +
_par_last_termination_times_ms[i];
_par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] -
worker_known_time;
}
print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms);
print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
} else {
print_stats(1, "Ext Root Scanning", ext_root_scan_time);
if (print_marking_info) {
print_stats(1, "SATB Filtering", satb_filtering_time);
}
print_stats(1, "Update RS", update_rs_time);
if (G1Log::finest()) {
print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers);
}
print_stats(1, "Scan RS", scan_rs_time);
print_stats(1, "Object Copying", obj_copy_time);
}
print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
#ifndef PRODUCT
print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms);
print_stats(1, "Min Clear CC", _min_clear_cc_time_ms);
print_stats(1, "Max Clear CC", _max_clear_cc_time_ms);
if (_num_cc_clears > 0) {
print_stats(1, "Avg Clear CC", _cum_clear_cc_time_ms / ((double)_num_cc_clears));
}
#endif
print_stats(1, "Other", other_time_ms);
print_stats(2, "Choose CSet",
(_recorded_young_cset_choice_time_ms +
_recorded_non_young_cset_choice_time_ms));
print_stats(2, "Ref Proc", _cur_ref_proc_time_ms);
print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
print_stats(2, "Free CSet",
(_recorded_young_free_cset_time_ms +
_recorded_non_young_free_cset_time_ms));
}
bool new_in_marking_window = _in_marking_window;
bool new_in_marking_window_im = false;
if (during_initial_mark_pause()) {
@ -1406,8 +1036,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
// do that for any other surv rate groupsx
if (update_stats) {
double pause_time_ms = elapsed_ms;
size_t diff = 0;
if (_max_pending_cards >= _pending_cards) {
diff = _max_pending_cards - _pending_cards;
@ -1416,7 +1044,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
double cost_per_card_ms = 0.0;
if (_pending_cards > 0) {
cost_per_card_ms = update_rs_time / (double) _pending_cards;
cost_per_card_ms = phase_times()->_update_rs_time / (double) _pending_cards;
_cost_per_card_ms_seq->add(cost_per_card_ms);
}
@ -1424,7 +1052,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
double cost_per_entry_ms = 0.0;
if (cards_scanned > 10) {
cost_per_entry_ms = scan_rs_time / (double) cards_scanned;
cost_per_entry_ms = phase_times()->_scan_rs_time / (double) cards_scanned;
if (_last_gc_was_young) {
_cost_per_entry_ms_seq->add(cost_per_entry_ms);
} else {
@ -1464,7 +1092,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
size_t copied_bytes = surviving_bytes;
double cost_per_byte_ms = 0.0;
if (copied_bytes > 0) {
cost_per_byte_ms = obj_copy_time / (double) copied_bytes;
cost_per_byte_ms = phase_times()->_obj_copy_time / (double) copied_bytes;
if (_in_marking_window) {
_cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
} else {
@ -1473,21 +1101,21 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
}
double all_other_time_ms = pause_time_ms -
(update_rs_time + scan_rs_time + obj_copy_time + termination_time);
(phase_times()->_update_rs_time + phase_times()->_scan_rs_time + phase_times()->_obj_copy_time + phase_times()->_termination_time);
double young_other_time_ms = 0.0;
if (young_cset_region_length() > 0) {
young_other_time_ms =
_recorded_young_cset_choice_time_ms +
_recorded_young_free_cset_time_ms;
phase_times()->_recorded_young_cset_choice_time_ms +
phase_times()->_recorded_young_free_cset_time_ms;
_young_other_cost_per_region_ms_seq->add(young_other_time_ms /
(double) young_cset_region_length());
}
double non_young_other_time_ms = 0.0;
if (old_cset_region_length() > 0) {
non_young_other_time_ms =
_recorded_non_young_cset_choice_time_ms +
_recorded_non_young_free_cset_time_ms;
phase_times()->_recorded_non_young_cset_choice_time_ms +
phase_times()->_recorded_non_young_free_cset_time_ms;
_non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms /
(double) old_cset_region_length());
@ -1514,7 +1142,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
// Note that _mmu_tracker->max_gc_time() returns the time in seconds.
double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
adjust_concurrent_refinement(phase_times()->_update_rs_time, phase_times()->_update_rs_processed_buffers, update_rs_time_goal_ms);
_collectionSetChooser->verify();
}
@ -2323,7 +1951,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths);
double young_end_time_sec = os::elapsedTime();
_recorded_young_cset_choice_time_ms =
phase_times()->_recorded_young_cset_choice_time_ms =
(young_end_time_sec - young_start_time_sec) * 1000.0;
// We are doing young collections so reset this.
@ -2439,7 +2067,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
predicted_pause_time_ms, target_pause_time_ms);
double non_young_end_time_sec = os::elapsedTime();
_recorded_non_young_cset_choice_time_ms =
phase_times()->_recorded_non_young_cset_choice_time_ms =
(non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
}
@ -2455,33 +2083,29 @@ void TraceGen0TimeData::record_yield_time(double yield_time_ms) {
}
}
void TraceGen0TimeData::record_end_collection(
double total_ms,
double other_ms,
double root_region_scan_wait_ms,
double parallel_ms,
double ext_root_scan_ms,
double satb_filtering_ms,
double update_rs_ms,
double scan_rs_ms,
double obj_copy_ms,
double termination_ms,
double parallel_other_ms,
double clear_ct_ms)
{
void TraceGen0TimeData::record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times) {
if(TraceGen0Time) {
_total.add(total_ms);
_other.add(other_ms);
_root_region_scan_wait.add(root_region_scan_wait_ms);
_parallel.add(parallel_ms);
_ext_root_scan.add(ext_root_scan_ms);
_satb_filtering.add(satb_filtering_ms);
_update_rs.add(update_rs_ms);
_scan_rs.add(scan_rs_ms);
_obj_copy.add(obj_copy_ms);
_termination.add(termination_ms);
_parallel_other.add(parallel_other_ms);
_clear_ct.add(clear_ct_ms);
_total.add(pause_time_ms);
_other.add(pause_time_ms - phase_times->accounted_time_ms());
_root_region_scan_wait.add(phase_times->_root_region_scan_wait_time_ms);
_parallel.add(phase_times->_cur_collection_par_time_ms);
_ext_root_scan.add(phase_times->_ext_root_scan_time);
_satb_filtering.add(phase_times->_satb_filtering_time);
_update_rs.add(phase_times->_update_rs_time);
_scan_rs.add(phase_times->_scan_rs_time);
_obj_copy.add(phase_times->_obj_copy_time);
_termination.add(phase_times->_termination_time);
double parallel_known_time = phase_times->_ext_root_scan_time +
phase_times->_satb_filtering_time +
phase_times->_update_rs_time +
phase_times->_scan_rs_time +
phase_times->_obj_copy_time +
+ phase_times->_termination_time;
double parallel_other_time = phase_times->_cur_collection_par_time_ms - parallel_known_time;
_parallel_other.add(parallel_other_time);
_clear_ct.add(phase_times->_cur_clear_ct_time_ms);
}
}
@ -2497,20 +2121,18 @@ void TraceGen0TimeData::increment_mixed_collection_count() {
}
}
void TraceGen0TimeData::print_summary(int level,
const char* str,
void TraceGen0TimeData::print_summary(const char* str,
const NumberSeq* seq) const {
double sum = seq->sum();
LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)",
gclog_or_tty->print_cr("%-27s = %8.2lf s (avg = %8.2lf ms)",
str, sum / 1000.0, seq->avg());
}
void TraceGen0TimeData::print_summary_sd(int level,
const char* str,
void TraceGen0TimeData::print_summary_sd(const char* str,
const NumberSeq* seq) const {
print_summary(level, str, seq);
LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)",
seq->num(), seq->sd(), seq->maximum());
print_summary(str, seq);
gclog_or_tty->print_cr("%+45s = %5d, std dev = %8.2lf ms, max = %8.2lf ms)",
"(num", seq->num(), seq->sd(), seq->maximum());
}
void TraceGen0TimeData::print() const {
@ -2519,7 +2141,7 @@ void TraceGen0TimeData::print() const {
}
gclog_or_tty->print_cr("ALL PAUSES");
print_summary_sd(0, "Total", &_total);
print_summary_sd(" Total", &_total);
gclog_or_tty->print_cr("");
gclog_or_tty->print_cr("");
gclog_or_tty->print_cr(" Young GC Pauses: %8d", _young_pause_num);
@ -2531,24 +2153,24 @@ void TraceGen0TimeData::print() const {
if (_young_pause_num == 0 && _mixed_pause_num == 0) {
gclog_or_tty->print_cr("none");
} else {
print_summary_sd(0, "Evacuation Pauses", &_total);
print_summary(1, "Root Region Scan Wait", &_root_region_scan_wait);
print_summary(1, "Parallel Time", &_parallel);
print_summary(2, "Ext Root Scanning", &_ext_root_scan);
print_summary(2, "SATB Filtering", &_satb_filtering);
print_summary(2, "Update RS", &_update_rs);
print_summary(2, "Scan RS", &_scan_rs);
print_summary(2, "Object Copy", &_obj_copy);
print_summary(2, "Termination", &_termination);
print_summary(2, "Parallel Other", &_parallel_other);
print_summary(1, "Clear CT", &_clear_ct);
print_summary(1, "Other", &_other);
print_summary_sd(" Evacuation Pauses", &_total);
print_summary(" Root Region Scan Wait", &_root_region_scan_wait);
print_summary(" Parallel Time", &_parallel);
print_summary(" Ext Root Scanning", &_ext_root_scan);
print_summary(" SATB Filtering", &_satb_filtering);
print_summary(" Update RS", &_update_rs);
print_summary(" Scan RS", &_scan_rs);
print_summary(" Object Copy", &_obj_copy);
print_summary(" Termination", &_termination);
print_summary(" Parallel Other", &_parallel_other);
print_summary(" Clear CT", &_clear_ct);
print_summary(" Other", &_other);
}
gclog_or_tty->print_cr("");
gclog_or_tty->print_cr("MISC");
print_summary_sd(0, "Stop World", &_all_stop_world_times_ms);
print_summary_sd(0, "Yields", &_all_yield_times_ms);
print_summary_sd(" Stop World", &_all_stop_world_times_ms);
print_summary_sd(" Yields", &_all_yield_times_ms);
}
void TraceGen1TimeData::record_full_collection(double full_gc_time_ms) {

View File

@ -36,6 +36,7 @@
class HeapRegion;
class CollectionSetChooser;
class G1GCPhaseTimes;
// TraceGen0Time collects data on _both_ young and mixed evacuation pauses
// (the latter may contain non-young regions - i.e. regions that are
@ -61,26 +62,14 @@ class TraceGen0TimeData : public CHeapObj<mtGC> {
NumberSeq _parallel_other;
NumberSeq _clear_ct;
void print_summary (int level, const char* str, const NumberSeq* seq) const;
void print_summary_sd (int level, const char* str, const NumberSeq* seq) const;
void print_summary(const char* str, const NumberSeq* seq) const;
void print_summary_sd(const char* str, const NumberSeq* seq) const;
public:
TraceGen0TimeData() : _young_pause_num(0), _mixed_pause_num(0) {};
void record_start_collection(double time_to_stop_the_world_ms);
void record_yield_time(double yield_time_ms);
void record_end_collection(
double total_ms,
double other_ms,
double root_region_scan_wait_ms,
double parallel_ms,
double ext_root_scan_ms,
double satb_filtering_ms,
double update_rs_ms,
double scan_rs_ms,
double obj_copy_ms,
double termination_ms,
double parallel_other_ms,
double clear_ct_ms);
void record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times);
void increment_young_collection_count();
void increment_mixed_collection_count();
void print() const;
@ -186,25 +175,9 @@ private:
CollectionSetChooser* _collectionSetChooser;
double _cur_collection_start_sec;
double _full_collection_start_sec;
size_t _cur_collection_pause_used_at_start_bytes;
uint _cur_collection_pause_used_regions_at_start;
double _cur_collection_par_time_ms;
double _cur_collection_code_root_fixup_time_ms;
double _cur_clear_ct_time_ms;
double _cur_ref_proc_time_ms;
double _cur_ref_enq_time_ms;
#ifndef PRODUCT
// Card Table Count Cache stats
double _min_clear_cc_time_ms; // min
double _max_clear_cc_time_ms; // max
double _cur_clear_cc_time_ms; // clearing time during current pause
double _cum_clear_cc_time_ms; // cummulative clearing time
jlong _num_cc_clears; // number of times the card count cache has been cleared
#endif
// These exclude marking times.
TruncatedSeq* _recent_gc_times_ms;
@ -217,23 +190,6 @@ private:
double _stop_world_start;
double* _par_last_gc_worker_start_times_ms;
double* _par_last_ext_root_scan_times_ms;
double* _par_last_satb_filtering_times_ms;
double* _par_last_update_rs_times_ms;
double* _par_last_update_rs_processed_buffers;
double* _par_last_scan_rs_times_ms;
double* _par_last_obj_copy_times_ms;
double* _par_last_termination_times_ms;
double* _par_last_termination_attempts;
double* _par_last_gc_worker_end_times_ms;
double* _par_last_gc_worker_times_ms;
// Each workers 'other' time i.e. the elapsed time of the parallel
// code executed by a worker minus the sum of the individual sub-phase
// times for that worker thread.
double* _par_last_gc_worker_other_times_ms;
// indicates whether we are in young or mixed GC mode
bool _gcs_are_young;
@ -306,10 +262,6 @@ private:
size_t _recorded_rs_lengths;
size_t _max_rs_lengths;
double _recorded_young_free_cset_time_ms;
double _recorded_non_young_free_cset_time_ms;
double _sigma;
size_t _rs_lengths_prediction;
@ -341,8 +293,7 @@ private:
void set_no_of_gc_threads(uintx v) { _no_of_gc_threads = v; }
double _pause_time_target_ms;
double _recorded_young_cset_choice_time_ms;
double _recorded_non_young_cset_choice_time_ms;
size_t _pending_cards;
size_t _max_pending_cards;
@ -497,14 +448,6 @@ public:
uint young_cset_region_length() { return eden_cset_region_length() +
survivor_cset_region_length(); }
void record_young_free_cset_time_ms(double time_ms) {
_recorded_young_free_cset_time_ms = time_ms;
}
void record_non_young_free_cset_time_ms(double time_ms) {
_recorded_non_young_free_cset_time_ms = time_ms;
}
double predict_survivor_regions_evac_time();
void cset_regions_freed() {
@ -552,19 +495,6 @@ public:
}
private:
void print_stats(int level, const char* str, double value);
void print_stats(int level, const char* str, double value, int workers);
void print_stats(int level, const char* str, int value);
void print_par_stats(int level, const char* str, double* data, bool showDecimals = true);
double avg_value (double* data);
double max_value (double* data);
double sum_of_values (double* data);
double max_sum (double* data1, double* data2);
double _last_pause_time_ms;
size_t _bytes_in_collection_set_before_gc;
size_t _bytes_copied_during_gc;
@ -638,6 +568,8 @@ private:
// Stash a pointer to the g1 heap.
G1CollectedHeap* _g1;
G1GCPhaseTimes* _phase_times;
// The ratio of gc time to elapsed time, computed over recent pauses.
double _recent_avg_pause_time_ratio;
@ -677,7 +609,6 @@ private:
double _cur_mark_stop_world_time_ms;
double _mark_remark_start_sec;
double _mark_cleanup_start_sec;
double _root_region_scan_wait_time_ms;
// Update the young list target length either by setting it to the
// desired fixed value or by calculating it using G1's pause
@ -728,6 +659,8 @@ public:
return CollectorPolicy::G1CollectorPolicyKind;
}
G1GCPhaseTimes* phase_times() const { return _phase_times; }
// Check the current value of the young list RSet lengths and
// compare it against the last prediction. If the current value is
// higher, recalculate the young list target length prediction.
@ -772,10 +705,6 @@ public:
void record_concurrent_mark_init_end(double
mark_init_elapsed_time_ms);
void record_root_region_scan_wait_time(double time_ms) {
_root_region_scan_wait_time_ms = time_ms;
}
void record_concurrent_mark_remark_start();
void record_concurrent_mark_remark_end();
@ -784,97 +713,14 @@ public:
void record_concurrent_mark_cleanup_completed();
void record_concurrent_pause();
void record_concurrent_pause_end();
void record_collection_pause_end(int no_of_gc_threads);
void record_collection_pause_end(double pause_time);
void print_heap_transition();
// Record the fact that a full collection occurred.
void record_full_collection_start();
void record_full_collection_end();
void record_gc_worker_start_time(int worker_i, double ms) {
_par_last_gc_worker_start_times_ms[worker_i] = ms;
}
void record_ext_root_scan_time(int worker_i, double ms) {
_par_last_ext_root_scan_times_ms[worker_i] = ms;
}
void record_satb_filtering_time(int worker_i, double ms) {
_par_last_satb_filtering_times_ms[worker_i] = ms;
}
void record_update_rs_time(int thread, double ms) {
_par_last_update_rs_times_ms[thread] = ms;
}
void record_update_rs_processed_buffers (int thread,
double processed_buffers) {
_par_last_update_rs_processed_buffers[thread] = processed_buffers;
}
void record_scan_rs_time(int thread, double ms) {
_par_last_scan_rs_times_ms[thread] = ms;
}
void reset_obj_copy_time(int thread) {
_par_last_obj_copy_times_ms[thread] = 0.0;
}
void reset_obj_copy_time() {
reset_obj_copy_time(0);
}
void record_obj_copy_time(int thread, double ms) {
_par_last_obj_copy_times_ms[thread] += ms;
}
void record_termination(int thread, double ms, size_t attempts) {
_par_last_termination_times_ms[thread] = ms;
_par_last_termination_attempts[thread] = (double) attempts;
}
void record_gc_worker_end_time(int worker_i, double ms) {
_par_last_gc_worker_end_times_ms[worker_i] = ms;
}
void record_pause_time_ms(double ms) {
_last_pause_time_ms = ms;
}
void record_clear_ct_time(double ms) {
_cur_clear_ct_time_ms = ms;
}
void record_par_time(double ms) {
_cur_collection_par_time_ms = ms;
}
void record_code_root_fixup_time(double ms) {
_cur_collection_code_root_fixup_time_ms = ms;
}
void record_ref_proc_time(double ms) {
_cur_ref_proc_time_ms = ms;
}
void record_ref_enq_time(double ms) {
_cur_ref_enq_time_ms = ms;
}
#ifndef PRODUCT
void record_cc_clear_time(double ms) {
if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms)
_min_clear_cc_time_ms = ms;
if (_max_clear_cc_time_ms < 0.0 || ms >= _max_clear_cc_time_ms)
_max_clear_cc_time_ms = ms;
_cur_clear_cc_time_ms = ms;
_cum_clear_cc_time_ms += ms;
_num_cc_clears++;
}
#endif
// Record how much space we copied during a GC. This is typically
// called when a GC alloc region is being retired.
void record_bytes_copied_during_gc(size_t bytes) {

View File

@ -0,0 +1,379 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1Log.hpp"
// Helper class for avoiding interleaved logging
class LineBuffer: public StackObj {
private:
static const int BUFFER_LEN = 1024;
static const int INDENT_CHARS = 3;
char _buffer[BUFFER_LEN];
int _indent_level;
int _cur;
void vappend(const char* format, va_list ap) {
int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap);
if (res != -1) {
_cur += res;
} else {
DEBUG_ONLY(warning("buffer too small in LineBuffer");)
_buffer[BUFFER_LEN -1] = 0;
_cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again
}
}
public:
explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) {
for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) {
_buffer[_cur] = ' ';
}
}
#ifndef PRODUCT
~LineBuffer() {
assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?");
}
#endif
void append(const char* format, ...) {
va_list ap;
va_start(ap, format);
vappend(format, ap);
va_end(ap);
}
void append_and_print_cr(const char* format, ...) {
va_list ap;
va_start(ap, format);
vappend(format, ap);
va_end(ap);
gclog_or_tty->print_cr("%s", _buffer);
_cur = _indent_level * INDENT_CHARS;
}
};
G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
_max_gc_threads(max_gc_threads),
_min_clear_cc_time_ms(-1.0),
_max_clear_cc_time_ms(-1.0),
_cur_clear_cc_time_ms(0.0),
_cum_clear_cc_time_ms(0.0),
_num_cc_clears(0L)
{
assert(max_gc_threads > 0, "Must have some GC threads");
_par_last_gc_worker_start_times_ms = new double[_max_gc_threads];
_par_last_ext_root_scan_times_ms = new double[_max_gc_threads];
_par_last_satb_filtering_times_ms = new double[_max_gc_threads];
_par_last_update_rs_times_ms = new double[_max_gc_threads];
_par_last_update_rs_processed_buffers = new double[_max_gc_threads];
_par_last_scan_rs_times_ms = new double[_max_gc_threads];
_par_last_obj_copy_times_ms = new double[_max_gc_threads];
_par_last_termination_times_ms = new double[_max_gc_threads];
_par_last_termination_attempts = new double[_max_gc_threads];
_par_last_gc_worker_end_times_ms = new double[_max_gc_threads];
_par_last_gc_worker_times_ms = new double[_max_gc_threads];
_par_last_gc_worker_other_times_ms = new double[_max_gc_threads];
}
void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads,
bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) {
assert(active_gc_threads > 0, "The number of threads must be > 0");
assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max nubmer of threads");
_active_gc_threads = active_gc_threads;
_pause_start_time_sec = pause_start_time_sec;
_is_young_gc = is_young_gc;
_is_initial_mark_gc = is_initial_mark_gc;
_gc_cause = gc_cause;
#ifdef ASSERT
// initialise the timing data to something well known so that we can spot
// if something is not set properly
for (uint i = 0; i < _max_gc_threads; ++i) {
_par_last_gc_worker_start_times_ms[i] = -1234.0;
_par_last_ext_root_scan_times_ms[i] = -1234.0;
_par_last_satb_filtering_times_ms[i] = -1234.0;
_par_last_update_rs_times_ms[i] = -1234.0;
_par_last_update_rs_processed_buffers[i] = -1234.0;
_par_last_scan_rs_times_ms[i] = -1234.0;
_par_last_obj_copy_times_ms[i] = -1234.0;
_par_last_termination_times_ms[i] = -1234.0;
_par_last_termination_attempts[i] = -1234.0;
_par_last_gc_worker_end_times_ms[i] = -1234.0;
_par_last_gc_worker_times_ms[i] = -1234.0;
_par_last_gc_worker_other_times_ms[i] = -1234.0;
}
#endif
}
void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) {
if (G1Log::fine()) {
double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS;
for (uint i = 0; i < _active_gc_threads; i++) {
_par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] -
_par_last_gc_worker_start_times_ms[i];
double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
_par_last_satb_filtering_times_ms[i] +
_par_last_update_rs_times_ms[i] +
_par_last_scan_rs_times_ms[i] +
_par_last_obj_copy_times_ms[i] +
_par_last_termination_times_ms[i];
_par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] -
worker_known_time;
}
print(pause_time_ms);
}
}
void G1GCPhaseTimes::print_par_stats(int level,
const char* str,
double* data,
bool showDecimals) {
double min = data[0], max = data[0];
double total = 0.0;
LineBuffer buf(level);
buf.append("[%s (ms):", str);
for (uint i = 0; i < _active_gc_threads; ++i) {
double val = data[i];
if (val < min)
min = val;
if (val > max)
max = val;
total += val;
if (G1Log::finest()) {
if (showDecimals) {
buf.append(" %.1lf", val);
} else {
buf.append(" %d", (int)val);
}
}
}
if (G1Log::finest()) {
buf.append_and_print_cr("");
}
double avg = total / (double) _active_gc_threads;
if (showDecimals) {
buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]",
min, avg, max, max - min, total);
} else {
buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]",
(int)min, (int)avg, (int)max, (int)max - (int)min, (int)total);
}
}
void G1GCPhaseTimes::print_stats(int level, const char* str, double value) {
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
}
void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) {
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
}
void G1GCPhaseTimes::print_stats(int level, const char* str, int value) {
LineBuffer(level).append_and_print_cr("[%s: %d]", str, value);
}
double G1GCPhaseTimes::avg_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = 0.0;
for (uint i = 0; i < _active_gc_threads; ++i) {
ret += data[i];
}
return ret / (double) _active_gc_threads;
} else {
return data[0];
}
}
double G1GCPhaseTimes::max_value(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double ret = data[0];
for (uint i = 1; i < _active_gc_threads; ++i) {
if (data[i] > ret) {
ret = data[i];
}
}
return ret;
} else {
return data[0];
}
}
double G1GCPhaseTimes::sum_of_values(double* data) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
double sum = 0.0;
for (uint i = 0; i < _active_gc_threads; i++) {
sum += data[i];
}
return sum;
} else {
return data[0];
}
}
double G1GCPhaseTimes::max_sum(double* data1, double* data2) {
double ret = data1[0] + data2[0];
if (G1CollectedHeap::use_parallel_gc_threads()) {
for (uint i = 1; i < _active_gc_threads; ++i) {
double data = data1[i] + data2[i];
if (data > ret) {
ret = data;
}
}
}
return ret;
}
void G1GCPhaseTimes::collapse_par_times() {
_ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
_satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms);
_update_rs_time = avg_value(_par_last_update_rs_times_ms);
_update_rs_processed_buffers =
sum_of_values(_par_last_update_rs_processed_buffers);
_scan_rs_time = avg_value(_par_last_scan_rs_times_ms);
_obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
_termination_time = avg_value(_par_last_termination_times_ms);
}
double G1GCPhaseTimes::accounted_time_ms() {
// Subtract the root region scanning wait time. It's initialized to
// zero at the start of the pause.
double misc_time_ms = _root_region_scan_wait_time_ms;
misc_time_ms += _cur_collection_par_time_ms;
// Now subtract the time taken to fix up roots in generated code
misc_time_ms += _cur_collection_code_root_fixup_time_ms;
// Subtract the time taken to clean the card table from the
// current value of "other time"
misc_time_ms += _cur_clear_ct_time_ms;
return misc_time_ms;
}
void G1GCPhaseTimes::print(double pause_time_ms) {
if (PrintGCTimeStamps) {
gclog_or_tty->stamp();
gclog_or_tty->print(": ");
}
GCCauseString gc_cause_str = GCCauseString("GC pause", _gc_cause)
.append(_is_young_gc ? " (young)" : " (mixed)")
.append(_is_initial_mark_gc ? " (initial-mark)" : "");
gclog_or_tty->print_cr("[%s, %3.7f secs]", (const char*)gc_cause_str, pause_time_ms / 1000.0);
if (!G1Log::finer()) {
return;
}
if (_root_region_scan_wait_time_ms > 0.0) {
print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
}
if (G1CollectedHeap::use_parallel_gc_threads()) {
print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads);
print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
if (_satb_filtering_time > 0.0) {
print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms);
}
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
if (G1Log::finest()) {
print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers,
false /* showDecimals */);
}
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms);
if (G1Log::finest()) {
print_par_stats(3, "Termination Attempts", _par_last_termination_attempts,
false /* showDecimals */);
}
print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms);
print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
} else {
print_stats(1, "Ext Root Scanning", _ext_root_scan_time);
if (_satb_filtering_time > 0.0) {
print_stats(1, "SATB Filtering", _satb_filtering_time);
}
print_stats(1, "Update RS", _update_rs_time);
if (G1Log::finest()) {
print_stats(2, "Processed Buffers", (int)_update_rs_processed_buffers);
}
print_stats(1, "Scan RS", _scan_rs_time);
print_stats(1, "Object Copying", _obj_copy_time);
}
print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
if (Verbose && G1Log::finest()) {
print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms);
print_stats(1, "Min Clear CC", _min_clear_cc_time_ms);
print_stats(1, "Max Clear CC", _max_clear_cc_time_ms);
if (_num_cc_clears > 0) {
print_stats(1, "Avg Clear CC", _cum_clear_cc_time_ms / ((double)_num_cc_clears));
}
}
double misc_time_ms = pause_time_ms - accounted_time_ms();
print_stats(1, "Other", misc_time_ms);
print_stats(2, "Choose CSet",
(_recorded_young_cset_choice_time_ms +
_recorded_non_young_cset_choice_time_ms));
print_stats(2, "Ref Proc", _cur_ref_proc_time_ms);
print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
print_stats(2, "Free CSet",
(_recorded_young_free_cset_time_ms +
_recorded_non_young_free_cset_time_ms));
}
void G1GCPhaseTimes::record_cc_clear_time_ms(double ms) {
if (!(Verbose && G1Log::finest())) {
return;
}
if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms) {
_min_clear_cc_time_ms = ms;
}
if (_max_clear_cc_time_ms < 0.0 || ms >= _max_clear_cc_time_ms) {
_max_clear_cc_time_ms = ms;
}
_cur_clear_cc_time_ms = ms;
_cum_clear_cc_time_ms += ms;
_num_cc_clears++;
}

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
#include "memory/allocation.hpp"
#include "gc_interface/gcCause.hpp"
class G1GCPhaseTimes : public CHeapObj<mtGC> {
friend class G1CollectorPolicy;
friend class TraceGen0TimeData;
private:
uint _active_gc_threads;
uint _max_gc_threads;
GCCause::Cause _gc_cause;
bool _is_young_gc;
bool _is_initial_mark_gc;
double _pause_start_time_sec;
double* _par_last_gc_worker_start_times_ms;
double* _par_last_ext_root_scan_times_ms;
double* _par_last_satb_filtering_times_ms;
double* _par_last_update_rs_times_ms;
double* _par_last_update_rs_processed_buffers;
double* _par_last_scan_rs_times_ms;
double* _par_last_obj_copy_times_ms;
double* _par_last_termination_times_ms;
double* _par_last_termination_attempts;
double* _par_last_gc_worker_end_times_ms;
double* _par_last_gc_worker_times_ms;
double* _par_last_gc_worker_other_times_ms;
double _cur_collection_par_time_ms;
double _cur_collection_code_root_fixup_time_ms;
double _cur_clear_ct_time_ms;
double _cur_ref_proc_time_ms;
double _cur_ref_enq_time_ms;
// Helper methods for detailed logging
void print_par_stats(int level, const char* str, double* data, bool showDecimals = true);
void print_stats(int level, const char* str, double value);
void print_stats(int level, const char* str, double value, int workers);
void print_stats(int level, const char* str, int value);
double avg_value(double* data);
double max_value(double* data);
double sum_of_values(double* data);
double max_sum(double* data1, double* data2);
double accounted_time_ms();
// Card Table Count Cache stats
double _min_clear_cc_time_ms; // min
double _max_clear_cc_time_ms; // max
double _cur_clear_cc_time_ms; // clearing time during current pause
double _cum_clear_cc_time_ms; // cummulative clearing time
jlong _num_cc_clears; // number of times the card count cache has been cleared
// The following insance variables are directly accessed by G1CollectorPolicy
// and TraceGen0TimeData. This is why those classes are declared friends.
// An alternative is to add getters and setters for all of these fields.
// It might also be possible to restructure the code to reduce these
// dependencies.
double _ext_root_scan_time;
double _satb_filtering_time;
double _update_rs_time;
double _update_rs_processed_buffers;
double _scan_rs_time;
double _obj_copy_time;
double _termination_time;
double _cur_collection_start_sec;
double _root_region_scan_wait_time_ms;
double _recorded_young_cset_choice_time_ms;
double _recorded_non_young_cset_choice_time_ms;
double _recorded_young_free_cset_time_ms;
double _recorded_non_young_free_cset_time_ms;
void print(double pause_time_ms);
public:
G1GCPhaseTimes(uint max_gc_threads);
void note_gc_start(double pause_start_time_sec, uint active_gc_threads,
bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause);
void note_gc_end(double pause_end_time_sec);
void collapse_par_times();
void record_gc_worker_start_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_gc_worker_start_times_ms[worker_i] = ms;
}
void record_ext_root_scan_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_ext_root_scan_times_ms[worker_i] = ms;
}
void record_satb_filtering_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_satb_filtering_times_ms[worker_i] = ms;
}
void record_update_rs_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_update_rs_times_ms[worker_i] = ms;
}
void record_update_rs_processed_buffers (uint worker_i,
double processed_buffers) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_update_rs_processed_buffers[worker_i] = processed_buffers;
}
void record_scan_rs_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_scan_rs_times_ms[worker_i] = ms;
}
void reset_obj_copy_time(uint worker_i) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_obj_copy_times_ms[worker_i] = 0.0;
}
void reset_obj_copy_time() {
reset_obj_copy_time(0);
}
void record_obj_copy_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_obj_copy_times_ms[worker_i] += ms;
}
void record_termination(uint worker_i, double ms, size_t attempts) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_termination_times_ms[worker_i] = ms;
_par_last_termination_attempts[worker_i] = (double) attempts;
}
void record_gc_worker_end_time(uint worker_i, double ms) {
assert(worker_i >= 0, "worker index must be > 0");
assert(worker_i < _active_gc_threads, "worker index out of bounds");
_par_last_gc_worker_end_times_ms[worker_i] = ms;
}
void record_clear_ct_time(double ms) {
_cur_clear_ct_time_ms = ms;
}
void record_par_time(double ms) {
_cur_collection_par_time_ms = ms;
}
void record_code_root_fixup_time(double ms) {
_cur_collection_code_root_fixup_time_ms = ms;
}
void record_ref_proc_time(double ms) {
_cur_ref_proc_time_ms = ms;
}
void record_ref_enq_time(double ms) {
_cur_ref_enq_time_ms = ms;
}
void record_root_region_scan_wait_time(double time_ms) {
_root_region_scan_wait_time_ms = time_ms;
}
void record_cc_clear_time_ms(double ms);
void record_young_free_cset_time_ms(double time_ms) {
_recorded_young_free_cset_time_ms = time_ms;
}
void record_non_young_free_cset_time_ms(double time_ms) {
_recorded_non_young_free_cset_time_ms = time_ms;
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP

View File

@ -29,6 +29,7 @@
#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
@ -224,7 +225,7 @@ void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
assert( _cards_scanned != NULL, "invariant" );
_cards_scanned[worker_i] = scanRScl.cards_done();
_g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
_g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
}
// Closure used for updating RSets and recording references that
@ -276,7 +277,7 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
guarantee(cl.n() == 0, "Card table should be clean.");
}
_g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
_g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
}
class CountRSSizeClosure: public HeapRegionClosure {
@ -390,13 +391,13 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
if (G1UseParallelRSetUpdating || (worker_i == 0)) {
updateRS(&into_cset_dcq, worker_i);
} else {
_g1p->record_update_rs_processed_buffers(worker_i, 0.0);
_g1p->record_update_rs_time(worker_i, 0.0);
_g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0.0);
_g1p->phase_times()->record_update_rs_time(worker_i, 0.0);
}
if (G1UseParallelRSetScanning || (worker_i == 0)) {
scanRS(oc, worker_i);
} else {
_g1p->record_scan_rs_time(worker_i, 0.0);
_g1p->phase_times()->record_scan_rs_time(worker_i, 0.0);
}
// We now clear the cached values of _cset_rs_update_cl for this worker

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -375,7 +375,6 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
Handle h_exception(thread, exception);
methodHandle h_method (thread, method(thread));
constantPoolHandle h_constants(thread, h_method->constants());
typeArrayHandle h_extable (thread, h_method->exception_table());
bool should_repeat;
int handler_bci;
int current_bci = bci(thread);
@ -547,23 +546,6 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode
}
}
if (is_put && !is_static && klass->is_subclass_of(SystemDictionary::CallSite_klass()) && (info.name() == vmSymbols::target_name())) {
const jint direction = frame::interpreter_frame_expression_stack_direction();
Handle call_site (THREAD, *((oop*) thread->last_frame().interpreter_frame_tos_at(-1 * direction)));
Handle method_handle(THREAD, *((oop*) thread->last_frame().interpreter_frame_tos_at( 0 * direction)));
assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be");
assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be");
{
// Walk all nmethods depending on this call site.
MutexLocker mu(Compile_lock, thread);
Universe::flush_dependents_on(call_site, method_handle);
}
// Don't allow fast path for setting CallSite.target and sub-classes.
put_code = (Bytecodes::Code) 0;
}
cache_entry(thread)->set_field(
get_code,
put_code,

View File

@ -231,8 +231,6 @@ public:
if (obj->is_constMethod()) {
mark_object(obj);
mark_object(constMethodOop(obj)->stackmap_data());
// Exception tables are needed by ci code during compilation.
mark_object(constMethodOop(obj)->exception_table());
}
// Mark objects referenced by klass objects which are read-only.
@ -513,7 +511,6 @@ public:
for(i = 0; i < methods->length(); i++) {
methodOop m = methodOop(methods->obj_at(i));
mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro);
mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro);
mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro);
}

View File

@ -140,14 +140,15 @@ klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_
constMethodOop oopFactory::new_constMethod(int byte_code_size,
int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS) {
klassOop cmkObj = Universe::constMethodKlassObj();
constMethodKlass* cmk = constMethodKlass::cast(cmkObj);
return cmk->allocate(byte_code_size, compressed_line_number_size,
localvariable_table_length, checked_exceptions_length,
is_conc_safe,
localvariable_table_length, exception_table_length,
checked_exceptions_length, is_conc_safe,
CHECK_NULL);
}
@ -155,6 +156,7 @@ constMethodOop oopFactory::new_constMethod(int byte_code_size,
methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags,
int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS) {
@ -164,6 +166,7 @@ methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags,
constMethodOop cm = new_constMethod(byte_code_size,
compressed_line_number_size,
localvariable_table_length,
exception_table_length,
checked_exceptions_length,
is_conc_safe, CHECK_NULL);
constMethodHandle rw(THREAD, cm);

View File

@ -86,6 +86,7 @@ private:
static constMethodOop new_constMethod(int byte_code_size,
int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS);
@ -97,6 +98,7 @@ public:
AccessFlags access_flags,
int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS);

View File

@ -65,6 +65,7 @@ bool constMethodKlass::oop_is_conc_safe(oop obj) const {
constMethodOop constMethodKlass::allocate(int byte_code_size,
int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS) {
@ -72,6 +73,7 @@ constMethodOop constMethodKlass::allocate(int byte_code_size,
int size = constMethodOopDesc::object_size(byte_code_size,
compressed_line_number_size,
localvariable_table_length,
exception_table_length,
checked_exceptions_length);
KlassHandle h_k(THREAD, as_klassOop());
constMethodOop cm = (constMethodOop)
@ -82,12 +84,12 @@ constMethodOop constMethodKlass::allocate(int byte_code_size,
cm->init_fingerprint();
cm->set_constants(NULL);
cm->set_stackmap_data(NULL);
cm->set_exception_table(NULL);
cm->set_code_size(byte_code_size);
cm->set_constMethod_size(size);
cm->set_inlined_tables_length(checked_exceptions_length,
compressed_line_number_size,
localvariable_table_length);
localvariable_table_length,
exception_table_length);
assert(cm->size() == size, "wrong size for object");
cm->set_is_conc_safe(is_conc_safe);
cm->set_partially_loaded();
@ -100,7 +102,6 @@ void constMethodKlass::oop_follow_contents(oop obj) {
constMethodOop cm = constMethodOop(obj);
MarkSweep::mark_and_push(cm->adr_constants());
MarkSweep::mark_and_push(cm->adr_stackmap_data());
MarkSweep::mark_and_push(cm->adr_exception_table());
// Performance tweak: We skip iterating over the klass pointer since we
// know that Universe::constMethodKlassObj never moves.
}
@ -112,7 +113,6 @@ void constMethodKlass::oop_follow_contents(ParCompactionManager* cm,
constMethodOop cm_oop = constMethodOop(obj);
PSParallelCompact::mark_and_push(cm, cm_oop->adr_constants());
PSParallelCompact::mark_and_push(cm, cm_oop->adr_stackmap_data());
PSParallelCompact::mark_and_push(cm, cm_oop->adr_exception_table());
// Performance tweak: We skip iterating over the klass pointer since we
// know that Universe::constMethodKlassObj never moves.
}
@ -123,7 +123,6 @@ int constMethodKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
constMethodOop cm = constMethodOop(obj);
blk->do_oop(cm->adr_constants());
blk->do_oop(cm->adr_stackmap_data());
blk->do_oop(cm->adr_exception_table());
// Get size before changing pointers.
// Don't call size() or oop_size() since that is a virtual call.
int size = cm->object_size();
@ -139,8 +138,6 @@ int constMethodKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr)
if (mr.contains(adr)) blk->do_oop(adr);
adr = cm->adr_stackmap_data();
if (mr.contains(adr)) blk->do_oop(adr);
adr = cm->adr_exception_table();
if (mr.contains(adr)) blk->do_oop(adr);
// Get size before changing pointers.
// Don't call size() or oop_size() since that is a virtual call.
int size = cm->object_size();
@ -155,7 +152,6 @@ int constMethodKlass::oop_adjust_pointers(oop obj) {
constMethodOop cm = constMethodOop(obj);
MarkSweep::adjust_pointer(cm->adr_constants());
MarkSweep::adjust_pointer(cm->adr_stackmap_data());
MarkSweep::adjust_pointer(cm->adr_exception_table());
// Get size before changing pointers.
// Don't call size() or oop_size() since that is a virtual call.
int size = cm->object_size();
@ -190,7 +186,6 @@ void constMethodKlass::oop_print_on(oop obj, outputStream* st) {
constMethodOop m = constMethodOop(obj);
st->print(" - constants: " INTPTR_FORMAT " ", (address)m->constants());
m->constants()->print_value_on(st); st->cr();
st->print(" - exceptions: " INTPTR_FORMAT "\n", (address)m->exception_table());
if (m->has_stackmap_table()) {
st->print(" - stackmap data: ");
m->stackmap_data()->print_value_on(st);
@ -228,8 +223,6 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
typeArrayOop stackmap_data = m->stackmap_data();
guarantee(stackmap_data == NULL ||
stackmap_data->is_perm(), "should be in permspace");
guarantee(m->exception_table()->is_perm(), "should be in permspace");
guarantee(m->exception_table()->is_typeArray(), "should be type array");
address m_end = (address)((oop*) m + m->size());
address compressed_table_start = m->code_end();
@ -244,11 +237,15 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
compressed_table_end += stream.position();
}
guarantee(compressed_table_end <= m_end, "invalid method layout");
// Verify checked exceptions and local variable tables
// Verify checked exceptions, exception table and local variable tables
if (m->has_checked_exceptions()) {
u2* addr = m->checked_exceptions_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
}
if (m->has_exception_handler()) {
u2* addr = m->exception_table_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
}
if (m->has_localvariable_table()) {
u2* addr = m->localvariable_table_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
@ -257,12 +254,12 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
u2* uncompressed_table_start;
if (m->has_localvariable_table()) {
uncompressed_table_start = (u2*) m->localvariable_table_start();
} else {
if (m->has_checked_exceptions()) {
} else if (m->has_exception_handler()) {
uncompressed_table_start = (u2*) m->exception_table_start();
} else if (m->has_checked_exceptions()) {
uncompressed_table_start = (u2*) m->checked_exceptions_start();
} else {
} else {
uncompressed_table_start = (u2*) m_end;
}
}
int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;
int max_gap = align_object_size(1)*BytesPerWord;
@ -273,8 +270,8 @@ void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
bool constMethodKlass::oop_partially_loaded(oop obj) const {
assert(obj->is_constMethod(), "object must be klass");
constMethodOop m = constMethodOop(obj);
// check whether exception_table points to self (flag for partially loaded)
return m->exception_table() == (typeArrayOop)obj;
// check whether stackmap_data points to self (flag for partially loaded)
return m->stackmap_data() == (typeArrayOop)obj;
}
@ -282,6 +279,6 @@ bool constMethodKlass::oop_partially_loaded(oop obj) const {
void constMethodKlass::oop_set_partially_loaded(oop obj) {
assert(obj->is_constMethod(), "object must be klass");
constMethodOop m = constMethodOop(obj);
// Temporarily set exception_table to point to self
m->set_exception_table((typeArrayOop)obj);
// Temporarily set stackmap_data to point to self
m->set_stackmap_data((typeArrayOop)obj);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,6 +46,7 @@ public:
DEFINE_ALLOCATE_PERMANENT(constMethodKlass);
constMethodOop allocate(int byte_code_size, int compressed_line_number_size,
int localvariable_table_length,
int exception_table_length,
int checked_exceptions_length,
bool is_conc_safe,
TRAPS);

View File

@ -35,6 +35,7 @@ const u2 constMethodOopDesc::UNSET_IDNUM = 0xFFFF;
int constMethodOopDesc::object_size(int code_size,
int compressed_line_number_size,
int local_variable_table_length,
int exception_table_length,
int checked_exceptions_length) {
int extra_bytes = code_size;
if (compressed_line_number_size > 0) {
@ -49,6 +50,10 @@ int constMethodOopDesc::object_size(int code_size,
extra_bytes +=
local_variable_table_length * sizeof(LocalVariableTableElement);
}
if (exception_table_length > 0) {
extra_bytes += sizeof(u2);
extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
}
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
return align_object_size(header_size() + extra_words);
}
@ -73,23 +78,40 @@ u2* constMethodOopDesc::checked_exceptions_length_addr() const {
return last_u2_element();
}
u2* constMethodOopDesc::localvariable_table_length_addr() const {
assert(has_localvariable_table(), "called only if table is present");
u2* constMethodOopDesc::exception_table_length_addr() const {
assert(has_exception_handler(), "called only if table is present");
if (has_checked_exceptions()) {
// If checked_exception present, locate immediately before them.
return (u2*) checked_exceptions_start() - 1;
} else {
// Else, the linenumber table is at the end of the constMethod.
// Else, the exception table is at the end of the constMethod.
return last_u2_element();
}
}
u2* constMethodOopDesc::localvariable_table_length_addr() const {
assert(has_localvariable_table(), "called only if table is present");
if (has_exception_handler()) {
// If exception_table present, locate immediately before them.
return (u2*) exception_table_start() - 1;
} else {
if (has_checked_exceptions()) {
// If checked_exception present, locate immediately before them.
return (u2*) checked_exceptions_start() - 1;
} else {
// Else, the linenumber table is at the end of the constMethod.
return last_u2_element();
}
}
}
// Update the flags to indicate the presence of these optional fields.
void constMethodOopDesc::set_inlined_tables_length(
int checked_exceptions_len,
int compressed_line_number_size,
int localvariable_table_len) {
int localvariable_table_len,
int exception_table_len) {
// Must be done in the order below, otherwise length_addr accessors
// will not work. Only set bit in header if length is positive.
assert(_flags == 0, "Error");
@ -100,6 +122,10 @@ void constMethodOopDesc::set_inlined_tables_length(
_flags |= _has_checked_exceptions;
*(checked_exceptions_length_addr()) = checked_exceptions_len;
}
if (exception_table_len > 0) {
_flags |= _has_exception_table;
*(exception_table_length_addr()) = exception_table_len;
}
if (localvariable_table_len > 0) {
_flags |= _has_localvariable_table;
*(localvariable_table_length_addr()) = localvariable_table_len;
@ -133,3 +159,15 @@ LocalVariableTableElement* constMethodOopDesc::localvariable_table_start() const
addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);
return (LocalVariableTableElement*) addr;
}
int constMethodOopDesc::exception_table_length() const {
return has_exception_handler() ? *(exception_table_length_addr()) : 0;
}
ExceptionTableElement* constMethodOopDesc::exception_table_start() const {
u2* addr = exception_table_length_addr();
u2 length = *addr;
assert(length > 0, "should only be called if table is present");
addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);
return (ExceptionTableElement*)addr;
}

View File

@ -43,7 +43,6 @@
// | fingerprint 2 |
// | constants (oop) |
// | stackmap_data (oop) |
// | exception_table (oop) |
// | constMethod_size |
// | interp_kind | flags | code_size |
// | name index | signature index |
@ -64,7 +63,13 @@
// | (length is u2, elements are 6-tuples of u2) |
// | (see class LocalVariableTableElement) |
// | (access flags bit tells whether table is present) |
// | (indexed from end of contMethodOop) |
// | (indexed from end of constMethodOop) |
// |------------------------------------------------------|
// | exception table + length (length last) |
// | (length is u2, elements are 4-tuples of u2) |
// | (see class ExceptionTableElement) |
// | (access flags bit tells whether table is present) |
// | (indexed from end of constMethodOop) |
// |------------------------------------------------------|
// | checked exceptions elements + length (length last) |
// | (length is u2, elements are u2) |
@ -93,6 +98,15 @@ class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
};
// Utitily class describing elements in exception table
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
public:
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type_index;
};
class constMethodOopDesc : public oopDesc {
friend class constMethodKlass;
friend class VMStructs;
@ -100,7 +114,8 @@ private:
enum {
_has_linenumber_table = 1,
_has_checked_exceptions = 2,
_has_localvariable_table = 4
_has_localvariable_table = 4,
_has_exception_table = 8
};
// Bit vector of signature
@ -114,7 +129,7 @@ private:
public:
oop* oop_block_beg() const { return adr_constants(); }
oop* oop_block_end() const { return adr_exception_table() + 1; }
oop* oop_block_end() const { return adr_stackmap_data() + 1; }
private:
//
@ -126,11 +141,6 @@ private:
// Raw stackmap data for the method
typeArrayOop _stackmap_data;
// The exception handler table. 4-tuples of ints [start_pc, end_pc,
// handler_pc, catch_type index] For methods with no exceptions the
// table is pointing to Universe::the_empty_int_array
typeArrayOop _exception_table;
//
// End of the oop block.
//
@ -152,7 +162,8 @@ public:
// Inlined tables
void set_inlined_tables_length(int checked_exceptions_len,
int compressed_line_number_size,
int localvariable_table_len);
int localvariable_table_len,
int exception_table_len);
bool has_linenumber_table() const
{ return (_flags & _has_linenumber_table) != 0; }
@ -163,6 +174,9 @@ public:
bool has_localvariable_table() const
{ return (_flags & _has_localvariable_table) != 0; }
bool has_exception_handler() const
{ return (_flags & _has_exception_table) != 0; }
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
int interpreter_kind(void) const { return _interpreter_kind; }
@ -181,11 +195,6 @@ public:
}
bool has_stackmap_table() const { return _stackmap_data != NULL; }
// exception handler table
typeArrayOop exception_table() const { return _exception_table; }
void set_exception_table(typeArrayOop e) { oop_store_without_check((oop*) &_exception_table, (oop) e); }
bool has_exception_handler() const { return exception_table() != NULL && exception_table()->length() > 0; }
void init_fingerprint() {
const uint64_t initval = CONST64(0x8000000000000000);
_fingerprint = initval;
@ -235,6 +244,7 @@ public:
// Object size needed
static int object_size(int code_size, int compressed_line_number_size,
int local_variable_table_length,
int exception_table_length,
int checked_exceptions_length);
int object_size() const { return _constMethod_size; }
@ -256,6 +266,7 @@ public:
u_char* compressed_linenumber_table() const; // not preserved by gc
u2* checked_exceptions_length_addr() const;
u2* localvariable_table_length_addr() const;
u2* exception_table_length_addr() const;
// checked exceptions
int checked_exceptions_length() const;
@ -265,6 +276,10 @@ public:
int localvariable_table_length() const;
LocalVariableTableElement* localvariable_table_start() const;
// exception table
int exception_table_length() const;
ExceptionTableElement* exception_table_start() const;
// byte codes
void set_code(address code) {
if (code_size() > 0) {
@ -282,13 +297,10 @@ public:
// interpreter support
static ByteSize constants_offset()
{ return byte_offset_of(constMethodOopDesc, _constants); }
static ByteSize exception_table_offset()
{ return byte_offset_of(constMethodOopDesc, _exception_table); }
// Garbage collection support
oop* adr_constants() const { return (oop*)&_constants; }
oop* adr_stackmap_data() const { return (oop*)&_stackmap_data; }
oop* adr_exception_table() const { return (oop*)&_exception_table; }
bool is_conc_safe() { return _is_conc_safe; }
void set_is_conc_safe(bool v) { _is_conc_safe = v; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -400,10 +400,9 @@ void GenerateOopMap::mark_bbheaders_and_count_gc_points() {
bool fellThrough = false; // False to get first BB marked.
// First mark all exception handlers as start of a basic-block
typeArrayOop excps = method()->exception_table();
for(int i = 0; i < excps->length(); i += 4) {
int handler_pc_idx = i+2;
bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL);
ExceptionTable excps(method());
for(int i = 0; i < excps.length(); i ++) {
bb_mark_fct(this, excps.handler_pc(i), NULL);
}
// Then iterate through the code
@ -450,10 +449,9 @@ void GenerateOopMap::mark_reachable_code() {
// Mark entry basic block as alive and all exception handlers
_basic_blocks[0].mark_as_alive();
typeArrayOop excps = method()->exception_table();
for(int i = 0; i < excps->length(); i += 4) {
int handler_pc_idx = i+2;
BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx));
ExceptionTable excps(method());
for(int i = 0; i < excps.length(); i++) {
BasicBlock *bb = get_basic_block_at(excps.handler_pc(i));
// If block is not already alive (due to multiple exception handlers to same bb), then
// make it alive
if (bb->is_dead()) bb->mark_as_alive();
@ -1181,12 +1179,12 @@ void GenerateOopMap::do_exception_edge(BytecodeStream* itr) {
if (_has_exceptions) {
int bci = itr->bci();
typeArrayOop exct = method()->exception_table();
for(int i = 0; i< exct->length(); i+=4) {
int start_pc = exct->int_at(i);
int end_pc = exct->int_at(i+1);
int handler_pc = exct->int_at(i+2);
int catch_type = exct->int_at(i+3);
ExceptionTable exct(method());
for(int i = 0; i< exct.length(); i++) {
int start_pc = exct.start_pc(i);
int end_pc = exct.end_pc(i);
int handler_pc = exct.handler_pc(i);
int catch_type = exct.catch_type_index(i);
if (start_pc <= bci && bci < end_pc) {
BasicBlock *excBB = get_basic_block_at(handler_pc);
@ -2055,7 +2053,7 @@ void GenerateOopMap::compute_map(TRAPS) {
_conflict = false;
_max_locals = method()->max_locals();
_max_stack = method()->max_stack();
_has_exceptions = (method()->exception_table()->length() > 0);
_has_exceptions = (method()->has_exception_handler());
_nof_refval_conflicts = 0;
_init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars
_report_result = false;
@ -2070,9 +2068,10 @@ void GenerateOopMap::compute_map(TRAPS) {
if (Verbose) {
_method->print_codes();
tty->print_cr("Exception table:");
typeArrayOop excps = method()->exception_table();
for(int i = 0; i < excps->length(); i += 4) {
tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2));
ExceptionTable excps(method());
for(int i = 0; i < excps.length(); i ++) {
tty->print_cr("[%d - %d] -> %d",
excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i));
}
}
}

View File

@ -111,25 +111,21 @@ char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, Symbol* method_name,
int methodOopDesc::fast_exception_handler_bci_for(KlassHandle ex_klass, int throw_bci, TRAPS) {
// exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index)
const int beg_bci_offset = 0;
const int end_bci_offset = 1;
const int handler_bci_offset = 2;
const int klass_index_offset = 3;
const int entry_size = 4;
// access exception table
typeArrayHandle table (THREAD, constMethod()->exception_table());
int length = table->length();
assert(length % entry_size == 0, "exception table format has changed");
ExceptionTable table(this);
int length = table.length();
// iterate through all entries sequentially
constantPoolHandle pool(THREAD, constants());
for (int i = 0; i < length; i += entry_size) {
int beg_bci = table->int_at(i + beg_bci_offset);
int end_bci = table->int_at(i + end_bci_offset);
for (int i = 0; i < length; i ++) {
//reacquire the table in case a GC happened
ExceptionTable table(this);
int beg_bci = table.start_pc(i);
int end_bci = table.end_pc(i);
assert(beg_bci <= end_bci, "inconsistent exception table");
if (beg_bci <= throw_bci && throw_bci < end_bci) {
// exception handler bci range covers throw_bci => investigate further
int handler_bci = table->int_at(i + handler_bci_offset);
int klass_index = table->int_at(i + klass_index_offset);
int handler_bci = table.handler_pc(i);
int klass_index = table.catch_type_index(i);
if (klass_index == 0) {
return handler_bci;
} else if (ex_klass.is_null()) {
@ -980,7 +976,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
{
int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
0, 0, 0, IsSafeConc, CHECK_(empty));
0, 0, 0, 0, IsSafeConc, CHECK_(empty));
m = methodHandle(THREAD, m_oop);
}
m->set_constants(cp());
@ -994,7 +990,6 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
m->set_result_index(rtf.type());
#endif
m->compute_size_of_parameters(THREAD);
m->set_exception_table(Universe::the_empty_int_array());
m->init_intrinsic_id();
assert(m->intrinsic_id() == vmIntrinsics::_invokeExact ||
m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker");
@ -1038,6 +1033,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
AccessFlags flags = m->access_flags();
int checked_exceptions_len = m->checked_exceptions_length();
int localvariable_len = m->localvariable_table_length();
int exception_table_len = m->exception_table_length();
// Allocate newm_oop with the is_conc_safe parameter set
// to IsUnsafeConc to indicate that newm_oop is not yet
// safe for concurrent processing by a GC.
@ -1045,6 +1041,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
flags,
new_compressed_linenumber_size,
localvariable_len,
exception_table_len,
checked_exceptions_len,
IsUnsafeConc,
CHECK_(methodHandle()));
@ -1085,6 +1082,7 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
newm->set_method_size(new_method_size);
assert(newm->code_size() == new_code_length, "check");
assert(newm->checked_exceptions_length() == checked_exceptions_len, "check");
assert(newm->exception_table_length() == exception_table_len, "check");
assert(newm->localvariable_table_length() == localvariable_len, "check");
// Copy new byte codes
memcpy(newm->code_base(), new_code, new_code_length);
@ -1100,6 +1098,12 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod
m->checked_exceptions_start(),
checked_exceptions_len * sizeof(CheckedExceptionElement));
}
// Copy exception table
if (exception_table_len > 0) {
memcpy(newm->exception_table_start(),
m->exception_table_start(),
exception_table_len * sizeof(ExceptionTableElement));
}
// Copy local variable number table
if (localvariable_len > 0) {
memcpy(newm->localvariable_table_start(),

View File

@ -122,8 +122,9 @@ class methodOopDesc : public oopDesc {
u2 _max_locals; // Number of local variables used by this method
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
u1 _jfr_towrite : 1, // Flags
: 7;
u1 _jfr_towrite : 1, // Flags
_force_inline : 1,
: 6;
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
u2 _number_of_breakpoints; // fullspeed debugging support
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
@ -282,12 +283,12 @@ class methodOopDesc : public oopDesc {
}
// exception handler table
typeArrayOop exception_table() const
{ return constMethod()->exception_table(); }
void set_exception_table(typeArrayOop e)
{ constMethod()->set_exception_table(e); }
bool has_exception_handler() const
{ return constMethod()->has_exception_handler(); }
int exception_table_length() const
{ return constMethod()->exception_table_length(); }
ExceptionTableElement* exception_table_start() const
{ return constMethod()->exception_table_start(); }
// Finds the first entry point bci of an exception handler for an
// exception of klass ex_klass thrown at throw_bci. A value of NULL
@ -655,6 +656,9 @@ class methodOopDesc : public oopDesc {
bool jfr_towrite() { return _jfr_towrite; }
void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
bool force_inline() { return _force_inline; }
void set_force_inline(bool fi) { _force_inline = fi; }
// On-stack replacement support
bool has_osr_nmethod(int level, bool match_level) {
return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
@ -835,4 +839,66 @@ class BreakpointInfo : public CHeapObj<mtClass> {
void clear(methodOop method);
};
// Utility class for access exception handlers
class ExceptionTable : public StackObj {
private:
ExceptionTableElement* _table;
u2 _length;
public:
ExceptionTable(methodOop m) {
if (m->has_exception_handler()) {
_table = m->exception_table_start();
_length = m->exception_table_length();
} else {
_table = NULL;
_length = 0;
}
}
int length() const {
return _length;
}
u2 start_pc(int idx) const {
assert(idx < _length, "out of bounds");
return _table[idx].start_pc;
}
void set_start_pc(int idx, u2 value) {
assert(idx < _length, "out of bounds");
_table[idx].start_pc = value;
}
u2 end_pc(int idx) const {
assert(idx < _length, "out of bounds");
return _table[idx].end_pc;
}
void set_end_pc(int idx, u2 value) {
assert(idx < _length, "out of bounds");
_table[idx].end_pc = value;
}
u2 handler_pc(int idx) const {
assert(idx < _length, "out of bounds");
return _table[idx].handler_pc;
}
void set_handler_pc(int idx, u2 value) {
assert(idx < _length, "out of bounds");
_table[idx].handler_pc = value;
}
u2 catch_type_index(int idx) const {
assert(idx < _length, "out of bounds");
return _table[idx].catch_type_index;
}
void set_catch_type_index(int idx, u2 value) {
assert(idx < _length, "out of bounds");
_table[idx].catch_type_index = value;
}
};
#endif // SHARE_VM_OOPS_METHODOOP_HPP

View File

@ -757,6 +757,7 @@ void PhaseGVN::dead_loop_check( Node *n ) {
//------------------------------PhaseIterGVN-----------------------------------
// Initialize hash table to fresh and clean for +VerifyOpto
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
_stack(C->unique() >> 1),
_delay_transform(false) {
}
@ -764,6 +765,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(i
// Initialize with previous PhaseIterGVN info; used by PhaseCCP
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
_worklist( igvn->_worklist ),
_stack( igvn->_stack ),
_delay_transform(igvn->_delay_transform)
{
}
@ -772,6 +774,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
// Initialize with previous PhaseGVN info from Parser
PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
_worklist(*C->for_igvn()),
_stack(C->unique() >> 1),
_delay_transform(false)
{
uint max;
@ -1138,51 +1141,77 @@ const Type* PhaseIterGVN::saturate(const Type* new_type, const Type* old_type,
// Kill a globally dead Node. All uses are also globally dead and are
// aggressively trimmed.
void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
assert(dead != C->root(), "killing root, eh?");
if (dead->is_top()) return;
NOT_PRODUCT( set_progress(); )
// Remove from iterative worklist
_worklist.remove(dead);
if (!dead->is_Con()) { // Don't kill cons but uses
// Remove from hash table
_table.hash_delete( dead );
// Smash all inputs to 'dead', isolating him completely
for( uint i = 0; i < dead->req(); i++ ) {
Node *in = dead->in(i);
if( in ) { // Points to something?
dead->set_req(i,NULL); // Kill the edge
if (in->outcnt() == 0 && in != C->top()) {// Made input go dead?
remove_dead_node(in); // Recursively remove
} else if (in->outcnt() == 1 &&
in->has_special_unique_user()) {
_worklist.push(in->unique_out());
} else if (in->outcnt() <= 2 && dead->is_Phi()) {
if( in->Opcode() == Op_Region )
_worklist.push(in);
else if( in->is_Store() ) {
DUIterator_Fast imax, i = in->fast_outs(imax);
_worklist.push(in->fast_out(i));
i++;
if(in->outcnt() == 2) {
_worklist.push(in->fast_out(i));
i++;
enum DeleteProgress {
PROCESS_INPUTS,
PROCESS_OUTPUTS
};
assert(_stack.is_empty(), "not empty");
_stack.push(dead, PROCESS_INPUTS);
while (_stack.is_nonempty()) {
dead = _stack.node();
uint progress_state = _stack.index();
assert(dead != C->root(), "killing root, eh?");
assert(!dead->is_top(), "add check for top when pushing");
NOT_PRODUCT( set_progress(); )
if (progress_state == PROCESS_INPUTS) {
// After following inputs, continue to outputs
_stack.set_index(PROCESS_OUTPUTS);
// Remove from iterative worklist
_worklist.remove(dead);
if (!dead->is_Con()) { // Don't kill cons but uses
bool recurse = false;
// Remove from hash table
_table.hash_delete( dead );
// Smash all inputs to 'dead', isolating him completely
for( uint i = 0; i < dead->req(); i++ ) {
Node *in = dead->in(i);
if( in ) { // Points to something?
dead->set_req(i,NULL); // Kill the edge
if (in->outcnt() == 0 && in != C->top()) {// Made input go dead?
_stack.push(in, PROCESS_INPUTS); // Recursively remove
recurse = true;
} else if (in->outcnt() == 1 &&
in->has_special_unique_user()) {
_worklist.push(in->unique_out());
} else if (in->outcnt() <= 2 && dead->is_Phi()) {
if( in->Opcode() == Op_Region )
_worklist.push(in);
else if( in->is_Store() ) {
DUIterator_Fast imax, i = in->fast_outs(imax);
_worklist.push(in->fast_out(i));
i++;
if(in->outcnt() == 2) {
_worklist.push(in->fast_out(i));
i++;
}
assert(!(i < imax), "sanity");
}
}
assert(!(i < imax), "sanity");
}
}
if (dead->is_macro()) {
C->remove_macro_node(dead);
}
if (recurse) {
continue;
}
}
}
if (dead->is_macro()) {
C->remove_macro_node(dead);
// Aggressively kill globally dead uses
// (Rather than pushing all the outs at once, we push one at a time,
// plus the parent to resume later, because of the indefinite number
// of edge deletions per loop trip.)
if (dead->outcnt() > 0) {
// Recursively remove
_stack.push(dead->raw_out(0), PROCESS_INPUTS);
} else {
_stack.pop();
}
}
// Aggressively kill globally dead uses
// (Cannot use DUIterator_Last because of the indefinite number
// of edge deletions per loop trip.)
while (dead->outcnt() > 0) {
remove_globally_dead_node(dead->raw_out(0));
}
}
//------------------------------subsume_node-----------------------------------

View File

@ -403,6 +403,8 @@ class PhaseIterGVN : public PhaseGVN {
// Subsume users of node 'old' into node 'nn'
void subsume_node( Node *old, Node *nn );
Node_Stack _stack; // Stack used to avoid recursion
protected:
// Idealize new Node 'n' with respect to its inputs and its value
@ -438,8 +440,8 @@ public:
// It is significant only for debugging and profiling.
Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL);
// Kill a globally dead Node. It is allowed to have uses which are
// assumed dead and left 'in limbo'.
// Kill a globally dead Node. All uses are also globally dead and are
// aggressively trimmed.
void remove_globally_dead_node( Node *dead );
// Kill all inputs to a dead node, recursively making more dead nodes.

View File

@ -533,7 +533,17 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) {
CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava();
if (csj->method() != NULL &&
csj->method()->intrinsic_id() == vmIntrinsics::_Integer_toString) {
csj->method()->intrinsic_id() == vmIntrinsics::_Integer_toString &&
arg->outcnt() == 1) {
// _control is the list of StringBuilder calls nodes which
// will be replaced by new String code after this optimization.
// Integer::toString() call is not part of StringBuilder calls
// chain. It could be eliminated only if its result is used
// only by this SB calls chain.
// Another limitation: it should be used only once because
// it is unknown that it is used only by this SB calls chain
// until all related SB calls nodes are collected.
assert(arg->unique_out() == cnode, "sanity");
sc->add_control(csj);
sc->push_int(csj->in(TypeFunc::Parms));
continue;

View File

@ -35,6 +35,7 @@
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/methodOop.hpp"
#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
@ -2183,11 +2184,11 @@ JVM_QUICK_ENTRY(void, JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
typeArrayOop extable = methodOop(method)->exception_table();
entry->start_pc = extable->int_at(entry_index * 4);
entry->end_pc = extable->int_at(entry_index * 4 + 1);
entry->handler_pc = extable->int_at(entry_index * 4 + 2);
entry->catchType = extable->int_at(entry_index * 4 + 3);
ExceptionTable extable((methodOop(method)));
entry->start_pc = extable.start_pc(entry_index);
entry->end_pc = extable.end_pc(entry_index);
entry->handler_pc = extable.handler_pc(entry_index);
entry->catchType = extable.catch_type_index(entry_index);
JVM_END
@ -2196,7 +2197,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cl
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
oop method = instanceKlass::cast(k)->methods()->obj_at(method_index);
return methodOop(method)->exception_table()->length() / 4;
return methodOop(method)->exception_table_length();
JVM_END

View File

@ -191,15 +191,14 @@ void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
}
}
typeArrayHandle exception_table(thread(), const_method->exception_table());
int exception_table_length = exception_table->length();
int exception_table_entries = exception_table_length / 4;
ExceptionTable exception_table(method());
int exception_table_length = exception_table.length();
int code_size = const_method->code_size();
int size =
2+2+4 + // max_stack, max_locals, code_length
code_size + // code
2 + // exception_table_length
(2+2+2+2) * exception_table_entries + // exception_table
(2+2+2+2) * exception_table_length + // exception_table
2 + // attributes_count
attr_size; // attributes
@ -209,12 +208,12 @@ void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
write_u2(method->max_locals());
write_u4(code_size);
copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
write_u2(exception_table_entries);
for (int index = 0; index < exception_table_length; ) {
write_u2(exception_table->int_at(index++));
write_u2(exception_table->int_at(index++));
write_u2(exception_table->int_at(index++));
write_u2(exception_table->int_at(index++));
write_u2(exception_table_length);
for (int index = 0; index < exception_table_length; index++) {
write_u2(exception_table.start_pc(index));
write_u2(exception_table.end_pc(index));
write_u2(exception_table.handler_pc(index));
write_u2(exception_table.catch_type_index(index));
}
write_u2(attr_count);
if (line_num_cnt != 0) {

View File

@ -2478,23 +2478,17 @@ void VM_RedefineClasses::set_new_constant_pool(
// to use new constant pool indices as needed. The exception table
// holds quadruple entries of the form:
// (beg_bci, end_bci, handler_bci, klass_index)
const int beg_bci_offset = 0;
const int end_bci_offset = 1;
const int handler_bci_offset = 2;
const int klass_index_offset = 3;
const int entry_size = 4;
typeArrayHandle ex_table (THREAD, method->exception_table());
int ext_length = ex_table->length();
assert(ext_length % entry_size == 0, "exception table format has changed");
ExceptionTable ex_table(method());
int ext_length = ex_table.length();
for (int j = 0; j < ext_length; j += entry_size) {
int cur_index = ex_table->int_at(j + klass_index_offset);
for (int j = 0; j < ext_length; j ++) {
int cur_index = ex_table.catch_type_index(j);
int new_index = find_new_index(cur_index);
if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("ext-klass_index change: %d to %d", cur_index, new_index));
ex_table->int_at_put(j + klass_index_offset, new_index);
ex_table.set_catch_type_index(j, new_index);
}
} // end for each exception table entry

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1796,7 +1796,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) {
{
methodOop m_oop = oopFactory::new_method(bytecode_length(),
accessFlags_from(flags_bits),
0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty));
0, 0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty));
m = methodHandle(THREAD, m_oop);
}
@ -1812,9 +1812,6 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) {
m->set_max_locals(max_locals());
m->set_size_of_parameters(_num_params);
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
m->set_exception_table(exception_handlers());
// Rewrite the method and set up the constant pool cache.
objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty));
objArrayHandle methods(THREAD, m_array);

View File

@ -3180,17 +3180,15 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
jclass MH_class = env->FindClass(MH_name);
status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod));
}
if (!env->ExceptionOccurred()) {
status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod));
}
if (env->ExceptionOccurred()) {
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
enable_MH = false;
env->ExceptionClear();
}
status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
// Exception is okay until 7087357
env->ExceptionClear();
}
}
if (enable_MH) {

View File

@ -178,17 +178,6 @@ jint Unsafe_invocation_key_to_method_slot(jint key) {
v = *(oop*)index_oop_from_field_offset_long(p, offset); \
}
#define GET_OOP_FIELD_VOLATILE(obj, offset, v) \
oop p = JNIHandles::resolve(obj); \
volatile oop v; \
if (UseCompressedOops) { \
volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \
v = oopDesc::decode_heap_oop(n); \
} else { \
v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \
} \
OrderAccess::acquire();
// Get/SetObject must be special-cased, since it works with handles.
@ -296,28 +285,21 @@ UNSAFE_END
UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
UnsafeWrapper("Unsafe_GetObjectVolatile");
GET_OOP_FIELD_VOLATILE(obj, offset, v)
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
volatile oop v;
if (UseCompressedOops) {
volatile narrowOop n = *(volatile narrowOop*) addr;
v = oopDesc::decode_heap_oop(n);
} else {
v = *(volatile oop*) addr;
}
OrderAccess::acquire();
return JNIHandles::make_local(env, v);
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
UnsafeWrapper("Unsafe_SetObjectVolatile");
{
// Catch VolatileCallSite.target stores (via
// CallSite.setTargetVolatile) and check call site dependencies.
oop p = JNIHandles::resolve(obj);
if ((offset == java_lang_invoke_CallSite::target_offset_in_bytes()) && p->is_a(SystemDictionary::CallSite_klass())) {
Handle call_site (THREAD, p);
Handle method_handle(THREAD, JNIHandles::resolve(x_h));
assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be");
assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be");
{
// Walk all nmethods depending on this call site.
MutexLocker mu(Compile_lock, thread);
Universe::flush_dependents_on(call_site(), method_handle());
}
}
}
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -392,16 +392,16 @@ void Relocator::change_jumps(int break_bci, int delta) {
// The width of instruction at "pc" is changing by "delta". Adjust the
// exception table, if any, of "rc->mb".
void Relocator::adjust_exception_table(int bci, int delta) {
typeArrayOop table = method()->exception_table();
for (int index = 0; index < table->length(); index +=4) {
if (table->int_at(index) > bci) {
table->int_at_put(index+0, table->int_at(index+0) + delta);
table->int_at_put(index+1, table->int_at(index+1) + delta);
} else if (bci < table->int_at(index+1)) {
table->int_at_put(index+1, table->int_at(index+1) + delta);
ExceptionTable table(_method());
for (int index = 0; index < table.length(); index ++) {
if (table.start_pc(index) > bci) {
table.set_start_pc(index, table.start_pc(index) + delta);
table.set_end_pc(index, table.end_pc(index) + delta);
} else if (bci < table.end_pc(index)) {
table.set_end_pc(index, table.end_pc(index) + delta);
}
if (table->int_at(index+2) > bci)
table->int_at_put(index+2, table->int_at(index+2) + delta);
if (table.handler_pc(index) > bci)
table.set_handler_pc(index, table.handler_pc(index) + delta);
}
}

View File

@ -388,7 +388,6 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
volatile_nonstatic_field(constMethodOopDesc, _fingerprint, uint64_t) \
nonstatic_field(constMethodOopDesc, _constants, constantPoolOop) \
nonstatic_field(constMethodOopDesc, _stackmap_data, typeArrayOop) \
nonstatic_field(constMethodOopDesc, _exception_table, typeArrayOop) \
nonstatic_field(constMethodOopDesc, _constMethod_size, int) \
nonstatic_field(constMethodOopDesc, _interpreter_kind, jbyte) \
nonstatic_field(constMethodOopDesc, _flags, jbyte) \
@ -425,6 +424,10 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
nonstatic_field(LocalVariableTableElement, descriptor_cp_index, u2) \
nonstatic_field(LocalVariableTableElement, signature_cp_index, u2) \
nonstatic_field(LocalVariableTableElement, slot, u2) \
nonstatic_field(ExceptionTableElement, start_pc, u2) \
nonstatic_field(ExceptionTableElement, end_pc, u2) \
nonstatic_field(ExceptionTableElement, handler_pc, u2) \
nonstatic_field(ExceptionTableElement, catch_type_index, u2) \
nonstatic_field(BreakpointInfo, _orig_bytecode, Bytecodes::Code) \
nonstatic_field(BreakpointInfo, _bci, int) \
nonstatic_field(BreakpointInfo, _name_index, u2) \
@ -1460,6 +1463,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
\
declare_toplevel_type(CheckedExceptionElement) \
declare_toplevel_type(LocalVariableTableElement) \
declare_toplevel_type(ExceptionTableElement) \
\
/******************************************/ \
/* Generation and space hierarchies */ \
@ -2301,6 +2305,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
declare_constant(constMethodOopDesc::_has_linenumber_table) \
declare_constant(constMethodOopDesc::_has_checked_exceptions) \
declare_constant(constMethodOopDesc::_has_localvariable_table) \
declare_constant(constMethodOopDesc::_has_exception_table) \
\
/*************************************/ \
/* instanceKlass enum */ \

View File

@ -45,11 +45,11 @@ MemPointer* SequencedRecordIterator::next_record() {
}
debug_only(volatile jint MemRecorder::_instance_count = 0;)
volatile jint MemRecorder::_instance_count = 0;
MemRecorder::MemRecorder() {
assert(MemTracker::is_on(), "Native memory tracking is off");
debug_only(Atomic::inc(&_instance_count);)
Atomic::inc(&_instance_count);
debug_only(set_generation();)
if (MemTracker::track_callsite()) {
@ -83,9 +83,7 @@ MemRecorder::~MemRecorder() {
delete _next;
}
#ifdef ASSERT
Atomic::dec(&_instance_count);
#endif
}
// Sorting order:

View File

@ -249,9 +249,9 @@ class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
SequencedRecordIterator pointer_itr();
public:
protected:
// number of MemRecorder instance
debug_only(static volatile jint _instance_count;)
static volatile jint _instance_count;
private:
// sorting function, sort records into following order

View File

@ -173,7 +173,7 @@ MemSnapshot::MemSnapshot() {
_staging_area = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecord>();
}
_lock = new (std::nothrow) Mutex(Monitor::native, "memSnapshotLock");
_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock");
NOT_PRODUCT(_untracked_count = 0;)
}

View File

@ -67,7 +67,7 @@ class MemTrackWorker : public NamedThread {
NOT_PRODUCT(int _last_gen_in_use;)
inline int generations_in_use() const {
return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1));
return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1));
}
};

View File

@ -54,7 +54,7 @@ void SyncThreadRecorderClosure::do_thread(Thread* thread) {
MemRecorder* MemTracker::_global_recorder = NULL;
MemSnapshot* MemTracker::_snapshot = NULL;
MemBaseline MemTracker::_baseline;
Mutex MemTracker::_query_lock(Monitor::native, "NMT_queryLock");
Mutex* MemTracker::_query_lock = NULL;
volatile MemRecorder* MemTracker::_merge_pending_queue = NULL;
volatile MemRecorder* MemTracker::_pooled_recorders = NULL;
MemTrackWorker* MemTracker::_worker_thread = NULL;
@ -89,6 +89,12 @@ void MemTracker::bootstrap_single_thread() {
return;
}
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
if (_query_lock == NULL) {
shutdown(NMT_out_of_memory);
return;
}
debug_only(_main_thread_tid = os::current_thread_id();)
_state = NMT_bootstrapping_single_thread;
NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
@ -164,7 +170,7 @@ void MemTracker::final_shutdown() {
{
// shared baseline and snapshot are the only objects needed to
// create query results
MutexLockerEx locker(&_query_lock, true);
MutexLockerEx locker(_query_lock, true);
// cleanup baseline data and snapshot
_baseline.clear();
delete _snapshot;
@ -351,21 +357,17 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
}
if (thread != NULL) {
#ifdef ASSERT
// cause assertion on stack base. This ensures that threads call
// Thread::record_stack_base_and_size() method, which will create
// thread native stack records.
thread->stack_base();
#endif
// for a JavaThread, if it is running in native state, we need to transition it to
// VM state, so it can stop at safepoint. JavaThread running in VM state does not
// need lock to write records.
if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
if (((JavaThread*)thread)->thread_state() == _thread_in_native) {
ThreadInVMfromNative trans((JavaThread*)thread);
create_record_in_recorder(addr, flags, size, pc, thread);
JavaThread* java_thread = static_cast<JavaThread*>(thread);
JavaThreadState state = java_thread->thread_state();
if (SafepointSynchronize::safepoint_safe(java_thread, state)) {
// JavaThreads that are safepoint safe, can run through safepoint,
// so ThreadCritical is needed to ensure no threads at safepoint create
// new records while the records are being gathered and the sequence number is changing
ThreadCritical tc;
create_record_in_recorder(addr, flags, size, pc, java_thread);
} else {
create_record_in_recorder(addr, flags, size, pc, thread);
create_record_in_recorder(addr, flags, size, pc, java_thread);
}
} else {
// other threads, such as worker and watcher threads, etc. need to
@ -390,10 +392,9 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
// write a record to proper recorder. No lock can be taken from this method
// down.
void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags,
size_t size, address pc, Thread* thread) {
assert(thread == NULL || thread->is_Java_thread(), "wrong thread");
size_t size, address pc, JavaThread* thread) {
MemRecorder* rc = get_thread_recorder((JavaThread*)thread);
MemRecorder* rc = get_thread_recorder(thread);
if (rc != NULL) {
rc->record(addr, flags, size, pc);
}
@ -460,17 +461,18 @@ void MemTracker::sync() {
}
}
_sync_point_skip_count = 0;
// walk all JavaThreads to collect recorders
SyncThreadRecorderClosure stc;
Threads::threads_do(&stc);
_thread_count = stc.get_thread_count();
MemRecorder* pending_recorders = get_pending_recorders();
{
// This method is running at safepoint, with ThreadCritical lock,
// it should guarantee that NMT is fully sync-ed.
ThreadCritical tc;
// walk all JavaThreads to collect recorders
SyncThreadRecorderClosure stc;
Threads::threads_do(&stc);
_thread_count = stc.get_thread_count();
MemRecorder* pending_recorders = get_pending_recorders();
if (_global_recorder != NULL) {
_global_recorder->set_next(pending_recorders);
pending_recorders = _global_recorder;
@ -486,8 +488,6 @@ void MemTracker::sync() {
// now, it is the time to shut whole things off
if (_state == NMT_final_shutdown) {
_tracking_level = NMT_off;
// walk all JavaThreads to delete all recorders
SyncThreadRecorderClosure stc;
Threads::threads_do(&stc);
@ -499,8 +499,16 @@ void MemTracker::sync() {
_global_recorder = NULL;
}
}
_state = NMT_shutdown;
MemRecorder* pending_recorders = get_pending_recorders();
if (pending_recorders != NULL) {
delete pending_recorders;
}
// try at a later sync point to ensure MemRecorder instance drops to zero to
// completely shutdown NMT
if (MemRecorder::_instance_count == 0) {
_state = NMT_shutdown;
_tracking_level = NMT_off;
}
}
}
@ -534,7 +542,7 @@ void MemTracker::thread_exiting(JavaThread* thread) {
// baseline current memory snapshot
bool MemTracker::baseline() {
MutexLockerEx lock(&_query_lock, true);
MutexLockerEx lock(_query_lock, true);
MemSnapshot* snapshot = get_snapshot();
if (snapshot != NULL) {
return _baseline.baseline(*snapshot, false);
@ -545,7 +553,7 @@ bool MemTracker::baseline() {
// print memory usage from current snapshot
bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
MemBaseline baseline;
MutexLockerEx lock(&_query_lock, true);
MutexLockerEx lock(_query_lock, true);
MemSnapshot* snapshot = get_snapshot();
if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) {
BaselineReporter reporter(out, unit);
@ -557,7 +565,7 @@ bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool sum
// compare memory usage between current snapshot and baseline
bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
MutexLockerEx lock(&_query_lock, true);
MutexLockerEx lock(_query_lock, true);
if (_baseline.baselined()) {
MemBaseline baseline;
MemSnapshot* snapshot = get_snapshot();

View File

@ -126,6 +126,8 @@ class MemTracker : AllStatic {
return "Native memory tracking has been shutdown by user";
case NMT_normal:
return "Native memory tracking has been shutdown due to process exiting";
case NMT_out_of_memory:
return "Native memory tracking has been shutdown due to out of native memory";
case NMT_initialization:
return "Native memory tracking failed to initialize";
case NMT_error_reporting:
@ -326,7 +328,7 @@ class MemTracker : AllStatic {
static void create_memory_record(address addr, MEMFLAGS type,
size_t size, address pc, Thread* thread);
static void create_record_in_recorder(address addr, MEMFLAGS type,
size_t size, address pc, Thread* thread);
size_t size, address pc, JavaThread* thread);
private:
// global memory snapshot
@ -336,7 +338,7 @@ class MemTracker : AllStatic {
static MemBaseline _baseline;
// query lock
static Mutex _query_lock;
static Mutex* _query_lock;
// a thread can start to allocate memory before it is attached
// to VM 'Thread', those memory activities are recorded here.

View File

@ -25,6 +25,7 @@
* @test
* @bug 6294277
* @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
* @run main/othervm -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n SourceDebugExtension
*/
import java.io.*;

View File

@ -1,92 +0,0 @@
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test Test6294277.sh
# @bug 6294277
# @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
# @run shell Test6294277.sh
#
if [ "${TESTSRC}" = "" ]
then TESTSRC=.
fi
if [ "${TESTJAVA}" = "" ]
then
PARENT=`dirname \`which java\``
TESTJAVA=`dirname ${PARENT}`
echo "TESTJAVA not set, selecting " ${TESTJAVA}
echo "If this is incorrect, try setting the variable manually."
fi
BIT_FLAG=""
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
SunOS | Linux )
NULL=/dev/null
PS=":"
FS="/"
## for solaris, linux it's HOME
FILE_LOCATION=$HOME
if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" -a `uname -p`='sparc' ]
then
BIT_FLAG="-d64"
fi
;;
Windows_* | Darwin )
NULL=NUL
PS=";"
FS="\\"
echo "Test skipped"
exit 0
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
cp ${TESTSRC}${FS}*.java .
${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion
${TESTJAVA}${FS}bin${FS}javac *.java
${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -classpath . -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n SourceDebugExtension > test.out 2>&1 &
P_PID=$!
sleep 60
STATUS=1
grep "Test PASSES" test.out > ${NULL}
if [ $? = 0 ]; then
cat test.out
STATUS=0
fi
exit $STATUS

View File

@ -2,10 +2,10 @@
##
## @test
## @bug 7020373 7055247
## @bug 7020373 7055247 7053586 7185550
## @key cte_test
## @summary JSR rewriting can overflow memory address size variables
## @ignore Ignore it until 7053586 fixed
## @ignore Ignore it as 7053586 test uses lots of memory. See bug report for detail.
## @run shell Test7020373.sh
##
@ -30,7 +30,7 @@ fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
SunOS | Linux )
SunOS | Linux | Darwin )
NULL=/dev/null
PS=":"
FS="/"
@ -66,7 +66,7 @@ then
echo "Test Failed"
exit 1
else
grep "java.lang.LinkageError" test.out
egrep "java.lang.LinkageError|java.lang.NoSuchMethodError|Main method not found in class OOMCrashClass4000_1|insufficient memory" test.out
if [ $? = 0 ]
then
echo "Test Passed"

Binary file not shown.

View File

@ -169,3 +169,5 @@ eff4ece9c8bc43b3ce2b3758574c4c20147f0689 jdk8-b43
57476f66e13c55eea2f2fe2b858369a4c64b9936 jdk8-b45
300f45e990643af230d6cca39477ff62c44a9a54 jdk8-b46
404521944ac9383afda7d55d60713b212c730646 jdk8-b47
1c88da9a1365797e49be77ae42c34bbc0a3c3f0c jdk8-b48
f81e981eca7b63316cf9d778f93903a4fc62161d jdk8-b49

View File

@ -602,7 +602,7 @@ protected static final String PARSER_SETTINGS =
if (reader == null) {
stream = xmlInputSource.getByteStream();
if (stream == null) {
URL location = new URL(escapeNonUSAscii(expandedSystemId));
URL location = new URL(expandedSystemId);
URLConnection connect = location.openConnection();
if (!(connect instanceof HttpURLConnection)) {
stream = connect.getInputStream();
@ -2586,76 +2586,6 @@ protected static final String PARSER_SETTINGS =
} // fixURI(String):String
/**
* Escape invalid URI characters.
*
* Passed a URI that contains invalid characters (like spaces, non-ASCII Unicode characters, and the like),
* this function percent encodes the invalid characters per the URI specification (i.e., as a sequence of
* %-encoded UTF-8 octets).
*
* N.B. There are two problems. If the URI contains a '%' character, that might be an indication that
* the URI has already been escaped by the author, or it might be an invalid '%'. In the former case,
* it's important not to escape it, or we'll wind up with invalid, doubly-escaped '%'s. In the latter,
* the URI is broken if we don't encode it. Similarly, a '#' character might be the start of a fragment
* identifier or it might be an invalid '#'.
*
* Given that the former is vastly more likely than the latter in each case (most users are familiar with
* the magic status of '%' and '#' and they occur relatively infrequently in filenames, and if the user parses
* a proper Java File, we will already have %-escaped the URI), we simply assume that %'s and #'s are legit.
*
* Very rarely, we may be wrong. If so, tell the user to fix the clearly broken URI.
*/
protected static String escapeNonUSAscii(String str) {
if (str == null) {
return str;
}
int len = str.length(), i=0, ch;
for (; i < len; i++) {
ch = str.charAt(i);
// if it's not an ASCII 7 character, break here, and use UTF-8 encoding
if (ch >= 128)
break;
}
// we saw no non-ascii-7 character
if (i == len) {
return str;
}
// get UTF-8 bytes for the string
StringBuffer buffer = new StringBuffer();
byte[] bytes = null;
byte b;
try {
bytes = str.getBytes("UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
// should never happen
return str;
}
len = bytes.length;
// for each byte
for (i = 0; i < len; i++) {
b = bytes[i];
// for non-ascii character: make it positive, then escape
if (b < 0) {
ch = b + 256;
buffer.append('%');
buffer.append(gHexChs[ch >> 4]);
buffer.append(gHexChs[ch & 0xf]);
}
else if (b != '%' && b != '#' && gNeedEscaping[b]) {
buffer.append('%');
buffer.append(gAfterEscaping1[b]);
buffer.append(gAfterEscaping2[b]);
}
else {
buffer.append((char)b);
}
}
return buffer.toString();
}
//
// Package visible methods

View File

@ -169,3 +169,5 @@ f6a417540ef124c9b4123d07da5e26f2ab909949 jdk8-b44
e80ac58b5ba904f24e125c742c30d0d740f05f86 jdk8-b45
ae368a83c2404b65c9e38c65e2aa081f2201ca74 jdk8-b46
fe6a060afc404dcf0921708a740de770666b781f jdk8-b47
efb564de8a8ee397a65fab77d45cb20200f6ddd8 jdk8-b48
b48865af8ac559ba6f60fb86fa3fe0ebdd22746c jdk8-b49

View File

@ -169,3 +169,5 @@ db471a7af03168e4441c245b1d9976f720a7cb77 jdk8-b44
b92353a01aa049bc508fc56f0347d5934b7c4390 jdk8-b45
8d2ed9d58453c8049715a72a6d26b6b66b37a94c jdk8-b46
00b22b23269a57d0bb46c57753be2fe9a9d2c1a3 jdk8-b47
3e4ab821f46166fcf63e8fe5c8046216003c941f jdk8-b48
51707c3b75c0f521794d9ab425f4e5b2351c70c1 jdk8-b49

View File

@ -32,10 +32,20 @@ import javax.swing.plaf.basic.BasicPanelUI;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
import java.awt.Graphics;
public class AquaPanelUI extends BasicPanelUI {
static RecyclableSingleton<AquaPanelUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaPanelUI>(AquaPanelUI.class);
public static ComponentUI createUI(final JComponent c) {
return instance.get();
}
@Override
public final void update(final Graphics g, final JComponent c) {
if (c.isOpaque()) {
AquaUtils.fillRect(g, c);
}
paint(g, c);
}
}

View File

@ -319,4 +319,12 @@ public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener,
updateComponentTreeUIActivation(element, active);
}
}
@Override
public final void update(final Graphics g, final JComponent c) {
if (c.isOpaque()) {
AquaUtils.fillRect(g, c);
}
paint(g, c);
}
}

View File

@ -73,9 +73,7 @@ public class AquaToolBarUI extends BasicToolBarUI implements SwingConstants {
g.translate(x, y);
if (c.isOpaque()) {
final Color background = c.getBackground();
g.setColor(background);
g.fillRect(0, 0, w - 1, h - 1);
AquaUtils.fillRect(g, c, c.getBackground(), 0, 0, w - 1, h - 1);
}
final Color oldColor = g.getColor();
@ -137,4 +135,12 @@ public class AquaToolBarUI extends BasicToolBarUI implements SwingConstants {
return true;
}
}
@Override
public final void update(final Graphics g, final JComponent c) {
if (c.isOpaque()) {
AquaUtils.fillRect(g, c);
}
paint(g, c);
}
}

View File

@ -28,18 +28,19 @@ package com.apple.laf;
import java.awt.*;
import java.awt.image.*;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import sun.awt.AppContext;
import sun.lwawt.macosx.CImage;
import sun.lwawt.macosx.CImage.Creator;
import sun.lwawt.macosx.CPlatformWindow;
import sun.swing.SwingUtilities2;
import com.apple.laf.AquaImageFactory.SlicedImageControl;
@ -389,4 +390,51 @@ public class AquaUtils {
return false;
}
}
protected static boolean isWindowTextured(final Component c) {
if (!(c instanceof JComponent)) {
return false;
}
final JRootPane pane = ((JComponent) c).getRootPane();
if (pane == null) {
return false;
}
Object prop = pane.getClientProperty(
CPlatformWindow.WINDOW_BRUSH_METAL_LOOK);
if (prop != null) {
return Boolean.parseBoolean(prop.toString());
}
prop = pane.getClientProperty(CPlatformWindow.WINDOW_STYLE);
return prop != null && "textured".equals(prop);
}
private static Color resetAlpha(final Color color) {
return new Color(color.getRed(), color.getGreen(), color.getBlue(), 0);
}
protected static void fillRect(final Graphics g, final Component c) {
fillRect(g, c, c.getBackground(), 0, 0, c.getWidth(), c.getHeight());
}
protected static void fillRect(final Graphics g, final Component c,
final Color color, final int x, final int y,
final int w, final int h) {
if (!(g instanceof Graphics2D)) {
return;
}
final Graphics2D cg = (Graphics2D) g.create();
try {
if (color instanceof UIResource && isWindowTextured(c)
&& color.equals(SystemColor.window)) {
cg.setComposite(AlphaComposite.Src);
cg.setColor(resetAlpha(color));
} else {
cg.setColor(color);
}
cg.fillRect(x, y, w, h);
} finally {
cg.dispose();
}
}
}

View File

@ -48,6 +48,9 @@ public class CGraphicsDevice extends GraphicsDevice {
private static AWTPermission fullScreenExclusivePermission;
// Save/restore DisplayMode for the Full Screen mode
private DisplayMode originalMode;
public CGraphicsDevice(int displayID) {
this.displayID = displayID;
configs = new GraphicsConfiguration[] {
@ -124,18 +127,22 @@ public class CGraphicsDevice extends GraphicsDevice {
}
boolean fsSupported = isFullScreenSupported();
if (fsSupported && old != null) {
// enter windowed mode (and restore original display mode)
exitFullScreenExclusive(old);
// TODO: restore display mode
if (originalMode != null) {
setDisplayMode(originalMode);
originalMode = null;
}
}
super.setFullScreenWindow(w);
if (fsSupported && w != null) {
// TODO: save current display mode
if (isDisplayChangeSupported()) {
originalMode = getDisplayMode();
}
// enter fullscreen mode
enterFullScreenExclusive(w);
}

View File

@ -68,11 +68,12 @@ public class CGLLayer extends CFRetainedResource {
}
public boolean isOpaque() {
return peer.isOpaque();
return !peer.isTranslucent();
}
public int getTransparency() {
return (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT);
return peer.isTranslucent() ? Transparency.TRANSLUCENT :
Transparency.OPAQUE;
}
public Object getDestination() {

View File

@ -424,8 +424,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override
public final Graphics getGraphics() {
Graphics g = getWindowPeerOrSelf().isOpaque() ? getOnscreenGraphics()
: getOffscreenGraphics();
final Graphics g = getOnscreenGraphics();
if (g != null) {
synchronized (getPeerTreeLock()){
applyConstrain(g);
@ -443,13 +442,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOnscreenGraphics(getForeground(), getBackground(),
getFont());
}
public final Graphics getOffscreenGraphics() {
final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOffscreenGraphics(getForeground(), getBackground(),
getFont());
}
private void applyConstrain(final Graphics g) {
@ -463,7 +456,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
}
//TODO Move this method to SG2D?
private void SG2DConstraint(final SunGraphics2D sg2d, Region r) {
void SG2DConstraint(final SunGraphics2D sg2d, Region r) {
sg2d.constrainX = sg2d.transX;
sg2d.constrainY = sg2d.transY;
@ -710,7 +703,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
// Obtain the metrics from the offscreen window where this peer is
// mostly drawn to.
// TODO: check for "use platform metrics" settings
Graphics g = getWindowPeer().getOffscreenGraphics();
Graphics g = getWindowPeer().getGraphics();
try {
if (g != null) {
return g.getFontMetrics(f);
@ -1011,14 +1004,33 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override
public final void applyShape(final Region shape) {
synchronized (getStateLock()) {
region = shape;
if (region == shape || (region != null && region.equals(shape))) {
return;
}
}
applyShapeImpl(shape);
}
void applyShapeImpl(final Region shape) {
synchronized (getStateLock()) {
if (shape != null) {
region = Region.WHOLE_REGION.getIntersection(shape);
} else {
region = null;
}
}
repaintParent(getBounds());
}
protected final Region getRegion() {
synchronized (getStateLock()) {
return region == null ? Region.getInstance(getSize()) : region;
return isShaped() ? region : Region.getInstance(getSize());
}
}
public boolean isShaped() {
synchronized (getStateLock()) {
return region != null;
}
}
@ -1386,11 +1398,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
}
}
// Just a helper method, thus final
protected final void flushOffscreenGraphics() {
flushOffscreenGraphics(getSize());
}
protected static final void flushOnscreenGraphics(){
final OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock();
@ -1401,36 +1408,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
}
}
/*
* Flushes the given rectangle from the back buffer to the screen.
*/
protected void flushOffscreenGraphics(Rectangle r) {
flushOffscreenGraphics(r.x, r.y, r.width, r.height);
}
private void flushOffscreenGraphics(int x, int y, int width, int height) {
Image bb = getWindowPeerOrSelf().getBackBuffer();
if (bb != null) {
// g is a screen Graphics from the delegate
final Graphics g = getOnscreenGraphics();
if (g != null && g instanceof Graphics2D) {
try {
Graphics2D g2d = (Graphics2D)g;
Point p = localToWindow(new Point(0, 0));
Composite composite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Src);
g.drawImage(bb, x, y, x + width, y + height, p.x + x,
p.y + y, p.x + x + width, p.y + y + height,
null);
g2d.setComposite(composite);
} finally {
g.dispose();
}
}
}
}
/**
* Used by ContainerPeer to skip all the paint events during layout.
*

View File

@ -58,9 +58,6 @@ final class LWRepaintArea extends RepaintArea {
private static void flushBuffers(final LWComponentPeer peer) {
if (peer != null) {
if (!peer.getWindowPeerOrSelf().isOpaque()) {
peer.flushOffscreenGraphics();
}
peer.flushOnscreenGraphics();
}
}

View File

@ -522,12 +522,6 @@ public abstract class LWToolkit extends SunToolkit implements Runnable {
postEvent(targetToAppContext(event.getSource()), event);
}
// use peer's back buffer to implement non-opaque windows.
@Override
public boolean needUpdateWindow() {
return true;
}
@Override
public void grab(Window w) {
if (w.getPeer() != null) {

View File

@ -37,6 +37,7 @@ import sun.awt.*;
import sun.java2d.*;
import sun.java2d.loops.Blit;
import sun.java2d.loops.CompositeType;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger;
public class LWWindowPeer
@ -109,6 +110,10 @@ public class LWWindowPeer
private volatile boolean skipNextFocusChange;
private static final Color nonOpaqueBackground = new Color(0, 0, 0, 0);
private volatile boolean textured;
/**
* Current modal blocker or null.
*
@ -169,6 +174,11 @@ public class LWWindowPeer
setAlwaysOnTop(getTarget().isAlwaysOnTop());
updateMinimumSize();
final Shape shape = getTarget().getShape();
if (shape != null) {
applyShape(Region.getInstance(shape, null));
}
final float opacity = getTarget().getOpacity();
if (opacity < 1.0f) {
setOpacity(opacity);
@ -178,7 +188,7 @@ public class LWWindowPeer
updateInsets(platformWindow.getInsets());
if (getSurfaceData() == null) {
replaceSurfaceData();
replaceSurfaceData(false);
}
}
@ -280,7 +290,7 @@ public class LWWindowPeer
// "buffer", that's why numBuffers - 1
assert numBuffers > 1;
replaceSurfaceData(numBuffers - 1, caps);
replaceSurfaceData(numBuffers - 1, caps, false);
} catch (InvalidPipeException z) {
throw new AWTException(z.toString());
}
@ -420,19 +430,44 @@ public class LWWindowPeer
public final void setOpaque(final boolean isOpaque) {
if (this.isOpaque != isOpaque) {
this.isOpaque = isOpaque;
getPlatformWindow().setOpaque(isOpaque);
replaceSurfaceData();
repaintPeer();
updateOpaque();
}
}
public final boolean isOpaque() {
return isOpaque;
private void updateOpaque() {
getPlatformWindow().setOpaque(!isTranslucent());
replaceSurfaceData(false);
repaintPeer();
}
@Override
public void updateWindow() {
flushOffscreenGraphics();
}
public final boolean isTextured() {
return textured;
}
public final void setTextured(final boolean isTextured) {
textured = isTextured;
}
public final boolean isTranslucent() {
synchronized (getStateLock()) {
/*
* Textured window is a special case of translucent window.
* The difference is only in nswindow background. So when we set
* texture property our peer became fully translucent. It doesn't
* fill background, create non opaque backbuffers and layer etc.
*/
return !isOpaque || isShaped() || isTextured();
}
}
@Override
final void applyShapeImpl(final Region shape) {
super.applyShapeImpl(shape);
updateOpaque();
}
@Override
@ -587,7 +622,20 @@ public class LWWindowPeer
getFont());
if (g != null) {
try {
g.clearRect(0, 0, w, h);
if (g instanceof Graphics2D) {
((Graphics2D) g).setComposite(AlphaComposite.Src);
}
if (isTranslucent()) {
g.setColor(nonOpaqueBackground);
g.fillRect(0, 0, w, h);
}
if (!isTextured()) {
if (g instanceof SunGraphics2D) {
SG2DConstraint((SunGraphics2D) g, getRegion());
}
g.setColor(getBackground());
g.fillRect(0, 0, w, h);
}
} finally {
g.dispose();
}
@ -894,35 +942,6 @@ public class LWWindowPeer
});
}
/**
* This method returns a back buffer Graphics to render all the
* peers to. After the peer is painted, the back buffer contents
* should be flushed to the screen. All the target painting
* (Component.paint() method) should be done directly to the screen.
*/
protected final Graphics getOffscreenGraphics(Color fg, Color bg, Font f) {
final Image bb = getBackBuffer();
if (bb == null) {
return null;
}
if (fg == null) {
fg = SystemColor.windowText;
}
if (bg == null) {
bg = SystemColor.window;
}
if (f == null) {
f = DEFAULT_FONT;
}
final Graphics2D g = (Graphics2D) bb.getGraphics();
if (g != null) {
g.setColor(fg);
g.setBackground(bg);
g.setFont(f);
}
return g;
}
/*
* May be called by delegate to provide SD to Java2D code.
*/
@ -933,11 +952,16 @@ public class LWWindowPeer
}
private void replaceSurfaceData() {
replaceSurfaceData(backBufferCount, backBufferCaps);
replaceSurfaceData(true);
}
private void replaceSurfaceData(boolean blit) {
replaceSurfaceData(backBufferCount, backBufferCaps, blit);
}
private void replaceSurfaceData(int newBackBufferCount,
BufferCapabilities newBackBufferCaps) {
BufferCapabilities newBackBufferCaps,
boolean blit) {
synchronized (surfaceDataLock) {
final SurfaceData oldData = getSurfaceData();
surfaceData = platformWindow.replaceSurfaceData();
@ -950,7 +974,10 @@ public class LWWindowPeer
if (getSurfaceData() != null && oldData != getSurfaceData()) {
clearBackground(size.width, size.height);
}
blitSurfaceData(oldData, getSurfaceData());
if (blit) {
blitSurfaceData(oldData, getSurfaceData());
}
if (oldData != null && oldData != getSurfaceData()) {
// TODO: drop oldData for D3D/WGL pipelines
@ -965,11 +992,18 @@ public class LWWindowPeer
Graphics g = backBuffer.getGraphics();
try {
Rectangle r = getBounds();
g.setColor(getBackground());
if (g instanceof Graphics2D) {
((Graphics2D) g).setComposite(AlphaComposite.Src);
}
g.setColor(nonOpaqueBackground);
g.fillRect(0, 0, r.width, r.height);
if (g instanceof SunGraphics2D) {
SG2DConstraint((SunGraphics2D) g, getRegion());
}
if (!isTextured()) {
g.setColor(getBackground());
g.fillRect(0, 0, r.width, r.height);
}
if (oldBB != null) {
// Draw the old back buffer to the new one
g.drawImage(oldBB, 0, 0, null);
@ -993,7 +1027,7 @@ public class LWWindowPeer
CompositeType.Src,
dst.getSurfaceType());
if (blit != null) {
blit.Blit(src, dst, ((Graphics2D) getGraphics()).getComposite(),
blit.Blit(src, dst, AlphaComposite.Src,
getRegion(), 0, 0, 0, 0, size.width, size.height);
}
}

View File

@ -117,7 +117,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
Rectangle r = peer.getBounds();
Image im = null;
if (!r.isEmpty()) {
int transparency = (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT);
int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency);
}
return im;

View File

@ -64,7 +64,7 @@ public class CPlatformView extends CFRetainedResource {
}
public boolean isOpaque() {
return peer.isOpaque();
return !peer.isTranslucent();
}
/*

View File

@ -209,6 +209,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private boolean undecorated; // initialized in getInitialStyleBits()
private Rectangle normalBounds = null; // not-null only for undecorated maximized windows
private CPlatformResponder responder;
private volatile boolean zoomed = false; // from native perspective
public CPlatformWindow(final PeerType peerType) {
super(0, true);
@ -298,7 +299,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look.
if (isPopup) {
styleBits = SET(styleBits, TEXTURED, true);
styleBits = SET(styleBits, TEXTURED, false);
// Popups in applets don't activate applet's process
styleBits = SET(styleBits, NONACTIVATING, true);
}
@ -372,6 +373,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
peer.setTextured(IS(TEXTURED, styleBits));
return styleBits;
}
@ -467,26 +470,42 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h);
}
private void zoom() {
private boolean isMaximized() {
return undecorated ? this.normalBounds != null : zoomed;
}
private void maximize() {
if (isMaximized()) {
return;
}
if (!undecorated) {
zoomed = true;
CWrapper.NSWindow.zoom(getNSWindowPtr());
} else {
// OS X handles -zoom incorrectly for undecorated windows
final boolean isZoomed = this.normalBounds == null;
deliverZoom(isZoomed);
deliverZoom(true);
Rectangle toBounds;
if (isZoomed) {
this.normalBounds = peer.getBounds();
long screen = CWrapper.NSWindow.screen(getNSWindowPtr());
toBounds = CWrapper.NSScreen.visibleFrame(screen).getBounds();
// Flip the y coordinate
Rectangle frame = CWrapper.NSScreen.frame(screen).getBounds();
toBounds.y = frame.height - toBounds.y - toBounds.height;
} else {
toBounds = normalBounds;
this.normalBounds = null;
}
this.normalBounds = peer.getBounds();
long screen = CWrapper.NSWindow.screen(getNSWindowPtr());
Rectangle toBounds = CWrapper.NSScreen.visibleFrame(screen).getBounds();
// Flip the y coordinate
Rectangle frame = CWrapper.NSScreen.frame(screen).getBounds();
toBounds.y = frame.height - toBounds.y - toBounds.height;
setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
}
}
private void unmaximize() {
if (!isMaximized()) {
return;
}
if (!undecorated) {
zoomed = false;
CWrapper.NSWindow.zoom(getNSWindowPtr());
} else {
deliverZoom(false);
Rectangle toBounds = this.normalBounds;
this.normalBounds = null;
setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
}
}
@ -499,9 +518,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
public void setVisible(boolean visible) {
final long nsWindowPtr = getNSWindowPtr();
// 1. Process parent-child relationship when hiding
// Process parent-child relationship when hiding
if (!visible) {
// 1a. Unparent my children
// Unparent my children
for (Window w : target.getOwnedWindows()) {
WindowPeer p = (WindowPeer)w.getPeer();
if (p instanceof LWWindowPeer) {
@ -512,30 +531,17 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
// 1b. Unparent myself
// Unparent myself
if (owner != null && owner.isVisible()) {
CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), nsWindowPtr);
}
}
// 2. Configure stuff
// Configure stuff
updateIconImages();
updateFocusabilityForAutoRequestFocus(false);
// 3. Manage the extended state when hiding
if (!visible) {
// Cancel out the current native state of the window
switch (peer.getState()) {
case Frame.ICONIFIED:
CWrapper.NSWindow.deminiaturize(nsWindowPtr);
break;
case Frame.MAXIMIZED_BOTH:
zoom();
break;
}
}
// 4. Actually show or hide the window
// Actually show or hide the window
LWWindowPeer blocker = peer.getBlocker();
if (blocker == null || !visible) {
// If it ain't blocked, or is being hidden, go regular way
@ -564,16 +570,19 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
this.visible = visible;
// 5. Manage the extended state when showing
// Manage the extended state when showing
if (visible) {
// Re-apply the extended state as expected in shared code
// Apply the extended state as expected in shared code
if (target instanceof Frame) {
switch (((Frame)target).getExtendedState()) {
case Frame.ICONIFIED:
CWrapper.NSWindow.miniaturize(nsWindowPtr);
break;
case Frame.MAXIMIZED_BOTH:
zoom();
maximize();
break;
default: // NORMAL
unmaximize(); // in case it was maximized, otherwise this is a no-op
break;
}
}
@ -581,12 +590,12 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
// 6. Configure stuff #2
// Configure stuff #2
updateFocusabilityForAutoRequestFocus(true);
// 7. Manage parent-child relationship when showing
// Manage parent-child relationship when showing
if (visible) {
// 7a. Add myself as a child
// Add myself as a child
if (owner != null && owner.isVisible()) {
CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), nsWindowPtr, CWrapper.NSWindow.NSWindowAbove);
if (target.isAlwaysOnTop()) {
@ -594,7 +603,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
// 7b. Add my own children to myself
// Add my own children to myself
for (Window w : target.getOwnedWindows()) {
WindowPeer p = (WindowPeer)w.getPeer();
if (p instanceof LWWindowPeer) {
@ -609,7 +618,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
// 8. Deal with the blocker of the window being shown
// Deal with the blocker of the window being shown
if (blocker != null && visible) {
// Make sure the blocker is above its siblings
((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
@ -733,10 +742,19 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
@Override
public void setOpaque(boolean isOpaque) {
CWrapper.NSWindow.setOpaque(getNSWindowPtr(), isOpaque);
if (!isOpaque) {
if (!isOpaque && !peer.isTextured()) {
long clearColor = CWrapper.NSColor.clearColor();
CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), clearColor);
}
//This is a temporary workaround. Looks like after 7124236 will be fixed
//the correct place for invalidateShadow() is CGLayer.drawInCGLContext.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
invalidateShadow();
}
});
}
@Override
@ -767,7 +785,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
if (prevWindowState == Frame.MAXIMIZED_BOTH) {
// let's return into the normal states first
// the zoom call toggles between the normal and the max states
zoom();
unmaximize();
}
CWrapper.NSWindow.miniaturize(nsWindowPtr);
break;
@ -776,14 +794,14 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// let's return into the normal states first
CWrapper.NSWindow.deminiaturize(nsWindowPtr);
}
zoom();
maximize();
break;
case Frame.NORMAL:
if (prevWindowState == Frame.ICONIFIED) {
CWrapper.NSWindow.deminiaturize(nsWindowPtr);
} else if (prevWindowState == Frame.MAXIMIZED_BOTH) {
// the zoom call toggles between the normal and the max states
zoom();
unmaximize();
}
break;
default:
@ -805,6 +823,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSetEnabled(getNSWindowPtr(), !blocked);
}
public final void invalidateShadow(){
nativeRevalidateNSWindowShadow(getNSWindowPtr());
}
// ----------------------------------------------------------------------
// UTILITY METHODS
// ----------------------------------------------------------------------

View File

@ -749,6 +749,11 @@ public class LWCToolkit extends LWToolkit {
(modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
}
@Override
public boolean isWindowShapingSupported() {
return true;
}
@Override
public boolean isWindowTranslucencySupported() {
return true;
@ -759,6 +764,10 @@ public class LWCToolkit extends LWToolkit {
return true;
}
public boolean isSwingBackbufferTranslucencySupported() {
return true;
}
@Override
public boolean enableInputMethodsForTextComponent() {
return true;

View File

@ -941,14 +941,17 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSW
(JNIEnv *env, jclass clazz, jlong windowPtr)
{
JNF_COCOA_ENTER(env);
AWT_ASSERT_NOT_APPKIT_THREAD;
NSWindow *nsWindow = OBJC(windowPtr);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
if ([NSThread isMainThread]) {
[nsWindow invalidateShadow];
}];
} else {
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
[nsWindow invalidateShadow];
}];
}
JNF_COCOA_EXIT(env);
}

View File

@ -28,7 +28,7 @@
/*
* Convert the mode string to the more convinient bits per pixel value
*/
static int getBPPFromModeString(CFStringRef mode)
static int getBPPFromModeString(CFStringRef mode)
{
if ((CFStringCompare(mode, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
// This is a strange mode, where we using 10 bits per RGB component and pack it into 32 bits
@ -44,7 +44,7 @@ static int getBPPFromModeString(CFStringRef mode)
else if (CFStringCompare(mode, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
return 8;
}
return 0;
}
@ -68,6 +68,11 @@ static CGDisplayModeRef getBestModeForParameters(CFArrayRef allModes, int w, int
// One of the key parameters does not match
continue;
}
if (refrate == 0) { // REFRESH_RATE_UNKNOWN
return cRef;
}
// Refresh rate might be 0 in display mode and we ask for specific display rate
// but if we do not find exact match then 0 refresh rate might be just Ok
if (CGDisplayModeGetRefreshRate(cRef) == refrate) {
@ -165,7 +170,10 @@ Java_sun_awt_CGraphicsDevice_nativeSetDisplayMode
}
}
}];
} else {
[JNFException raise:env as:kIllegalArgumentException reason:"Invalid display mode"];
}
CFRelease(allModes);
JNF_COCOA_EXIT(env);
}

View File

@ -1586,10 +1586,18 @@ public class JViewport extends JComponent implements Accessible
int bdx = blitToX - blitFromX;
int bdy = blitToY - blitFromY;
Composite oldComposite = null;
// Shift the scrolled region
if (g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Src);
}
rm.copyArea(this, g, blitFromX, blitFromY, blitW, blitH, bdx, bdy,
false);
if (oldComposite != null) {
((Graphics2D) g).setComposite(oldComposite);
}
// Paint the newly exposed region.
int x = view.getX();
int y = view.getY();

View File

@ -118,6 +118,11 @@ public class RepaintManager
// Whether or not a VolatileImage should be used for double-buffered painting
static boolean volatileImageBufferEnabled = true;
/**
* Type of VolatileImage which should be used for double-buffered
* painting.
*/
private static final int volatileBufferType;
/**
* Value of the system property awt.nativeDoubleBuffering.
*/
@ -204,6 +209,13 @@ public class RepaintManager
((SunGraphicsEnvironment)ge).addDisplayChangedListener(
new DisplayChangedHandler());
}
Toolkit tk = Toolkit.getDefaultToolkit();
if ((tk instanceof SunToolkit)
&& ((SunToolkit) tk).isSwingBackbufferTranslucencySupported()) {
volatileBufferType = Transparency.TRANSLUCENT;
} else {
volatileBufferType = Transparency.OPAQUE;
}
}
/**
@ -989,7 +1001,8 @@ public class RepaintManager
if (image != null) {
image.flush();
}
image = config.createCompatibleVolatileImage(width, height);
image = config.createCompatibleVolatileImage(width, height,
volatileBufferType);
volatileMap.put(config, image);
}
return image;
@ -1483,9 +1496,26 @@ public class RepaintManager
for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
osg.translate(-x, -y);
osg.setClip(x,y,bw,bh);
if (volatileBufferType != Transparency.OPAQUE
&& osg instanceof Graphics2D) {
final Graphics2D g2d = (Graphics2D) osg;
final Color oldBg = g2d.getBackground();
g2d.setBackground(c.getBackground());
g2d.clearRect(x, y, bw, bh);
g2d.setBackground(oldBg);
}
c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
g.setClip(x, y, bw, bh);
g.drawImage(image, x, y, c);
if (volatileBufferType != Transparency.OPAQUE
&& g instanceof Graphics2D) {
final Graphics2D g2d = (Graphics2D) g;
final Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(image, x, y, c);
g2d.setComposite(oldComposite);
} else {
g.drawImage(image, x, y, c);
}
osg.translate(x, y);
}
}

View File

@ -319,7 +319,8 @@ public class SwingUtilities implements SwingConstants
newEvent = new MouseWheelEvent(newSource,
sourceWheelEvent.getID(),
sourceWheelEvent.getWhen(),
sourceWheelEvent.getModifiers(),
sourceWheelEvent.getModifiers()
| sourceWheelEvent.getModifiersEx(),
p.x,p.y,
sourceWheelEvent.getXOnScreen(),
sourceWheelEvent.getYOnScreen(),
@ -334,7 +335,8 @@ public class SwingUtilities implements SwingConstants
newEvent = new MenuDragMouseEvent(newSource,
sourceMenuDragEvent.getID(),
sourceMenuDragEvent.getWhen(),
sourceMenuDragEvent.getModifiers(),
sourceMenuDragEvent.getModifiers()
| sourceMenuDragEvent.getModifiersEx(),
p.x,p.y,
sourceMenuDragEvent.getXOnScreen(),
sourceMenuDragEvent.getYOnScreen(),
@ -347,7 +349,8 @@ public class SwingUtilities implements SwingConstants
newEvent = new MouseEvent(newSource,
sourceEvent.getID(),
sourceEvent.getWhen(),
sourceEvent.getModifiers(),
sourceEvent.getModifiers()
| sourceEvent.getModifiersEx(),
p.x,p.y,
sourceEvent.getXOnScreen(),
sourceEvent.getYOnScreen(),

View File

@ -440,7 +440,7 @@ public class TitledBorder extends AbstractBorder
* @return the title-font of the titled border
*/
public Font getTitleFont() {
return titleFont;
return titleFont == null ? UIManager.getFont("TitledBorder.font") : titleFont;
}
/**
@ -449,7 +449,7 @@ public class TitledBorder extends AbstractBorder
* @return the title-color of the titled border
*/
public Color getTitleColor() {
return titleColor;
return titleColor == null ? UIManager.getColor("TitledBorder.titleColor") : titleColor;
}
@ -681,10 +681,6 @@ public class TitledBorder extends AbstractBorder
if (font != null) {
return font;
}
font = UIManager.getFont("TitledBorder.font");
if (font != null) {
return font;
}
if (c != null) {
font = c.getFont();
if (font != null) {
@ -699,10 +695,6 @@ public class TitledBorder extends AbstractBorder
if (color != null) {
return color;
}
color = UIManager.getColor("TitledBorder.titleColor");
if (color != null) {
return color;
}
return (c != null)
? c.getForeground()
: null;

View File

@ -1984,6 +1984,13 @@ public abstract class SunToolkit extends Toolkit
return false;
}
/**
* Returns true if swing backbuffer should be translucent.
*/
public boolean isSwingBackbufferTranslucencySupported() {
return false;
}
/**
* Returns whether or not a containing top level window for the passed
* component is
@ -2105,25 +2112,41 @@ class PostEventQueue {
private EventQueueItem queueTail = null;
private final EventQueue eventQueue;
// For the case when queue is cleared but events are not posted
private volatile boolean isFlushing = false;
PostEventQueue(EventQueue eq) {
eventQueue = eq;
}
public synchronized boolean noEvents() {
return queueHead == null;
return queueHead == null && !isFlushing;
}
/*
* Continually post pending AWTEvents to the Java EventQueue. The method
* is synchronized to ensure the flush is completed before a new event
* can be posted to this queue.
*
* 7177040: The method couldn't be wholly synchronized because of calls
* of EventQueue.postEvent() that uses pushPopLock, otherwise it could
* potentially lead to deadlock
*/
public synchronized void flush() {
EventQueueItem tempQueue = queueHead;
queueHead = queueTail = null;
while (tempQueue != null) {
eventQueue.postEvent(tempQueue.event);
tempQueue = tempQueue.next;
public void flush() {
EventQueueItem tempQueue;
synchronized (this) {
tempQueue = queueHead;
queueHead = queueTail = null;
isFlushing = true;
}
try {
while (tempQueue != null) {
eventQueue.postEvent(tempQueue.event);
tempQueue = tempQueue.next;
}
}
finally {
isFlushing = false;
}
}

View File

@ -137,8 +137,9 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
LayoutEngine e = (LayoutEngine)cache.get(key);
if (e == null) {
e = new SunLayoutEngine(key.copy());
cache.put(key, e);
LayoutEngineKey copy = key.copy();
e = new SunLayoutEngine(copy);
cache.put(copy, e);
}
return e;
}

View File

@ -393,7 +393,16 @@ OGLBlitSwToTexture(SurfaceDataRasInfo *srcInfo, OGLPixelFormat *pf,
OGLSDOps *dstOps,
jint dx1, jint dy1, jint dx2, jint dy2)
{
jboolean adjustAlpha = (pf != NULL && !pf->hasAlpha);
j2d_glBindTexture(dstOps->textureTarget, dstOps->textureID);
if (adjustAlpha) {
// if the source surface does not have an alpha channel,
// we need to ensure that the alpha values are forced to 1.0f
j2d_glPixelTransferf(GL_ALPHA_SCALE, 0.0f);
j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0f);
}
// in case pixel stride is not a multiple of scanline stride the copy
// has to be done line by line (see 6207877)
if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
@ -413,6 +422,11 @@ OGLBlitSwToTexture(SurfaceDataRasInfo *srcInfo, OGLPixelFormat *pf,
dx1, dy1, dx2-dx1, dy2-dy1,
pf->format, pf->type, srcInfo->rasBase);
}
if (adjustAlpha) {
// restore scale/bias to their original values
j2d_glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0f);
}
}
/**

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7183458
* @summary Verify advance of space is not overly widened by bold styling.
* @run main StyledSpaceAdvance
*/
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.Locale;
public class StyledSpaceAdvance {
static String name = "Gulim";
public static void main(String args[]) {
for (int sz=9;sz<18;sz++) {
test(sz);
}
}
static void test(int sz) {
Font reg = new Font(name, Font.PLAIN, sz);
Font bold = new Font(name, Font.BOLD, sz);
//System.out.println("reg="+reg);
//System.out.println("bold="+bold);
FontRenderContext frc = new FontRenderContext(null, false, false);
if (reg.getFontName(Locale.ENGLISH).equals(name) &&
bold.getFontName(Locale.ENGLISH).equals(name)) {
Rectangle2D rb = reg.getStringBounds(" ", frc);
Rectangle2D bb = bold.getStringBounds(" ", frc);
if (bb.getWidth() > rb.getWidth() + 1.01f) {
System.err.println("reg="+reg+" bds = " + rb);
System.err.println("bold="+bold+" bds = " + bb);
throw new RuntimeException("Advance difference too great.");
}
} else {
System.out.println("Skipping test because fonts aren't as expected");
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
@test
@bug 7177173
@summary The maximized state shouldn't be reset upon hiding a frame
@author anthony.petrov@oracle.com: area=awt.toplevel
@run main HideMaximized
*/
import java.awt.*;
public class HideMaximized {
public static void main(String[] args) {
if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
// Nothing to test
return;
}
// First test a decorated frame
Frame frame = new Frame("test");
test(frame);
// Now test an undecorated frames
frame = new Frame("undecorated test");
frame.setUndecorated(true);
test(frame);
}
private static void test(Frame frame) {
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.setVisible(true);
try { Thread.sleep(1000); } catch (Exception ex) {}
if (frame.getExtendedState() != Frame.MAXIMIZED_BOTH) {
throw new RuntimeException("The maximized state has not been applied");
}
// This will hide the frame, and also clean things up for safe exiting
frame.dispose();
try { Thread.sleep(1000); } catch (Exception ex) {}
if (frame.getExtendedState() != Frame.MAXIMIZED_BOTH) {
throw new RuntimeException("The maximized state has been reset");
}
}
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Frame;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import javax.swing.SwingUtilities;
import javax.swing.event.MenuDragMouseEvent;
/**
* @test
* @bug 7170657
* @author Sergey Bylokhov
*/
public final class bug7170657 {
private static boolean FAILED;
public static void main(final String[] args) {
final int mask = InputEvent.META_DOWN_MASK | InputEvent.CTRL_MASK;
Frame f = new Frame();
MouseEvent mwe = new MouseWheelEvent(f, 1, 1, mask, 1, 1, 1, 1, 1, true,
1, 1, 1);
MouseEvent mdme = new MenuDragMouseEvent(f, 1, 1, mask, 1, 1, 1, 1, 1,
true, null, null);
MouseEvent me = new MouseEvent(f, 1, 1, mask, 1, 1, 1, 1, 1, true,
MouseEvent.NOBUTTON);
test(f, mwe);
test(f, mdme);
test(f, me);
if (FAILED) {
throw new RuntimeException("Wrong mouse event");
}
}
private static void test(final Frame frame, final MouseEvent me) {
MouseEvent newme = SwingUtilities.convertMouseEvent(frame, me, frame);
if (me.getModifiersEx() != newme.getModifiersEx()
|| me.getModifiers() != newme.getModifiers()) {
fail(me, newme);
}
}
private static void fail(final MouseEvent exp, final MouseEvent act) {
System.err.println("Expected: " + exp);
System.err.println("Actual: " + act);
FAILED = true;
}
}

Some files were not shown because too many files have changed in this diff Show More