From 6bc6236e65baec49b3495479dc6392405b1d46ce Mon Sep 17 00:00:00 2001 From: Nikita Gubarkov Date: Mon, 4 Dec 2023 18:35:10 +0100 Subject: [PATCH 001/976] JBR-6387 Revert "8315701: [macos] Regression: KeyEvent has different keycode on different keyboard layouts" --- .../classes/sun/lwawt/LWWindowPeer.java | 12 +- .../sun/lwawt/PlatformEventNotifier.java | 2 +- .../sun/lwawt/macosx/CPlatformResponder.java | 14 +- .../sun/lwawt/macosx/CWarningWindow.java | 2 +- .../macosx/native/libawt_lwawt/awt/AWTEvent.m | 13 +- .../AcceleratorTest/AcceleratorTest.html | 43 ++ .../AcceleratorTest/AcceleratorTest.java | 427 ++++++++++++------ 7 files changed, 343 insertions(+), 170 deletions(-) create mode 100644 test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 4ec8d87fee3f..7f218e4d1baa 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -1044,7 +1044,7 @@ public void notifyMouseWheelEvent(long when, int x, int y, int absX, */ @Override public void notifyKeyEvent(int id, long when, int modifiers, - int keyCode, char keyChar, int keyLocation, int extendedKeyCode) + int keyCode, char keyChar, int keyLocation) { LWKeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); Component focusOwner = kfmPeer.getCurrentFocusOwner(); @@ -1058,13 +1058,9 @@ public void notifyKeyEvent(int id, long when, int modifiers, KeyEvent keyEvent = new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation); - if (extendedKeyCode >= 0) { - AWTAccessor.getKeyEventAccessor().setExtendedKeyCode(keyEvent, extendedKeyCode); - } else { - AWTAccessor.getKeyEventAccessor().setExtendedKeyCode(keyEvent, - (keyChar == KeyEvent.CHAR_UNDEFINED) ? keyCode - : ExtendedKeyCodes.getExtendedKeyCodeForChar(keyChar)); - } + AWTAccessor.getKeyEventAccessor().setExtendedKeyCode(keyEvent, + (keyChar == KeyEvent.CHAR_UNDEFINED) ? keyCode + : ExtendedKeyCodes.getExtendedKeyCodeForChar(keyChar)); postEvent(keyEvent); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java b/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java index aea8ff2e6a93..d613b9cea25a 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java @@ -61,5 +61,5 @@ void notifyMouseWheelEvent(long when, int x, int y, final int absX, * Called by the delegate when a key is pressed. */ void notifyKeyEvent(int id, long when, int modifiers, - int keyCode, char keyChar, int keyLocation, int extendedKeyCode); + int keyCode, char keyChar, int keyLocation); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index f14c7b40cbab..2cbf308fafbb 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -143,7 +143,6 @@ void handleKeyEvent(int eventType, int modifierFlags, String chars, String chars int jeventType = KeyEvent.KEY_PRESSED; int jkeyCode = KeyEvent.VK_UNDEFINED; - int jextendedkeyCode = -1; int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN; boolean postsTyped = false; boolean spaceKeyTyped = false; @@ -174,7 +173,7 @@ void handleKeyEvent(int eventType, int modifierFlags, String chars, String chars charsIgnoringModifiers.charAt(0) : KeyEvent.CHAR_UNDEFINED; int[] in = new int[] {testCharIgnoringModifiers, isDeadChar ? 1 : 0, modifierFlags, keyCode}; - int[] out = new int[4]; // [jkeyCode, jkeyLocation, deadChar, extendedKeyCode] + int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar] postsTyped = NSEvent.nsToJavaKeyInfo(in, out); if (!postsTyped) { @@ -202,7 +201,6 @@ void handleKeyEvent(int eventType, int modifierFlags, String chars, String chars } jkeyCode = out[0]; - jextendedkeyCode = out[3]; jkeyLocation = out[1]; jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(eventType) : NSEvent.nsToJavaEventType(eventType); @@ -223,7 +221,7 @@ void handleKeyEvent(int eventType, int modifierFlags, String chars, String chars lastKeyPressCode = jkeyCode; } eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers, - jkeyCode, javaChar, jkeyLocation, jextendedkeyCode); + jkeyCode, javaChar, jkeyLocation); // Current browser may be sending input events, so don't // post the KEY_TYPED here. @@ -243,12 +241,12 @@ void handleKeyEvent(int eventType, int modifierFlags, String chars, String chars } eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, when, jmodifiers, KeyEvent.VK_UNDEFINED, javaChar, - KeyEvent.KEY_LOCATION_UNKNOWN, jextendedkeyCode); + KeyEvent.KEY_LOCATION_UNKNOWN); //If events come from Firefox, released events should also be generated. if (needsKeyReleased) { eventNotifier.notifyKeyEvent(KeyEvent.KEY_RELEASED, when, jmodifiers, jkeyCode, javaChar, - KeyEvent.KEY_LOCATION_UNKNOWN, jextendedkeyCode); + KeyEvent.KEY_LOCATION_UNKNOWN); } } } @@ -262,13 +260,13 @@ void handleInputEvent(String text) { eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, c, - KeyEvent.KEY_LOCATION_UNKNOWN, -1); + KeyEvent.KEY_LOCATION_UNKNOWN); index++; } eventNotifier.notifyKeyEvent(KeyEvent.KEY_RELEASED, System.currentTimeMillis(), 0, lastKeyPressCode, c, - KeyEvent.KEY_LOCATION_UNKNOWN, -1); + KeyEvent.KEY_LOCATION_UNKNOWN); } } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java index bcb18c76ae10..52e85e338415 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java @@ -245,7 +245,7 @@ public void notifyMouseWheelEvent(long when, int x, int y, int absX, @Override public void notifyKeyEvent(int id, long when, int modifiers, int keyCode, - char keyChar, int keyLocation, int jextendedkeyCode) { + char keyChar, int keyLocation) { } protected int getInitialStyleBits() { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index d26def5694fb..0f09c59c2c0d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -429,7 +429,7 @@ static unichar NsGetDeadKeyChar(unsigned short keyCode) NsCharToJavaVirtualKeyCode(unichar ch, BOOL isDeadChar, NSUInteger flags, unsigned short key, jint *keyCode, jint *keyLocation, BOOL *postsTyped, - unichar *deadChar, jint *extendedkeyCode) + unichar *deadChar) { static size_t size = sizeof(keyTable) / sizeof(struct _key); NSInteger offset; @@ -469,9 +469,10 @@ static unichar NsGetDeadKeyChar(unsigned short keyCode) *postsTyped = YES; // do quick conversion // the keyCode is off by 32, so adding it here - *extendedkeyCode = java_awt_event_KeyEvent_VK_A + offset + 32; + *keyCode = java_awt_event_KeyEvent_VK_A + offset + 32; *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD; - } +return; + } } if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:ch]) { @@ -694,20 +695,18 @@ jlong UTC(NSEvent *event) { jshort keyCode = (jshort)data[3]; jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; - jint jextendedkeyCode = -1; jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; jint testDeadChar = 0; NsCharToJavaVirtualKeyCode((unichar)testChar, isDeadChar, (NSUInteger)modifierFlags, (unsigned short)keyCode, &jkeyCode, &jkeyLocation, &postsTyped, - (unichar *) &testDeadChar, &jextendedkeyCode); + (unichar *) &testDeadChar); - // out = [jkeyCode, jkeyLocation, deadChar, jextendedkeyCode]; + // out = [jkeyCode, jkeyLocation, deadChar]; (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode); (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation); (*env)->SetIntArrayRegion(env, outData, 2, 1, &testDeadChar); - (*env)->SetIntArrayRegion(env, outData, 3, 1, &jextendedkeyCode); (*env)->ReleaseIntArrayElements(env, inData, data, 0); diff --git a/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html b/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html new file mode 100644 index 000000000000..e6f7dcb9d5d6 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html @@ -0,0 +1,43 @@ + + + + + + AcceleratorTest + + + +

AcceleratorTest
Bug ID:

+ +

See the dialog box (usually in upper left corner) for instructions

+ + + + diff --git a/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java b/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java index 1d9635d58caa..8d983461d745 100644 --- a/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java +++ b/test/jdk/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,170 +22,307 @@ */ /* - * @test - * @bug 6680988 - * @key headful - * @summary verify that various shortcuts and accelerators work - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual AcceleratorTest + test + @bug 6680988 + @summary verify that various shortcuts and accelerators work + @author yuri.nesterenko : area=awt.keyboard + @run applet/manual=yesno AcceleratorTest.html +*/ + +/** + * AcceleratorTest.java + * + * summary: */ -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; +//import java.applet.Applet; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; import java.util.Hashtable; -import javax.swing.AbstractAction; -import javax.swing.InputMap; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JTextArea; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; - -public class AcceleratorTest { - static JFrame output; - static JTextArea text; - static JFrame jfr; - static Hashtable cmdHash = new Hashtable(); - static String[] CMD = { - "\u042E, keep me in focus", - "Item Ctrl Be", - "Item Ctrl English Period", - "Item Ctrl English N", - "\u0436" + + +public class AcceleratorTest extends JApplet +{ + //Declare things used in the test, like buttons and labels here + static int pressed = 0; + Hashtable cmdHash = new Hashtable(); + String[] CMD = { + "\u042E, keep me in focus", + "Item Cyrl Be", + "Item English Period", + "Item English N", + "\u0436" }; - public static void main(String[] args) throws Exception { - String instructions = - "Ensure you have Russian keyboard layout as a currently active.\n" + - "(1) Press Ctrl + \u0411 (a key with \",<\" on it) \n" + - "(2) Find a . (period) in this layout (perhaps \"/?\" or \"7&\" key). " + - "Press Ctrl + .\n" + - "(3) Press Ctrl + regular English . (period) key (on \".>\" )\n" + - "(4) Press Ctrl + key with English N.\n" + - "(5) Press Alt + \u042E (key with \".>\")\n" + - "(6) Press Alt + \u0436 (key with \";:\")\n" + - "If all expected commands will be fired, look for message\n" + - "\"All tests passed\""; - - for (int i = 0; i < CMD.length; i++) { + JFrame jfr; + + public void init() + { + //Create instructions for the user here, as well as set up + // the environment -- set the layout manager, add buttons, + // etc. + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + " Ensure you have Russian keyboard layout as a currently active.", + "(1) Press Ctrl+\u0411 (a key with \",<\" on it) ", + "(2) Find a . (period) in this layout (perhaps \"/?\" or \"7&\" key).", + "Press Ctrl+.", + "(3) Press Crtl+ regular English . (period) key (on \".>\" )", + "(4) Press Ctrl+ key with English N.", + "(5) Press Alt+\u042E (key with \".>\")", + "(6) Press Alt+\u0436 (key with \";:\")", + "If all expected commands will be fired, look for message", + "\"All tests passed\"" + }; + Sysout.createDialogWithInstructions( instructions ); + for(int i = 0; i < CMD.length; i++) { cmdHash.put(CMD[i], 0); } - PassFailJFrame testFrame = new PassFailJFrame.Builder() - .title("Test Instructions Frame") - .instructions(instructions) - .testTimeOut(10) - .rows(10) - .columns(45) - .build(); - - SwingUtilities.invokeAndWait(() -> { - output = new JFrame("output"); - text = new JTextArea(); - output.getContentPane().add(text); - - jfr = new JFrame("AcceleratorTest"); - jfr.setLayout(new BorderLayout()); - JButton jbu; - jfr.add((jbu = new JButton(CMD[0]))); - jbu.setMnemonic(java.awt.event.KeyEvent.getExtendedKeyCodeForChar('\u042E')); - jbu.addActionListener(new ALi(CMD[0])); - - JMenuBar menuBar = new JMenuBar(); - jfr.setJMenuBar(menuBar); - JMenu menu = new JMenu("Menu"); - menuBar.add(menu); - - JMenuItem menuItem = new JMenuItem(CMD[1]); - menuItem.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent - .getExtendedKeyCodeForChar('\u0431'), InputEvent.CTRL_DOWN_MASK)); - - JMenuItem menuItemEnglish = new JMenuItem(CMD[2]); - menuItemEnglish.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, - InputEvent.CTRL_DOWN_MASK)); - - JMenuItem menuItemE1 = new JMenuItem(CMD[3]); - menuItemE1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, - InputEvent.CTRL_DOWN_MASK)); - - menuItem.addActionListener(new ALi(CMD[1])); - menuItemEnglish.addActionListener(new ALi(CMD[2])); - menuItemE1.addActionListener(new ALi(CMD[3])); - - menu.add(menuItem); - menu.add(menuItemEnglish); - menu.add(menuItemE1); - - KeyStroke ks; - InputMap im = new InputMap(); - ks = KeyStroke.getKeyStroke(KeyEvent.getExtendedKeyCodeForChar('\u0436'), - java.awt.event.InputEvent.ALT_DOWN_MASK); - im.put(ks, "pushAction"); - im.setParent(jbu.getInputMap(JComponent.WHEN_FOCUSED)); - jbu.setInputMap(JComponent.WHEN_FOCUSED, im); - - jbu.getActionMap().put("pushAction", - new AbstractAction("pushAction") { - public void actionPerformed(ActionEvent evt) { - if (evt.getActionCommand().equals(CMD[4])) { - cmdHash.put(CMD[4], 1); - } - boolean notYet = false; - for (int i = 0; i < CMD.length; i++) { - if (cmdHash.get(CMD[i]) == 0) notYet = true; - } - text.append(evt.getActionCommand() + " FIRED\n"); - if (!notYet) { - text.append("All tests passed."); - } - } - } - ); - }); - - testFrame.addTestWindow(jfr); - testFrame.addTestWindow(output); - - PassFailJFrame.positionTestWindow(jfr, PassFailJFrame.Position.HORIZONTAL); - jfr.setSize(200, 200); - - PassFailJFrame.positionTestWindow(output, PassFailJFrame.Position.HORIZONTAL); - output.setSize(200, 200); + jfr = new JFrame(); + JButton jbu; + jfr.add((jbu = new JButton(CMD[0]))); + jbu.setMnemonic(java.awt.event.KeyEvent.getExtendedKeyCodeForChar('\u042E')); + jbu.addActionListener( new ALi(CMD[0])); + + + JMenuBar menuBar = new JMenuBar(); + jfr.setJMenuBar(menuBar); + JMenu menu = new JMenu("Menu"); + menuBar.add(menu); + JMenuItem menuItem = new JMenuItem(CMD[1]); + menuItem.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.getExtendedKeyCodeForChar('\u0431'), + InputEvent.CTRL_DOWN_MASK)); + + JMenuItem menuItemEnglish = new JMenuItem(CMD[2]); + menuItemEnglish.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, + InputEvent.CTRL_DOWN_MASK)); + JMenuItem menuItemE1 = new JMenuItem(CMD[3]); + menuItemE1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, + InputEvent.CTRL_DOWN_MASK)); + menuItem.addActionListener( new ALi(CMD[1])); + menuItemEnglish.addActionListener( new ALi(CMD[2])); + menuItemE1.addActionListener( new ALi(CMD[3])); + menu.add(menuItem); + menu.add(menuItemEnglish); + menu.add(menuItemE1); + + KeyStroke ks; + InputMap im = new InputMap(); + ks = KeyStroke.getKeyStroke(KeyEvent.getExtendedKeyCodeForChar('\u0436'), java.awt.event.InputEvent.ALT_DOWN_MASK); + im.put(ks, "pushAction"); + im.setParent(jbu.getInputMap(JComponent.WHEN_FOCUSED)); + jbu.setInputMap(JComponent.WHEN_FOCUSED, im); + + jbu.getActionMap().put("pushAction", + new AbstractAction("pushAction") { + public void actionPerformed(ActionEvent evt) { + if( evt.getActionCommand().equals(CMD[4])) { + cmdHash.put(CMD[4], 1); + } + boolean notYet = false; + for(int i = 0; i < CMD.length; i++) { + if(cmdHash.get(CMD[i]) == 0 ) notYet = true; + } + Sysout.println("Fired"); + if( !notYet ) { + Sysout.println("All tests passed."); + } + } + } + ); + + + jfr.setBounds(650,0,200,200); jfr.setVisible(true); - output.setVisible(true); - testFrame.awaitAndCheck(); - } + }//End init() - public static class ALi implements ActionListener { - String expectedCmd; + public void start () + { + //Get things going. Request focus, set size, et cetera + setSize (200,200); + setVisible(true); + validate(); - public ALi(String eCmd) { + }// start() + public class ALi implements ActionListener { + String expectedCmd; + public ALi( String eCmd ) { expectedCmd = eCmd; } - public void actionPerformed(ActionEvent ae) { - if (cmdHash.containsKey(ae.getActionCommand())) { + if( cmdHash.containsKey(ae.getActionCommand()) ) { cmdHash.put(expectedCmd, 1); } boolean notYet = false; - for (int i = 0; i < CMD.length; i++) { - if (cmdHash.get(CMD[i]) == 0) notYet = true; - //text.append(CMD[i]+":"+cmdHash.get(CMD[i])); + for(int i = 0; i < CMD.length; i++) { + if(cmdHash.get(CMD[i]) == 0 ) notYet = true; + //Sysout.println(CMD[i]+":"+cmdHash.get(CMD[i])); } - text.append(ae.getActionCommand() + " FIRED\n"); - if (!notYet) { - text.append("All tests passed.\n"); + Sysout.println("FIRED"); + if( !notYet ) { + Sysout.println("All tests passed."); } } } -} + + +}// class AcceleratorTest + +/* Place other classes related to the test after this line */ + + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + private static boolean numbering = false; + private static int messageNumber = 0; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + /* Enables message counting for the tester. */ + public static void enableNumbering(boolean enable){ + numbering = enable; + } + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + if (numbering) { + messageIn = "" + messageNumber + " " + messageIn; + messageNumber++; + } + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class From be746623d6ace451049919306fd75c9b223fa9bd Mon Sep 17 00:00:00 2001 From: "Vitaly.Provodin" Date: Tue, 24 Dec 2019 07:08:54 +0700 Subject: [PATCH 002/976] updated JTreg exclude list --- test/hotspot/jtreg/jbProblemList.txt | 159 +++++ test/jdk/jbProblemList.txt | 892 +++++++++++++++++++++++++++ 2 files changed, 1051 insertions(+) create mode 100644 test/hotspot/jtreg/jbProblemList.txt create mode 100644 test/jdk/jbProblemList.txt diff --git a/test/hotspot/jtreg/jbProblemList.txt b/test/hotspot/jtreg/jbProblemList.txt new file mode 100644 index 000000000000..3a565de150bd --- /dev/null +++ b/test/hotspot/jtreg/jbProblemList.txt @@ -0,0 +1,159 @@ +# +# Copyright (c) 2016, 2020, 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. +# + +############################################################################# +# +# List of quarantined tests -- tests that should not be run by default, because +# they may fail due to known reason. The reason (CR#) must be mandatory specified. +# +# List items are testnames followed by labels, all MUST BE commented +# as to why they are here and use a label: +# generic-all Problems on all platforms +# generic-ARCH Where ARCH is one of: x64, i586, ppc64, ppc64le, s390x etc. +# OSNAME-all Where OSNAME is one of: linux, windows, macosx, aix +# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. macosx-x64 +# OSNAME-REV Specific on to one OSNAME and REV, e.g. macosx-10.7.4 +# +# More than one label is allowed but must be on the same line. +# +############################################################################# + +# :hotspot_compiler + +compiler/ciReplay/TestSAServer.java 8029528 generic-all +compiler/codecache/jmx/PoolsIndependenceTest.java 8167015 generic-all +compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8225370 generic-all +compiler/jvmci/compilerToVM/GetFlagValueTest.java 8204459 generic-all +compiler/tiered/LevelTransitionTest.java 8067651 generic-all + +compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all + +compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x + +compiler/rtm/locking/TestRTMAbortRatio.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMAbortThreshold.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMLockingCalculationDelay.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMLockingThreshold.java 8183263 generic-x64 +compiler/rtm/locking/TestRTMSpinLoopCount.java 8183263 generic-x64 +compiler/rtm/locking/TestUseRTMDeopt.java 8183263 generic-x64 +compiler/rtm/locking/TestUseRTMXendForLockBusy.java 8183263 generic-x64 +compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java 8183263 generic-x64 + +compiler/c2/Test8004741.java 8235801 generic-all + +############################################################################# + +# :hotspot_gc + +gc/epsilon/TestMemoryMXBeans.java 8206434 generic-all +gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all +gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all +gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all +gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all +gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all +gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all +gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all +gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 + +############################################################################# + +# :hotspot_runtime + +runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP_JFR.java 8253437 windows-x64 +runtime/cds/DeterministicDump.java 8253495 generic-all +runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64 +runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all +containers/docker/TestJFRWithJMX.java 8256417 linux-5.4.17-2011.5.3.el8uek.x86_64 + +############################################################################# + +# :hotspot_serviceability + +serviceability/sa/sadebugd/DebugdConnectTest.java 8239062 macosx-x64 +serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all + +serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatIntervalTest.java 8214032 generic-all +serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java 8224150 generic-all +serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all + +serviceability/attach/RemovingUnixDomainSocketTest.java 8248162 linux-x64 + +############################################################################# + +# :hotspot_misc + +############################################################################# + + +############################################################################# + +# :vmTestbase_* + +############################################################################# + +vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded003/TestDescription.java 8153598 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded001/TestDescription.java 8198668 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded002/TestDescription.java 8153598 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded003/TestDescription.java 8198668 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded004/TestDescription.java 8153598 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded005/TestDescription.java 8153598 generic-all +vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestDescription.java 8060733 generic-all + +vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all + +vmTestbase/nsk/jdb/eval/eval001/eval001.java 8221503 generic-all + +vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all +vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all +vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8208250 generic-all +vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8208250 generic-all + +vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8202971 generic-all +vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/TestDescription.java 8219652 aix-ppc64 +vmTestbase/nsk/jvmti/scenarios/jni_interception/JI06/ji06t001/TestDescription.java 8219652 aix-ppc64 +vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/TestDescription.java 8219652 aix-ppc64 + +vmTestbase/gc/lock/jni/jnilock002/TestDescription.java 8192647 generic-all + +vmTestbase/jit/escape/LockCoarsening/LockCoarsening001.java 8148743 generic-all +vmTestbase/jit/escape/LockCoarsening/LockCoarsening002.java 8208259 generic-all + +vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInBootstrap/TestDescription.java 8013267 generic-all +vmTestbase/vm/mlvm/meth/func/java/throwException/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id1 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/sequences/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/gc/callSequencesDuringGC/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/java/sequences/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/jdi/breakpointInCompiledCode/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_a/TestDescription.java 8013267 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_b/TestDescription.java 8013267 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java 8013267 generic-all + + +vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all + +############################################################################# diff --git a/test/jdk/jbProblemList.txt b/test/jdk/jbProblemList.txt new file mode 100644 index 000000000000..dc71ee886d3b --- /dev/null +++ b/test/jdk/jbProblemList.txt @@ -0,0 +1,892 @@ +########################################################################### +# +# Copyright (c) 2009, 2021, 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. +# +########################################################################### +# +# List of tests that should not be run by test/Makefile, for various reasons: +# 1. Does not run with jtreg -samevm mode +# 2. Causes problems in jtreg -samevm mode for jtreg or tests that follow it +# 3. The test is too slow or consumes too many system resources +# 4. The test fails when run on any official build systems +# +# It is possible that a test being on this list is a mistake, and that some +# other test in samevm mode caused tests to fail, mistakes happen. +# +# Tests marked @ignore are not run by test/Makefile, but harmless to be listed. +# +# Tests that explicitly state "@run main/othervm ...", and are not listed here, +# will be run in the same batch as the samevm tests. +# +# Shell tests are othervm by default. +# +# List items are testnames followed by labels, all MUST BE commented +# as to why they are here and use a label: +# generic-all Problems on all platforms +# generic-ARCH Where ARCH is one of: x64, i586, ppc64, ppc64le, s390x, aarch64 etc. +# OSNAME-all Where OSNAME is one of: linux, windows, macosx, aix +# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. macosx-x64 +# OSNAME-REV Specific on to one OSNAME and REV, e.g. macosx-10.7.4 +# +# More than one label is allowed but must be on the same line comma seperated, +# without spaces. +# If there are several lines mentioning the same test, the last one is used. +# +############################################################################# +# +# Running the tests: +# cd test && make JT_HOME=jtreg_home PRODUCT_HOME=jdk_home jdk_all +# Or instead of jdk_all, use any of the jdk_* targets. +# +# Samevm Notes: +# * Although some tests may have only been seen to fail on some platforms, +# they might be flagged as 'generic-all' because the problem they have +# could cause hidden slowdowns on other platforms. +# Most samevm problems will be generic-all, but windows usually dislikes +# them the most. +# Address already in use or connection errors indicate a generic port issue. +# (this is not necessarily a samevm issue, but an issue for running the tests +# on shared machines, two people or two test runs will collide). +# * Samevm problem (windows in particular) is not closing all input/output +# * Samevm problem when a test calls setSecurityManager() +# * Samevm problem with setHttps*() is used? (not exactly sure here) +# * Samevm problem when stuffing system properties with non Strings or anything +# * Samevm problem when changing vm settings, or registering any vm actions +# * Samevm problems with deleteOnExit(), if it must happen at end of test +# * Samevm problems with URLClassLoader? (no details here) +# * Samevm problems with dependence on predictable GC or finalizations +# +# Any of the above problems may mean the test needs to be flagged as "othervm". +# +############################################################################# +# +# Fixing the tests: +# +# Some tests just may need to be run with "othervm", and that can easily be +# done by adding a @run line (or modifying any existing @run): +# @run main/othervm NameOfMainClass +# Make sure this @run follows any use of @library. +# Otherwise, if the test is a samevm possibility, make sure the test is +# cleaning up after itself, closing all streams, deleting temp files, etc. +# +# Keep in mind that the bug could be in many places, and even different per +# platform, it could be a bug in any one of: +# - the testcase +# - the jdk (jdk classes, native code, or hotspot) +# - the native compiler +# - the javac compiler +# - the OS (depends on what the testcase does) +# +# If you managed to really fix one of these tests, here is how you can +# remove tests from this list: +# 1. Make sure test passes on all platforms with samevm, or mark it othervm +# 2. Make sure test passes on all platforms when run with it's entire group +# 3. Make sure both VMs are tested, -server and -client, if possible +# 4. Use your favorite build and test system to verify these results +# 5. Delete lines in this file, include the changes with your test changes +# +# You may need to repeat your testing 2 or even 3 times to verify good +# results, some of these samevm failures are not very predictable. +# +############################################################################# + +############################################################################ + +# jdk_awt + +java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java 8168389 windows-all,macosx-all +java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java 8224055 macosx-all +java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java 8168408 windows-all,macosx-all +java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generic-all +java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all +java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all +java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all +java/awt/Focus/UnaccessibleChoice/AccessibleChoiceTest.java 8239801 macosx-all +java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all +java/awt/Frame/FrameLocation/FrameLocation.java 8233703 linux-all +java/awt/FileDialog/FileDialogIconTest/FileDialogIconTest.java 8160558 windows-all +java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion.java 8060176 windows-all,macosx-all +java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_1.java 8060176 windows-all,macosx-all +java/awt/dnd/DropTargetEnterExitTest/MissedDragExitTest.java 8159694 linux-all +java/awt/dnd/MissingEventsOnModalDialog/MissingEventsOnModalDialogTest.java 8164464 linux-all,macosx-all +java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java 8171510 macosx-all +javax/swing/dnd/7171812/bug7171812.java 8041447 macosx-all +java/awt/Focus/ChoiceFocus/ChoiceFocus.java 8169103 windows-all,macosx-all +java/awt/Focus/ClearLwQueueBreakTest/ClearLwQueueBreakTest.java 8198618 macosx-all +java/awt/Focus/ConsumeNextKeyTypedOnModalShowTest/ConsumeNextKeyTypedOnModalShowTest.java 6986252 macosx-all +java/awt/Focus/FocusTraversalPolicy/ButtonGroupLayoutTraversal/ButtonGroupLayoutTraversalTest.java 8198619 macosx-all +java/awt/Focus/KeyEventForBadFocusOwnerTest/KeyEventForBadFocusOwnerTest.java 8198621 macosx-all +java/awt/Focus/MouseClickRequestFocusRaceTest/MouseClickRequestFocusRaceTest.java 8194753 linux-all,macosx-all +java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java 7152980 macosx-all +java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java 8159599 macosx-all +java/awt/Focus/TypeAhead/TestFocusFreeze.java 8198622,6447537 macosx-all,windows-all,linux-all +java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java 7156130 linux-all +java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java 8169096 macosx-all +java/awt/event/KeyEvent/CorrectTime/CorrectTime.java 6626492 generic-all +java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all +java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.java 8198237 macosx-all +java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java 8144030 macosx-all,linux-all +java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all +java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all +java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java 8198626 macosx-all +java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all +java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all +java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all +java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java 6986109 generic-all +java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java 6986109 windows-all +java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java 8049405 generic-all +java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405 macosx-all +java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java 8049405 macosx-all +java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JListOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTableOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java 8158801 windows-all +java/awt/Mixing/MixingOnDialog.java 8225777 linux-all +java/awt/Mixing/NonOpaqueInternalFrame.java 7124549 macosx-all +java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java 8168388 linux-all +java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java 6829264 generic-all +java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java 8080982 generic-all +java/awt/datatransfer/SystemFlavorMap/AddFlavorTest.java 8079268 linux-all +java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java 6829250 windows-all +java/awt/Toolkit/RealSync/Test.java 6849383 linux-all +java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java 8159252 windows-all +java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java 8203047 macosx-all +java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636 macosx-all +java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055 windows-all,linux-all +java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all +java/awt/Focus/6378278/InputVerifierTest.java 8198616 macosx-all +java/awt/Focus/6382144/EndlessLoopTest.java 8198617 macosx-all +java/awt/Focus/6981400/Test1.java 8029675 windows-all,macosx-all +java/awt/Focus/8073453/AWTFocusTransitionTest.java 8136517 macosx-all +java/awt/Focus/8073453/SwingFocusTransitionTest.java 8136517 macosx-all +java/awt/Focus/6981400/Test3.java 8173264 generic-all +java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all +java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474,8224055 macosx-all,windows-all +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_3.java 6854300 generic-all +java/awt/event/KeyEvent/ExtendedModifiersTest/ExtendedModifiersTest.java 8129778 generic-all +java/awt/event/KeyEvent/KeyMaskTest/KeyMaskTest.java 8129778 generic-all +java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java 8252713 linux-all +java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTest.java 8129778 generic-all + +java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java 8194947 generic-all +java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all +java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java 8047218 generic-all +java/awt/GridLayout/LayoutExtraGaps/LayoutExtraGaps.java 8000171 windows-all +java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java 8196017 windows-all +java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java 8196018 windows-all,linux-all +java/awt/TrayIcon/ActionCommand/ActionCommand.java 8150540 windows-all +java/awt/TrayIcon/ActionEventMask/ActionEventMask.java 8150540 windows-all +java/awt/TrayIcon/ActionEventTest/ActionEventTest.java 8150540,8242801 windows-all,macosx-all +java/awt/TrayIcon/ModalityTest/ModalityTest.java 8150540 windows-all,macosx-all +java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java 8150540 windows-all +java/awt/TrayIcon/MouseMovedTest/MouseMovedTest.java 8150540 windows-all +java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java 8150540 windows-all +java/awt/TrayIcon/SystemTrayInstance/SystemTrayInstanceTest.java 8193543 linux-all +java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java 8150540 windows-all +java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java 8150540 windows-all +java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java 8150540 windows-all +java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java 8150540 windows-all,macosx-all +java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java 8150540 windows-all +java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java 8196440 linux-all + +java/awt/Window/ShapedAndTranslucentWindows/SetShapeAndClick.java 8197936 macosx-all +java/awt/Window/ShapedAndTranslucentWindows/SetShapeDynamicallyAndClick.java 8013450 macosx-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java 8013450 macosx-all +java/awt/Window/ShapedAndTranslucentWindows/TranslucentChoice.java 8221901 linux-all +java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java 8222323 windows-all +java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8222328 windows-all,linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/Shaped.java 8222328 windows-all,linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedByAPI.java 8222328 windows-all,linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucent.java 8222328 windows-all,linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8165218,8222328 windows-all,macosx-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/Translucent.java 8222328 windows-all,linux-all,macosx-all +java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 linux-all +java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all +java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all +java/awt/font/TextLayout/CombiningPerf.java 8192931 generic-all +java/awt/font/TextLayout/TextLayoutBounds.java 8169188 generic-all +java/awt/font/StyledMetrics/BoldSpace.java 8198422 linux-all +java/awt/FontMetrics/FontCrash.java 8198336 windows-all +java/awt/image/BufferedImage/ICMColorDataTest/ICMColorDataTest.java 8233028 generic-all +java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 linux-all +java/awt/image/DrawImage/BlitRotateClippedArea.java 8255724 linux-all +java/awt/image/multiresolution/MultiresolutionIconTest.java 8169187 macosx-all,windows-all +java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all +sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all +sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all +sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java 8022403 generic-all +sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all +sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all +java/awt/Graphics2D/CopyAreaOOB.java 7001973 windows-all,macosx-all +sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all +sun/java2d/SunGraphics2D/DrawImageBilinear.java 8191406 generic-all +sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all +sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all +sun/java2d/SunGraphics2D/SourceClippingBlitTest/SourceClippingBlitTest.java 8196185 generic-all + +sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.sh 8221451 linux-all +java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java 8169469 windows-all +java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8197796 generic-all +java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java 8196300 windows-all +java/awt/print/PrinterJob/PSQuestionMark.java 7003378 generic-all +java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all +java/awt/print/PrinterJob/Margins.java 8196301 windows-all,macosx-all +java/awt/PrintJob/PrinterException.java 8196301 windows-all,macosx-all +java/awt/Choice/PopupPosTest/PopupPosTest.java 8197811 windows-all +java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 7100044 macosx-all,linux-all +java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all +java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java 8165863 macosx-all +java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all +java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java 8000171 windows-all +java/awt/Frame/MiscUndecorated/RepaintTest.java 8079267 windows-all,linux-all +java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java 8157173 generic-all +java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogAppModal3Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogAppModal4Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogAppModal5Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogAppModal6Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal1Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal2Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal3Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal4Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal5Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal6Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogDocModal7Test.java 7186009 macosx-all,linux-all +java/awt/Modal/FileDialog/FileDialogModal1Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogModal2Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogModal3Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogModal4Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogModal5Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogModal6Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogNonModal1Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogNonModal2Test.java 7186009 macosx-all,linux-all +java/awt/Modal/FileDialog/FileDialogNonModal3Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogNonModal4Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogNonModal5Test.java 7186009 macosx-all +java/awt/Modal/FileDialog/FileDialogNonModal6Test.java 7186009 macosx-all,linux-all +java/awt/Modal/FileDialog/FileDialogNonModal7Test.java 7186009 macosx-all,linux-all +java/awt/Modal/FileDialog/FileDialogTKModal1Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal2Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal3Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal4Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal5Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal6Test.java 8196430 generic-all +java/awt/Modal/FileDialog/FileDialogTKModal7Test.java 8196430 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDAppModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDDocModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDModelessTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDNonModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDSetModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDToolkitModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFAppModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFSetModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFToolkitModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFWModeless1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFWModeless2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDocModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDModelessTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDNonModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal5Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal6Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal5Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal6Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal1Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal2Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal3Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal4Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal5Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal6Test.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogAppModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogDocModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogModelessTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogNonModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogSetModalTest.java 8198665 macosx-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogToolkitModalTest.java 8198665 macosx-all +java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java 8066259 macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFrameFileTest.java 8047179 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogFileTest.java 8047179 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPageSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPrintSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePageSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePrintSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFrameFileTest.java 8047179 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogFileTest.java 8047179 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPageSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPrintSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePageSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePrintSetupTest.java 8196431 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFAppModal2Test.java 8058813 windows-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless2Test.java 8196191 windows-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFDocModalTest.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFModelessTest.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFNonModalTest.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsModelessTest.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsNonModalTest.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWDocModalTest.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWModelessTest.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWNonModalTest.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal1Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal2Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal3Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal4Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal1Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal2Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal3Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal4Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless1Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless2Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless3Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless4Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal1Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal2Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal3Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal4Test.java 8196432 linux-all,macosx-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFDocModal2Test.java 8196432 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal2Test.java 8196432 linux-all +java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java 8198665 macosx-all +java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665 macosx-all +java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all +java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all +java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all +java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all +java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8023562 macosx-all +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all +java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all +java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407 macosx-all +java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170 macosx-all +java/awt/Modal/ToFront/DialogToFrontModeless1Test.java 8213530 linux-all +java/awt/Modal/ToFront/DialogToFrontNonModalTest.java 8221899 linux-all +java/awt/Modal/ToBack/ToBackAppModal1Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackAppModal2Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackAppModal3Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackAppModal4Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackAppModal5Test.java 8196441 macosx-all +java/awt/Modal/ToBack/ToBackAppModal6Test.java 8196441 linux-all +java/awt/Modal/ToBack/ToBackModal1Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackModal2Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackModal3Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackModal4Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackTKModal1Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackTKModal2Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackTKModal3Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackTKModal4Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackTKModal5Test.java 8196441 macosx-all +java/awt/Modal/ToBack/ToBackDocModal1Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackDocModal2Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackDocModal3Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackDocModal4Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackDocModal5Test.java 8196441 linux-all,macosx-all +java/awt/Modal/ToBack/ToBackModeless1Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackModeless2Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackModeless3Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackModeless4Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackModeless5Test.java 8196441 macosx-all +java/awt/Modal/ToBack/ToBackNonModal1Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackNonModal2Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackNonModal3Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackNonModal4Test.java 8196441 macosx-all,linux-all +java/awt/Modal/ToBack/ToBackNonModal5Test.java 8196441 macosx-all +java/awt/Modal/OnTop/OnTopAppModal1Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopAppModal2Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopAppModal3Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopAppModal4Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopAppModal5Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopAppModal6Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal1Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal2Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal3Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal4Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal5Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopDocModal6Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal1Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal2Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal3Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal4Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal5Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModal6Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless1Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless2Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless3Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless4Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless5Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopModeless6Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal1Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal2Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal3Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal4Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal5Test.java 8198666 macosx-all +java/awt/Modal/OnTop/OnTopTKModal6Test.java 8198666 macosx-all +java/awt/List/SingleModeDeselect/SingleModeDeselect.java 8196367 windows-all +java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java 8061235 macosx-all +javax/print/PrintSEUmlauts/PrintSEUmlauts.java 8135174 generic-all +java/awt/font/TextLayout/LigatureCaretTest.java 8197821 generic-all +java/awt/image/VolatileImage/CustomCompositeTest.java 8199002 windows-all,linux-all +java/awt/image/VolatileImage/GradientPaints.java 8199003 linux-all +java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all +java/awt/Debug/DumpOnKey/DumpOnKey.java 8202667 windows-all +java/awt/Robot/RobotWheelTest/RobotWheelTest.java 8129827 generic-all +java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java 8202926 linux-all +java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all +java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java 8202790 macosx-all,linux-all +java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882,8255898 linux-all,macosx-all +java/awt/dnd/MissingDragExitEventTest/MissingDragExitEventTest.java 8030121 macosx-all,linux-all +java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java 8202931 macosx-all,linux-all +java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all +java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all,linux-all +java/awt/Component/NativeInLightShow/NativeInLightShow.java 8202932 linux-all +java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all +java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all +java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all +java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all +java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all +java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all +java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java 8148041 linux-all +java/awt/Toolkit/DesktopProperties/rfe4758438.java 8193547 linux-all +java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163 +java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all +java/awt/im/memoryleak/InputContextMemoryLeakTest.java 8023814 linux-all +java/awt/Frame/DisposeParentGC/DisposeParentGC.java 8079786 macosx-all +java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 8169468 macosx-all +java/awt/TextArea/AutoScrollOnSelectAndAppend/AutoScrollOnSelectAndAppend.java 8213120 macosx-all + +java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223 linux-all,windows-all +java/awt/Window/WindowResizing/DoubleClickTitleBarTest.java 8233557 macosx-all +java/awt/Window/WindowOwnedByEmbeddedFrameTest/WindowOwnedByEmbeddedFrameTest.java 8233558 macosx-all +java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8233564 macosx-all +java/awt/Modal/NullModalityDialogTest/NullModalityDialogTest.java 8233565 macosx-all +java/awt/keyboard/AllKeyCode/AllKeyCode.java 8242930 macosx-all +java/awt/FullScreen/8013581/bug8013581.java 8169471 macosx-all +java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.java 8233567 macosx-all +java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java 8233568 macosx-all +java/awt/event/MouseEvent/MultipleMouseButtonsTest/MultipleMouseButtonsTest.java 8233568 macosx-all +java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java 8233568 macosx-all +java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java 8233568 macosx-all +java/awt/event/KeyEvent/DeadKey/deadKeyMacOSX.java 8233568 macosx-all +com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java 8233648 macosx-all +java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java 7185258 macosx-all +java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed.java 8238720 windows-all +java/awt/PopupMenu/PopupMenuLocation.java 8238720 windows-all +java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720 windows-all +java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720 windows-all +java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java + + +############################################################################ + +# jdk_beans + +java/beans/Introspector/8132566/OverridePropertyInfoTest.java 8132565 generic-all +java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java 8132565 generic-all + +java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all + +############################################################################ + +# jdk_foreign + +java/foreign/TestMismatch.java 8249684 macosx-all + +############################################################################ + +# jdk_lang + +java/lang/StringCoding/CheckEncodings.sh 7008363 generic-all +java/lang/ProcessHandle/InfoTest.java 8211847 aix-ppc64 +java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic-all +java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all +java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-x64 + +############################################################################ + +# jdk_instrument + +java/lang/instrument/RedefineBigClass.sh 8065756 generic-all +java/lang/instrument/RetransformBigClass.sh 8065756 generic-all + +java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all +java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all + +javax/management/monitor/DerivedGaugeMonitorTest.java 8042211 generic-all + +############################################################################ + +# jdk_io + +java/io/pathNames/GeneralWin32.java 8180264 windows-all + +############################################################################ + +# jdk_management + +com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all +com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all + +java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8247426 generic-all + +sun/management/jdp/JdpDefaultsTest.java 8241865 macosx-all +sun/management/jdp/JdpJmxRemoteDynamicPortTest.java 8241865 macosx-all +sun/management/jdp/JdpSpecificAddressTest.java 8241865 macosx-all + +############################################################################ + +# jdk_jmx + +javax/management/MBeanServer/OldMBeanServerTest.java 8030957 aix-all + +javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java 8042215 generic-all + +############################################################################ + +# jdk_net + +java/net/MulticastSocket/NoLoopbackPackets.java 7122846 macosx-all +java/net/MulticastSocket/SetLoopbackMode.java 7122846 macosx-all + +java/net/MulticastSocket/Test.java 7145658 macosx-all + +java/net/MulticastSocket/SetGetNetworkInterfaceTest.java 8219083 windows-all + +java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64 + +############################################################################ + +# jdk_nio + +java/nio/channels/DatagramChannel/Unref.java 8233519 generic-all + +java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64 + +java/nio/channels/Selector/Wakeup.java 6963118 windows-all + +############################################################################ + +# jdk_rmi + +java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java 7140992 generic-all + +java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-all + +java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all + +java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all + +java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java 8169569 windows-all + +java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java 8170562 generic-all + +java/rmi/registry/readTest/CodebaseTest.java 8173324 windows-all + +java/rmi/Naming/DefaultRegistryPort.java 8005619 windows-all +java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java 8005619 windows-all + +############################################################################ + +# jdk_sctp + +com/sun/nio/sctp/SctpMultiChannel/SendFailed.java 8141694 linux-all + +com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java 8141694 linux-all + +com/sun/nio/sctp/SctpChannel/SocketOptionTests.java 8141694 linux-all + +############################################################################ + +# jdk_security + +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-all + +sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all + +sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java 8026393 generic-all + +javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java 8212096 generic-all +javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 + +sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all + +sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8209398 generic-all + +security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all + +sun/security/smartcardio/TestChannel.java 8039280 generic-all +sun/security/smartcardio/TestConnect.java 8039280 generic-all +sun/security/smartcardio/TestConnectAgain.java 8039280 generic-all +sun/security/smartcardio/TestControl.java 8039280 generic-all +sun/security/smartcardio/TestDefault.java 8039280 generic-all +sun/security/smartcardio/TestDirect.java 8039280 generic-all +sun/security/smartcardio/TestExclusive.java 8039280 generic-all +sun/security/smartcardio/TestMultiplePresent.java 8039280 generic-all +sun/security/smartcardio/TestPresent.java 8039280 generic-all +sun/security/smartcardio/TestTransmit.java 8039280 generic-all +com/sun/crypto/provider/Cipher/DES/PerformanceTest.java 8039280 generic-all +com/sun/security/auth/callback/TextCallbackHandler/Default.java 8039280 generic-all +com/sun/security/auth/callback/TextCallbackHandler/Password.java 8039280 generic-all +com/sun/security/sasl/gsskerb/AuthOnly.java 8039280 generic-all +com/sun/security/sasl/gsskerb/ConfSecurityLayer.java 8039280 generic-all +com/sun/security/sasl/gsskerb/NoSecurityLayer.java 8039280 generic-all +javax/security/auth/kerberos/KerberosHashEqualsTest.java 8039280 generic-all +javax/security/auth/kerberos/KerberosTixDateTest.java 8039280 generic-all +sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 generic-all +sun/security/provider/PolicyParser/ExtDirsChange.java 8039280 generic-all +sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all + +############################################################################ + +# jdk_sound +javax/sound/sampled/DirectAudio/bug6372428.java 8055097 generic-all +javax/sound/sampled/Clip/bug5070081.java 8055097 generic-all +javax/sound/sampled/DataLine/LongFramePosition.java 8055097 generic-all + +javax/sound/sampled/Clip/Drain/ClipDrain.java 7062792 generic-all + +javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all + +javax/sound/midi/Sequencer/Recording.java 8167580 linux-all +javax/sound/midi/Sequencer/MetaCallback.java 8178698 linux-all + +############################################################################ + +# jdk_imageio + +############################################################################ + +# jdk_swing + +javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all + +javax/swing/border/TestTitledBorderLeak.java 8213531 linux-all +javax/swing/JComponent/6683775/bug6683775.java 8172337 generic-all +javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all +javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java 8233582 linux-all +javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java 8194128 macosx-all +javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java 8013450 macosx-all +javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java 8024627 macosx-all +# The next test below is an intermittent failure +javax/swing/JComboBox/8033069/bug8033069ScrollBar.java 8163367 generic-all +javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all +javax/swing/JTree/4633594/JTreeFocusTest.java 8173125 macosx-all +javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-all +javax/swing/JFileChooser/4524490/bug4524490.java 8042380 generic-all +javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8198003 generic-all +javax/swing/JPopupMenu/6580930/bug6580930.java 7124313 macosx-all +javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all +javax/swing/JTabbedPane/8007563/Test8007563.java 8051591 generic-all +javax/swing/JTabbedPane/4624207/bug4624207.java 8064922 macosx-all +javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all +javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java 8194048 windows-all +javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java 8213562 linux-all +javax/swing/JFileChooser/6798062/bug6798062.java 8146446 windows-all +javax/swing/JComboBox/8182031/ComboPopupTest.java 8196465 linux-all,macosx-all +javax/swing/JFileChooser/6738668/bug6738668.java 8194946 generic-all +javax/swing/JInternalFrame/Test6325652.java 8224977 macosx-all +javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all +javax/swing/PopupFactory/6276087/NonOpaquePopupMenuTest.java 8065099,8208565 macosx-all,linux-all +javax/swing/UIDefaults/6302464/bug6302464.java 8199079 macosx-all +javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all +javax/swing/Popup/TaskbarPositionTest.java 8065097 macosx-all,linux-all +javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all +javax/swing/JRootPane/4670486/bug4670486.java 8042381 macosx-all +javax/swing/JPopupMenu/4634626/bug4634626.java 8017175 macosx-all + +sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all +sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all + +############################################################################ + +# jdk_text + +############################################################################ + +# jdk_time + + +############################################################################ + +# core_tools + +tools/jlink/JLinkReproducibleTest.java 8217166 windows-all,linux-aarch64 +tools/jlink/JLinkReproducible3Test.java 8253688 linux-aarch64 +tools/jlink/plugins/CompressorPluginTest.java 8247407 generic-all + +############################################################################ + +# jdk_jdi + +com/sun/jdi/RepStep.java 8043571 generic-all + +com/sun/jdi/NashornPopFrameTest.java 8225620 generic-all + +com/sun/jdi/InvokeHangTest.java 8218463 linux-all + +com/sun/jdi/AfterThreadDeathTest.java 8232839 linux-x64 + +############################################################################ + +# jdk_time + +############################################################################ + +# jdk_util + +############################################################################ + +# jdk_instrument + +############################################################################ + +# svc_tools + +sun/tools/jhsdb/BasicLauncherTest.java 8211767 linux-ppc64,linux-ppc64le + +sun/tools/jstatd/TestJstatdDefaults.java 8081569,8226420 windows-all +sun/tools/jstatd/TestJstatdRmiPort.java 8226420,8251259 windows-all +sun/tools/jstatd/TestJstatdServer.java 8081569,8226420 windows-all + + +############################################################################ + +# jdk_other + +javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic-all + +javax/script/Test7.java 8239361 generic-all + +############################################################################ + +# jdk_jfr + +jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all +jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all +jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all +jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 +jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 + +############################################################################ + +# jdk_internal + +############################################################################ + +# jdk_jpackage + +tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java#id0 8248418 generic-all + +############################################################################ + +# Client manual tests + +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_1.java 7131438,8022539 generic-all +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,8022539 generic-all +java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all +java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all +javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all +javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all +java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all +java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.html 8080185 macosx-all,linux-all +javax/swing/JTabbedPane/4666224/bug4666224.html 8144124 macosx-all +java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java 8162380 generic-all +java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java 8163086 macosx-all +java/awt/image/multiresolution/MultiResolutionIcon/IconTest.java 8250804 macosx-all,linux-all +java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all +java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all +java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.java 8185429 macosx-all +java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html 8203867 macosx-all +java/awt/Frame/FrameStateTest/FrameStateTest.html 8203920 macosx-all,linux-all +javax/swing/SwingUtilities/TestTextPosInPrint.java 8227025 windows-all +java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all +java/awt/font/TextLayout/TestJustification.html 8250791 macosx-all +javax/swing/JTabbedPane/4209065/bug4209065.java 8251177 macosx-all +java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all +java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all +java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html 7187728 macosx-all,linux-all +java/awt/print/PageFormat/Orient.java 8016055 macosx-all +java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all +java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter.java 8254841 macosx-all +java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java 8256289 windows-x64 +java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all + + +############################################################################ + +# no printer found +java/awt/print/PrinterJob/ExceptionTest.java generic-all +java/awt/print/PrinterJob/ImagePrinting/NullClipARGB.java generic-all +java/awt/print/PrinterJob/PrintCrashTest.java generic-all +java/awt/print/PrinterJob/PrtException.java generic-all +javax/print/attribute/ChromaticityValues.java generic-all +javax/print/CheckDupFlavor.java generic-all +javax/print/PrintSE/PrintSE.sh generic-all +javax/print/PrintSEUmlauts/PrintSEUmlauts.java 8135174 generic-all +javax/print/PrintServiceLookup/CountPrintServices.java generic-all +javax/print/attribute/AttributeTest.java generic-all +javax/print/attribute/GetCopiesSupported.java generic-all +javax/print/attribute/SidesPageRangesTest.java generic-all +javax/print/attribute/SupportedPrintableAreas.java generic-all \ No newline at end of file From d7e8f81fa373ff197ba3fc2bff5cd7d09c0367e0 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 20 Jan 2021 10:40:10 +0700 Subject: [PATCH 003/976] JBR-3040 press the button END at the beggining in order to avoid text selection (cherry picked from commit 1c2bf33db2af39e37c67bc2679887a53d211003b) --- .../awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/jdk/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java b/test/jdk/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java index 421d8fe2faf0..9e2926f4249e 100644 --- a/test/jdk/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java +++ b/test/jdk/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java @@ -94,6 +94,9 @@ public void keyPressed(KeyEvent ke) { } public static void test() { + r.keyPress(KeyEvent.VK_END); + r.keyRelease(KeyEvent.VK_END); + r.keyPress(KeyEvent.VK_SHIFT); r.keyPress(KeyEvent.VK_META); From f9609ae8743a8a62cead3888c7b774a3a9ce455b Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 22 Jan 2021 12:58:32 +0700 Subject: [PATCH 004/976] JBR-3045 add pressing ESC to close the dialog after test completion (cherry picked from commit 44d8b28b0bc49c24d7a20a098028218f034ab026) --- .../java/awt/Desktop/8064934/bug8064934.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/jdk/java/awt/Desktop/8064934/bug8064934.java b/test/jdk/java/awt/Desktop/8064934/bug8064934.java index f3a6b4658ad3..c085e23ee64c 100644 --- a/test/jdk/java/awt/Desktop/8064934/bug8064934.java +++ b/test/jdk/java/awt/Desktop/8064934/bug8064934.java @@ -34,6 +34,7 @@ */ import jdk.test.lib.Platform; import java.awt.*; +import java.awt.event.KeyEvent; import java.io.File; import java.io.IOException; import java.security.AccessController; @@ -43,6 +44,8 @@ public class bug8064934 { private static final String NO_ASSOCIATION_ERROR_MESSAGE = "Error message: No application is associated with" + " the specified file for this operation."; + private static int SLEEP_TIME = 1000; + public static void main(String[] args) { // This test is intended only for Windows if (!AccessController.doPrivileged((PrivilegedAction) Platform::isWindows)) { @@ -70,6 +73,12 @@ public static void main(String[] args) { throw new RuntimeException("Can not create temp file"); } desktop.open(file); + try { + pressESC(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } catch (IOException ioe) { String errorMessage = ioe.getMessage().trim(); if (errorMessage != null && !errorMessage.endsWith(NO_ASSOCIATION_ERROR_MESSAGE)) { @@ -85,4 +94,12 @@ public static void main(String[] args) { System.out.println("Test PASSED!"); } + + private static void pressESC() throws Exception { + Thread.sleep(SLEEP_TIME); + + Robot robot = new Robot(); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + } } From d62a6a22e29153fe82250fdd1eee844eaface470 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 10 Feb 2021 05:30:10 +0700 Subject: [PATCH 005/976] Update docker script to create jdk15 build env --- jb/project/docker/Dockerfile | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 jb/project/docker/Dockerfile diff --git a/jb/project/docker/Dockerfile b/jb/project/docker/Dockerfile new file mode 100644 index 000000000000..f14c47fb5321 --- /dev/null +++ b/jb/project/docker/Dockerfile @@ -0,0 +1,13 @@ +# jetbrains/runtime:jbr15env +FROM centos:7 +RUN yum -y install centos-release-scl +RUN yum -y install devtoolset-8 +RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool gcc gcc-c++ libstdc++-devel alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel git +# Install Java 15 +RUN wget https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz \ +-O - | tar xz -C / +RUN mv /zulu15.27.17-ca-jdk15.0.0-linux_x64 /jdk15.0.0 +ENV PATH /opt/rh/devtoolset-8/root/usr/bin:$PATH +RUN mkdir .git +RUN git config user.email "builduser@jetbrains.com" +RUN git config user.name "builduser" From a19a95c6ae5e5ddace3755f035faaf54a0b03177 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 6 Mar 2019 09:37:47 +0700 Subject: [PATCH 006/976] JBR-1199 add JBR modules list for jlink --- modules.list | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 modules.list diff --git a/modules.list b/modules.list new file mode 100644 index 000000000000..d775e8fce2d4 --- /dev/null +++ b/modules.list @@ -0,0 +1,61 @@ +java.base, +java.compiler, +java.datatransfer, +java.desktop, +java.instrument, +java.logging, +java.management, +java.management.rmi, +java.naming, +java.net.http, +java.prefs, +java.rmi, +java.scripting, +java.se, +java.security.jgss, +java.security.sasl, +java.smartcardio, +java.sql, +java.sql.rowset, +java.transaction.xa, +java.xml, +java.xml.crypto, +javafx.base, +javafx.controls, +javafx.fxml, +javafx.graphics, +javafx.media, +javafx.swing, +javafx.web, +jdk.accessibility, +jdk.aot, +jdk.charsets, +jdk.crypto.cryptoki, +jdk.crypto.ec, +jdk.dynalink, +jdk.httpserver, +jdk.internal.ed, +jdk.internal.le, +jdk.internal.vm.ci, +jdk.internal.vm.compiler, +jdk.internal.vm.compiler.management, +jdk.jdi, +jdk.jdwp.agent, +jdk.jfr, +jdk.jsobject, +jdk.localedata, +jdk.management, +jdk.management.agent, +jdk.management.jfr, +jdk.naming.dns, +jdk.naming.rmi, +jdk.net, +jdk.pack, +jdk.scripting.nashorn, +jdk.scripting.nashorn.shell, +jdk.sctp, +jdk.security.auth, +jdk.security.jgss, +jdk.unsupported, +jdk.xml.dom, +jdk.zipfs From 0a8521ea1282c1b2f40f279196b06f97035cd51d Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 19 Mar 2019 11:18:23 +0700 Subject: [PATCH 007/976] JBR-1286 add jdk.compiler into JBR --- modules.list | 1 + 1 file changed, 1 insertion(+) diff --git a/modules.list b/modules.list index d775e8fce2d4..687f48e31e15 100644 --- a/modules.list +++ b/modules.list @@ -30,6 +30,7 @@ javafx.web, jdk.accessibility, jdk.aot, jdk.charsets, +jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.dynalink, From e641cd7e41d2caaef55002a5a8e0a09d22f1512b Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 13 Dec 2019 10:17:18 +0700 Subject: [PATCH 008/976] JBR-2014 add jdk.hotspot.agent module to jbr --- modules.list | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules.list b/modules.list index 687f48e31e15..7a962073e5a9 100644 --- a/modules.list +++ b/modules.list @@ -59,4 +59,5 @@ jdk.security.auth, jdk.security.jgss, jdk.unsupported, jdk.xml.dom, -jdk.zipfs +jdk.zipfs, +jdk.hotspot.agent From fe08bf021efd78f300700db3417fa4ecf721c69a Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 13 Dec 2019 10:29:31 +0300 Subject: [PATCH 009/976] JBR-2016 add jcef module and export some sun.* packages to it --- modules.list | 3 ++- src/java.desktop/share/classes/module-info.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/modules.list b/modules.list index 7a962073e5a9..5dca7ca4dfd9 100644 --- a/modules.list +++ b/modules.list @@ -60,4 +60,5 @@ jdk.security.jgss, jdk.unsupported, jdk.xml.dom, jdk.zipfs, -jdk.hotspot.agent +jdk.hotspot.agent, +jcef diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java index 897647ee3689..ff39372d4428 100644 --- a/src/java.desktop/share/classes/module-info.java +++ b/src/java.desktop/share/classes/module-info.java @@ -116,7 +116,11 @@ // see make/GensrcModuleInfo.gmk exports sun.awt to jdk.accessibility, - jdk.unsupported.desktop; + jdk.unsupported.desktop, + jcef; + + exports sun.lwawt.macosx to jcef; + exports sun.lwawt to jcef; exports java.awt.dnd.peer to jdk.unsupported.desktop; exports sun.awt.dnd to jdk.unsupported.desktop; From 757e6c8c66f5e353585c071de7915294f6659162 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 20 Feb 2020 20:27:53 +0700 Subject: [PATCH 010/976] JBR-2162 move building scripts from TC to JBR repo --- jb/project/tools/linux/scripts/mkimages.sh | 93 +++++++++++++++++ jb/project/tools/mac/scripts/mkimages.sh | 101 +++++++++++++++++++ jb/project/tools/windows/scripts/mkimages.sh | 75 ++++++++++++++ jb/project/tools/windows/scripts/pack.sh | 46 +++++++++ 4 files changed, 315 insertions(+) create mode 100755 jb/project/tools/linux/scripts/mkimages.sh create mode 100755 jb/project/tools/mac/scripts/mkimages.sh create mode 100755 jb/project/tools/windows/scripts/mkimages.sh create mode 100755 jb/project/tools/windows/scripts/pack.sh diff --git a/jb/project/tools/linux/scripts/mkimages.sh b/jb/project/tools/linux/scripts/mkimages.sh new file mode 100755 index 000000000000..a7735e1d638a --- /dev/null +++ b/jb/project/tools/linux/scripts/mkimages.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +function create_jbr { + if [ -d "$BASE_DIR/$JBR_BUNDLE" ]; then + rm -rf $BASE_DIR/$JBR_BUNDLE + fi + + if [ ! -z "$1" ]; then + grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list + else + cat modules.list > modules_tmp.list + fi + + echo Running jlink.... + $JSDK/bin/jlink \ + --module-path $JSDK/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE + + cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? + grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release + + echo Creating $JBR.tar.gz ... + tar -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $? + gzip $JBR.tar || exit $? +} + +JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION +JBR_BASE_NAME=jbr-$JBSDK_VERSION +JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION + +sh configure \ + --disable-warnings-as-errors \ + --with-debug-level=release \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-pre= \ + --with-version-opt=b$build_number \ + --with-import-modules=./modular-sdk \ + --enable-cds=yes || exit $? + +make clean CONF=linux-x86_64-normal-server-release || exit $? +make images CONF=linux-x86_64-normal-server-release || exit $? + +JSDK=build/linux-x86_64-normal-server-release/images/jdk +JBSDK=$JBRSDK_BASE_NAME-linux-x64-b$build_number + +echo Fixing permissions +chmod -R a+r $JSDK + +BASE_DIR=build/linux-x86_64-normal-server-release/images +JBRSDK_BUNDLE=jbrsdk + +rm -rf $BASE_DIR/$JBRSDK_BUNDLE +cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? + +echo Creating $JBSDK.tar.gz ... +tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR $JBRSDK_BUNDLE || exit $? +gzip $JBSDK.tar || exit $? + +JBR=$JBR_BASE_NAME-linux-x64-b$build_number +JBR_BUNDLE=jbr +create_jbr + +JBR=$JBRLW_BASE_NAME-linux-x64-b$build_number +JBR_BUNDLE=jbrlw +create_jbr "lw" + +make test-image || exit $? + +JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number + +echo Creating $JBSDK_TEST.tar.gz ... +tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? +gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh new file mode 100755 index 000000000000..77df6e30cc1e --- /dev/null +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +function create_jbr { + mkdir -p $JRE_CONTENTS + + if [ -d "$JRE_HOME" ]; then + rm -rf $JRE_HOME + fi + + if [ ! -z "$1" ]; then + grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list + else + cat modules.list > modules_tmp.list + fi + + $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ + --module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $JRE_HOME || exit $? + grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release + cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS + cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS + cp -a jcef_mac/Frameworks $JRE_HOME + + echo Creating $JBR.tar.gz ... + COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $? +} + +JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION +JBR_BASE_NAME=jbr-$JBSDK_VERSION +JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION + +sh configure \ + --disable-warnings-as-errors \ + --with-debug-level=release \ + --with-version-pre= \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b$build_number \ + --with-import-modules=./modular-sdk \ + --with-boot-jdk=`/usr/libexec/java_home -v 11` \ + --enable-cds=yes || exit $? + +make images CONF=macosx-x86_64-normal-server-release || exit $? + +JSDK=build/macosx-x86_64-normal-server-release/images/jdk-bundle +JBSDK=$JBRSDK_BASE_NAME-osx-x64-b$build_number + +BASE_DIR=jre +JBRSDK_BUNDLE=jbrsdk + +rm -rf $BASE_DIR +mkdir $BASE_DIR || exit $? +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +cp -a build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-$JBSDK_VERSION_WITH_DOTS.jdk \ + $BASE_DIR/$JBRSDK_BUNDLE || exit $? + +echo Creating $JBSDK.tar.gz ... +cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/ + +COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ + --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ + --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ + $JBRSDK_BUNDLE || exit $? + +JBR=$JBR_BASE_NAME-osx-x64-b$build_number +JBR_BUNDLE=jbr +JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents +JRE_HOME=$JRE_CONTENTS/Home +create_jbr + +JBR=$JBRLW_BASE_NAME-osx-x64-b$build_number +JBR_BUNDLE=jbrlw +JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents +JRE_HOME=$JRE_CONTENTS/Home +create_jbr "lw" + +make test-image || exit $? + +JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number + +echo Creating $JBSDK_TEST.tar.gz ... +COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-normal-server-release/images \ + --exclude='test/jdk/demos' test || exit $? diff --git a/jb/project/tools/windows/scripts/mkimages.sh b/jb/project/tools/windows/scripts/mkimages.sh new file mode 100755 index 000000000000..6e56a8870b94 --- /dev/null +++ b/jb/project/tools/windows/scripts/mkimages.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +function create_jbr { + rm -rf $BASE_DIR/$JBR_BUNDLE + + if [ ! -z "$1" ]; then + grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list + else + cat modules.list > modules_tmp.list + fi + + $JSDK/bin/jlink \ + --module-path $JSDK/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE || exit $? + cp -R jcef_win_x64/* $BASE_DIR/$JBR_BUNDLE/bin + echo Modifying release info ... + grep -v \"^JAVA_VERSION\" $JSDK/release | grep -v \"^MODULES\" >> $BASE_DIR/$JBR_BUNDLE/release +} + +JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION +JBR_BASE_NAME=jbr-$JBSDK_VERSION +JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION +WORK_DIR=$(pwd) + +PATH="/usr/local/bin:/usr/bin:$PATH" +./configure \ + --disable-warnings-as-errors \ + --disable-debug-symbols \ + --with-target-bits=64 \ + --with-version-pre= \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b$build_number \ + --with-import-modules=$WORK_DIR/modular-sdk \ + --with-toolchain-version=2015 \ + --with-boot-jdk=$BOOT_JDK \ + --disable-ccache \ + --enable-cds=yes || exit 1 +make clean CONF=windows-x86_64-normal-server-release || exit 1 +make images CONF=windows-x86_64-normal-server-release || exit 1 +make -d test-image || exit 1 + +JSDK=build/windows-x86_64-normal-server-release/images/jdk +JBR=$JBR_BASE_NAME-windows-x64-b$build_number +JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number + +BASE_DIR=build/windows-x86_64-normal-server-release/images +JBRSDK_BUNDLE=jbrsdk + +rm -rf $BASE_DIR/$JBRSDK_BUNDLE && rsync -a --exclude demo --exclude sample $JSDK/ $JBRSDK_BUNDLE || exit 1 +cp -R jcef_win_x64/* $JBRSDK_BUNDLE/bin + +JBR_BUNDLE=jbr +create_jbr + +JBR_BUNDLE=jbrlw +create_jbr "lw" diff --git a/jb/project/tools/windows/scripts/pack.sh b/jb/project/tools/windows/scripts/pack.sh new file mode 100755 index 000000000000..18c4f4515b33 --- /dev/null +++ b/jb/project/tools/windows/scripts/pack.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION +JBR_BASE_NAME=jbr-$JBSDK_VERSION +JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION + +JSDK=build/windows-x86_64-normal-server-release/images/jdk +JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number + +JBRSDK_BUNDLE=jbrsdk +BASE_DIR=build/windows-x86_64-normal-server-release/images +echo Creating $JBSDK.tar.gz ... +/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 + +JBR_BUNDLE=jbr +JBR=$JBR_BASE_NAME-windows-x64-b$build_number +echo Creating $JBR.tar.gz ... +/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $JBR_BUNDLE || exit 1 + +JBR_BUNDLE=jbrlw +JBR=$JBRLW_BASE_NAME-windows-x64-b$build_number +echo Creating $JBR.tar.gz ... +/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $JBR_BUNDLE || exit 1 + +JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number +echo Creating $JBRSDK_TEST.tar.gz ... +/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $BASE_DIR --exclude='test/jdk/demos' test || exit 1 \ No newline at end of file From e58ea99393cf98cf7e32f66e954527d2e669ab29 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 16 Oct 2019 14:32:49 +0700 Subject: [PATCH 011/976] JBR-1821 notarize JBR bundles as a standalone app --- jb/project/tools/mac/scripts/entitlements.xml | 16 ++ jb/project/tools/mac/scripts/notarize.sh | 120 +++++++++++++++ jb/project/tools/mac/scripts/sign.sh | 93 ++++++++++++ jb/project/tools/mac/scripts/signapp.sh | 139 ++++++++++++++++++ 4 files changed, 368 insertions(+) create mode 100644 jb/project/tools/mac/scripts/entitlements.xml create mode 100755 jb/project/tools/mac/scripts/notarize.sh create mode 100755 jb/project/tools/mac/scripts/sign.sh create mode 100755 jb/project/tools/mac/scripts/signapp.sh diff --git a/jb/project/tools/mac/scripts/entitlements.xml b/jb/project/tools/mac/scripts/entitlements.xml new file mode 100644 index 000000000000..9d4904529342 --- /dev/null +++ b/jb/project/tools/mac/scripts/entitlements.xml @@ -0,0 +1,16 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-library-validation + + com.apple.security.cs.disable-executable-page-protection + + + \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/notarize.sh b/jb/project/tools/mac/scripts/notarize.sh new file mode 100755 index 000000000000..fa95c1b165b2 --- /dev/null +++ b/jb/project/tools/mac/scripts/notarize.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +APP_DIRECTORY=$1 +APPL_USER=$2 +APPL_PASSWORD=$3 +APP_NAME=$4 +BUNDLE_ID=$5 +FAKE_ROOT="${6:-fake-root}" + +if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$APPL_USER" ]] || [[ -z "$APPL_PASSWORD" ]]; then + echo "Usage: $0 AppDirectory Username Password" + exit 1 +fi +if [[ ! -d "$APP_DIRECTORY" ]]; then + echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory" + exit 1 +fi + +function log() { + echo "$(date '+[%H:%M:%S]') $*" +} + +function publish-log() { + id=$1 + file=$2 + curl -T "$file" "$ARTIFACTORY_URL/$id" || true +} + +function altool-upload() { + # Since altool uses same file for upload token we have to trick it into using different folders for token file location + # Also it copies zip into TMPDIR so we override it too, to simplify cleanup + OLD_HOME="$HOME" + export HOME="$FAKE_ROOT/home" + export TMPDIR="$FAKE_ROOT/tmp" + mkdir -p "$HOME" + mkdir -p "$TMPDIR" + export _JAVA_OPTIONS="-Duser.home=$HOME -Djava.io.tmpdir=$TMPDIR" + # Reduce amount of downloads, cache transporter libraries + shared_itmstransporter="$OLD_HOME/shared-itmstransporter" + if [[ -f "$shared_itmstransporter" ]]; then + cp -r "$shared_itmstransporter" "$HOME/.itmstransporter" + fi + # For some reason altool prints everything to stderr, not stdout + set +e + xcrun altool --notarize-app \ + --username "$APPL_USER" --password "$APPL_PASSWORD" \ + --primary-bundle-id "$BUNDLE_ID" \ + --asc-provider JetBrainssro --file "$1" 2>&1 | tee "altool.init.out" + unset TMPDIR + export HOME="$OLD_HOME" + set -e +} + +#immediately exit script with an error if a command fails +set -euo pipefail + +file="$APP_NAME.zip" + +log "Zipping $file..." +rm -rf "$file" +ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY/Contents" "$file" + +log "Notarizing $file..." +rm -rf "altool.init.out" "altool.check.out" +altool-upload "$file" + +rm -rf "$file" + +notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')" + +if [ -z "$notarization_info" ]; then + log "Faile to read RequestUUID from altool.init.out" + exit 10 +fi + +PATH="$PATH:/usr/local/bin/" + +log "Notarization request sent, awaiting response" +spent=0 + +while true; do + # For some reason altool prints everything to stderr, not stdout + xcrun altool --username "$APPL_USER" --notarization-info "$notarization_info" --password "$APPL_PASSWORD" >"altool.check.out" 2>&1 || true + status="$(grep -oe 'Status: .*' "altool.check.out" | cut -c 9- || true)" + log "Current status: $status" + if [ "$status" = "invalid" ]; then + log "Notarization failed" + ec=1 + elif [ "$status" = "success" ]; then + log "Notarization succeeded" + ec=0 + else + if [ "$status" != "in progress" ]; then + log "Unknown notarization status, waiting more, altool output:" + cat "altool.check.out" + fi + if [[ $spent -gt 60 ]]; then + log "Waiting time out (apx 60 minutes)" + ec=2 + break + fi + sleep 60 + ((spent += 1)) + continue + fi + developer_log="developer_log.json" + log "Fetching $developer_log" + # TODO: Replace cut with trim or something better + url="$(grep -oe 'LogFileURL: .*' "altool.check.out" | cut -c 13-)" + wget "$url" -O "$developer_log" && cat "$developer_log" || true + if [ $ec != 0 ]; then + log "Publishing $developer_log" + publish-log "$notarization_info" "$developer_log" + fi + break +done +cat "altool.check.out" + +rm -rf "altool.init.out" "altool.check.out" +exit $ec diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh new file mode 100755 index 000000000000..eb2eb0493b8b --- /dev/null +++ b/jb/project/tools/mac/scripts/sign.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +APP_DIRECTORY=$1 +JB_CERT=$2 + +if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then + echo "Usage: $0 AppDirectory CertificateID" + exit 1 +fi +if [[ ! -d "$APP_DIRECTORY" ]]; then + echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory" + exit 1 +fi + +function log() { + echo "$(date '+[%H:%M:%S]') $*" +} + +#immediately exit script with an error if a command fails +set -euo pipefail + +# Cleanup files left from previous sign attempt (if any) +find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \; + +log "Signing libraries and executables..." +# -perm +111 searches for executables +for f in \ + "Contents/Home/bin" \ + "Contents/Home/lib"; do + if [ -d "$APP_DIRECTORY/$f" ]; then + find "$APP_DIRECTORY/$f" \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ + -exec codesign --timestamp \ + -v -s "$JB_CERT" --options=runtime \ + --entitlements entitlements.xml {} \; + fi +done + +log "Signing libraries in jars in $PWD" + +# todo: add set -euo pipefail; into the inner sh -c +# `-e` prevents `grep -q && printf` loginc +# with `-o pipefail` there's no input for 'while' loop +find "$APP_DIRECTORY" -name '*.jar' \ + -exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; | + while IFS= read -r -d $'\0' file; do + log "Processing libraries in $file" + + rm -rf jarfolder jar.jar + mkdir jarfolder + filename="${file##*/}" + log "Filename: $filename" + cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename") + + find jarfolder \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \ + -exec codesign --timestamp \ + -v -s "$JB_CERT" --options=runtime \ + --entitlements entitlements.xml {} \; + + (cd jarfolder; zip -q -r -o ../jar.jar .) + mv jar.jar "$file" + done + +rm -rf jarfolder jar.jar + +log "Signing other files..." +for f in \ + "Contents/MacOS"; do + if [ -d "$APP_DIRECTORY/$f" ]; then + find "$APP_DIRECTORY/$f" \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ + -exec codesign --timestamp \ + -v -s "$JB_CERT" --options=runtime \ + --entitlements entitlements.xml {} \; + fi +done + +#log "Signing executable..." +#codesign --timestamp \ +# -v -s "$JB_CERT" --options=runtime \ +# --force \ +# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea" + +log "Signing whole app..." +codesign --timestamp \ + -v -s "$JB_CERT" --options=runtime \ + --force \ + --entitlements entitlements.xml "$APP_DIRECTORY" + +log "Verifying java is not broken" +find "$APP_DIRECTORY" \ + -type f -name 'java' -perm +111 -exec {} -version \; diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh new file mode 100755 index 000000000000..9e2f9565f37d --- /dev/null +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +#immediately exit script with an error if a command fails +set -euo pipefail + +export COPY_EXTENDED_ATTRIBUTES_DISABLE=true +export COPYFILE_DISABLE=true + +INPUT_FILE=$1 +EXPLODED=$2.exploded +BACKUP_JMODS=$2.backup +USERNAME=$3 +PASSWORD=$4 +CODESIGN_STRING=$5 +NOTARIZE=$6 +BUNDLE_ID=$7 + +cd "$(dirname "$0")" + +function log() { + echo "$(date '+[%H:%M:%S]') $*" +} + +log "Deleting $EXPLODED ..." +if test -d "$EXPLODED"; then + find "$EXPLODED" -mindepth 1 -maxdepth 1 -exec chmod -R u+wx '{}' \; +fi +rm -rf "$EXPLODED" +mkdir "$EXPLODED" +rm -rf "$BACKUP_JMODS" +mkdir "$BACKUP_JMODS" + +log "Unzipping $INPUT_FILE to $EXPLODED ..." +tar -xzvf "$INPUT_FILE" --directory $EXPLODED +rm "$INPUT_FILE" +BUILD_NAME="$(ls "$EXPLODED")" +if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then + mv $EXPLODED/$BUILD_NAME/Contents/Home/jmods $BACKUP_JMODS +fi +if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then + mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS +fi + +#log "$INPUT_FILE unzipped and removed" +log "$INPUT_FILE extracted and removed" + +APPLICATION_PATH="$EXPLODED/$BUILD_NAME" + +find "$APPLICATION_PATH/Contents/Home/bin" \ + -maxdepth 1 -type f -name '*.jnilib' -print0 | + while IFS= read -r -d $'\0' file; do + if [ -f "$file" ]; then + log "Linking $file" + b="$(basename "$file" .jnilib)" + ln -sf "$b.jnilib" "$(dirname "$file")/$b.dylib" + fi + done + +find "$APPLICATION_PATH/Contents/" \ + -maxdepth 1 -type f -name '*.txt' -print0 | + while IFS= read -r -d $'\0' file; do + if [ -f "$file" ]; then + log "Moving $file" + mv "$file" "$APPLICATION_PATH/Contents/Resources" + fi + done + +non_plist=$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist' | wc -l) +if [[ $non_plist -gt 0 ]]; then + log "Only Info.plist file is allowed in Contents directory but found $non_plist file(s):" + log "$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist')" + exit 1 +fi + +log "Unlocking keychain..." +# Make sure *.p12 is imported into local KeyChain +security unlock-keychain -p "$PASSWORD" "/Users/$USERNAME/Library/Keychains/login.keychain" + +attempt=1 +limit=3 +set +e +while [[ $attempt -le $limit ]]; do + log "Signing (attempt $attempt) $APPLICATION_PATH ..." + ./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING" + ec=$? + if [[ $ec -ne 0 ]]; then + ((attempt += 1)) + if [ $attempt -eq $limit ]; then + set -e + fi + log "Signing failed, wait for 30 sec and try to sign again" + sleep 30 + else + log "Signing done" + codesign -v "$APPLICATION_PATH" -vvvvv + log "Check sign done" + ((attempt += limit)) + fi +done + +set -e + +if [ "$NOTARIZE" = "yes" ]; then + log "Notarizing..." + # shellcheck disable=SC1090 + source "$HOME/.notarize_token" + APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }') + # Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root + # Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR + FAKE_ROOT="$(pwd)/fake-root" + mkdir -p "$FAKE_ROOT" + echo "Notarization will use fake root: $FAKE_ROOT" + ./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT" + rm -rf "$FAKE_ROOT" + + set +e + log "Stapling..." + xcrun stapler staple "$APPLICATION_PATH" +else + log "Notarization disabled" + log "Stapling disabled" +fi + +log "Zipping $BUILD_NAME to $INPUT_FILE ..." +( + #cd "$EXPLODED" + #ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE" + if test ! -z $(ls $BACKUP_JMODS/libjli.dylib); then + mv $BACKUP_JMODS/libjli.dylib $EXPLODED/$BUILD_NAME/Contents/MacOS + fi + if test -d $BACKUP_JMODS/jmods; then + mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home + fi + + COPYFILE_DISABLE=1 tar -pczf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME + log "Finished zipping" +) +rm -rf "$EXPLODED" +log "Done" From 844f1729e240ad79716157d6efa455f00688c2ca Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 22 Jan 2020 12:00:49 +0700 Subject: [PATCH 012/976] JBR-2084 modify scripts to sign Contents/MacOS/libjli.dylib as a a normal file --- jb/project/tools/mac/scripts/signapp.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index 9e2f9565f37d..68c127471b49 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -39,6 +39,8 @@ if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then fi if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS +if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then + mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS fi #log "$INPUT_FILE unzipped and removed" @@ -125,9 +127,6 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..." ( #cd "$EXPLODED" #ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE" - if test ! -z $(ls $BACKUP_JMODS/libjli.dylib); then - mv $BACKUP_JMODS/libjli.dylib $EXPLODED/$BUILD_NAME/Contents/MacOS - fi if test -d $BACKUP_JMODS/jmods; then mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home fi From 4dc8cd838b7a8a7837873fcab263dac2dc3e3126 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 20 Feb 2020 20:30:39 +0700 Subject: [PATCH 013/976] JBR-2148 modify signapp&build scripts to match to the new layout --- jb/project/tools/mac/scripts/mkimages.sh | 6 ++++-- jb/project/tools/mac/scripts/sign.sh | 4 +++- jb/project/tools/mac/scripts/signapp.sh | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 77df6e30cc1e..c9e7be805ff6 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -38,7 +38,8 @@ function create_jbr { grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS - cp -a jcef_mac/Frameworks $JRE_HOME + cp -a jcef_mac/Frameworks $JRE_CONTENTS || exit $? + cp -a jcef_mac/Helpers $JRE_CONTENTS || exit $? echo Creating $JBR.tar.gz ... COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $? @@ -73,7 +74,8 @@ cp -a build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-$JBSDK_VER $BASE_DIR/$JBRSDK_BUNDLE || exit $? echo Creating $JBSDK.tar.gz ... -cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/ +cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ +cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index eb2eb0493b8b..e4d6e5526ba9 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -26,7 +26,9 @@ log "Signing libraries and executables..." # -perm +111 searches for executables for f in \ "Contents/Home/bin" \ - "Contents/Home/lib"; do + "Contents/Home/lib" \ + "Contents/Frameworks" \ + "Contents/Helpers"; do if [ -d "$APP_DIRECTORY/$f" ]; then find "$APP_DIRECTORY/$f" \ -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index 68c127471b49..04ea4ef93807 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -39,11 +39,11 @@ if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then fi if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS +fi if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS fi -#log "$INPUT_FILE unzipped and removed" log "$INPUT_FILE extracted and removed" APPLICATION_PATH="$EXPLODED/$BUILD_NAME" From 550fce4825a1335f8d05eaf77fb5f4b7eb9faa5f Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 3 Mar 2020 18:55:28 +0700 Subject: [PATCH 014/976] JBR-2181 create two separate JBR bundles with JFX and JFX+JCEF --- jb/project/tools/exclude_jcef_module.patch | 33 +++++ jb/project/tools/linux/scripts/mkbundles.sh | 8 ++ jb/project/tools/linux/scripts/mkimages.sh | 77 +++++++---- jb/project/tools/mac/scripts/mkbundles.sh | 8 ++ jb/project/tools/mac/scripts/mkimages.sh | 121 +++++++++++------- jb/project/tools/windows/scripts/mkbundles.sh | 8 ++ jb/project/tools/windows/scripts/mkimages.sh | 71 ++++++---- jb/project/tools/windows/scripts/pack.sh | 65 +++++++--- 8 files changed, 271 insertions(+), 120 deletions(-) create mode 100644 jb/project/tools/exclude_jcef_module.patch create mode 100755 jb/project/tools/linux/scripts/mkbundles.sh create mode 100755 jb/project/tools/mac/scripts/mkbundles.sh create mode 100755 jb/project/tools/windows/scripts/mkbundles.sh diff --git a/jb/project/tools/exclude_jcef_module.patch b/jb/project/tools/exclude_jcef_module.patch new file mode 100644 index 000000000000..9c60d4cacb9e --- /dev/null +++ b/jb/project/tools/exclude_jcef_module.patch @@ -0,0 +1,33 @@ +Index: src/java.desktop/share/classes/module-info.java +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +--- src/java.desktop/share/classes/module-info.java (revision 08d1926f8b7c74da0e1144e0ce5912e7589c4688) ++++ src/java.desktop/share/classes/module-info.java (date 1583207610780) +@@ -109,10 +109,7 @@ + // see make/GensrcModuleInfo.gmk + exports sun.awt to + jdk.accessibility, +- jdk.unsupported.desktop, +- jcef; +- +- exports java.awt.peer to jcef; ++ jdk.unsupported.desktop; + + exports java.awt.dnd.peer to jdk.unsupported.desktop; + exports sun.awt.dnd to jdk.unsupported.desktop; +Index: modules.list +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +--- modules.list (revision 08d1926f8b7c74da0e1144e0ce5912e7589c4688) ++++ modules.list (date 1583207610776) +@@ -60,5 +60,4 @@ + jdk.unsupported, + jdk.xml.dom, + jdk.zipfs, +-jdk.hotspot.agent, +-jcef ++jdk.hotspot.agent diff --git a/jb/project/tools/linux/scripts/mkbundles.sh b/jb/project/tools/linux/scripts/mkbundles.sh new file mode 100755 index 000000000000..003a44ac66e2 --- /dev/null +++ b/jb/project/tools/linux/scripts/mkbundles.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +bash -x jb/project/tools/linux/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" +bash -x jb/project/tools/linux/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" diff --git a/jb/project/tools/linux/scripts/mkimages.sh b/jb/project/tools/linux/scripts/mkimages.sh index a7735e1d638a..bbf257bf8f6e 100755 --- a/jb/project/tools/linux/scripts/mkimages.sh +++ b/jb/project/tools/linux/scripts/mkimages.sh @@ -4,10 +4,12 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # # $ ./java --version # openjdk 11.0.6 2020-01-14 @@ -18,34 +20,54 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +bundle_type=$4 function create_jbr { - if [ -d "$BASE_DIR/$JBR_BUNDLE" ]; then - rm -rf $BASE_DIR/$JBR_BUNDLE - fi - if [ ! -z "$1" ]; then + case "$1" in + "${bundle_type}_lw") + JBR_BASE_NAME=jbr_${bundle_type}_lw-$JBSDK_VERSION grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - else + ;; + "jfx") + JBR_BASE_NAME=jbr_${bundle_type}-$JBSDK_VERSION cat modules.list > modules_tmp.list - fi + ;; + "jcef") + JBR_BASE_NAME=jbr-$JBSDK_VERSION + cat modules.list > modules_tmp.list + ;; + *) + echo "***ERR*** bundle was not specified" && exit $? + ;; + esac + rm -rf $BASE_DIR/$JBR_BUNDLE + + JBR=$JBR_BASE_NAME-linux-x64-b$build_number echo Running jlink.... $JSDK/bin/jlink \ --module-path $JSDK/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE - cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? + if [ "$bundle_type" == "jcef" ]; then + cp -R $BASE_DIR/$JBR_BUNDLE $BASE_DIR/jbr + cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? + fi grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release echo Creating $JBR.tar.gz ... - tar -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $? + rm -rf ${BASE_DIR}/jbr + cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr + tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $? gzip $JBR.tar || exit $? } JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -JBR_BASE_NAME=jbr-$JBSDK_VERSION -JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION + +if [ "$bundle_type" == "jfx" ]; then + git apply -p0 < jb/project/tools/exclude_jcef_module.patch +fi sh configure \ --disable-warnings-as-errors \ @@ -70,24 +92,27 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? -cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? -echo Creating $JBSDK.tar.gz ... -tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR $JBRSDK_BUNDLE || exit $? -gzip $JBSDK.tar || exit $? +if [ "$bundle_type" == "jcef" ]; then + cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? + + echo Creating $JBSDK.tar.gz ... + tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR $JBRSDK_BUNDLE || exit $? + gzip $JBSDK.tar || exit $? +fi -JBR=$JBR_BASE_NAME-linux-x64-b$build_number -JBR_BUNDLE=jbr -create_jbr +JBR_BUNDLE=jbr_${bundle_type} +create_jbr ${bundle_type} -JBR=$JBRLW_BASE_NAME-linux-x64-b$build_number -JBR_BUNDLE=jbrlw -create_jbr "lw" +JBR_BUNDLE=jbr_${bundle_type}_lw +create_jbr ${bundle_type}_lw -make test-image || exit $? +if [ "$bundle_type" == "jcef" ]; then + make test-image || exit $? -JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number + JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number -echo Creating $JBSDK_TEST.tar.gz ... -tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file + echo Creating $JBSDK_TEST.tar.gz ... + tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? + gzip $JBRSDK_TEST.tar || exit $? +fi \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkbundles.sh b/jb/project/tools/mac/scripts/mkbundles.sh new file mode 100755 index 000000000000..ba50d4213c4b --- /dev/null +++ b/jb/project/tools/mac/scripts/mkbundles.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +bash -x jb/project/tools/mac/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" +bash -x jb/project/tools/mac/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index c9e7be805ff6..da4dd7d948f7 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -4,10 +4,12 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # # $ ./java --version # openjdk 11.0.6 2020-01-14 @@ -18,43 +20,70 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +bundle_type=$4 function create_jbr { - mkdir -p $JRE_CONTENTS - if [ -d "$JRE_HOME" ]; then - rm -rf $JRE_HOME - fi - - if [ ! -z "$1" ]; then + case "$1" in + "${bundle_type}_lw") + JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - else + ;; + "jfx") + JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} + cat modules.list > modules_tmp.list + ;; + "jcef") + JBR_BASE_NAME=jbr-${JBSDK_VERSION} cat modules.list > modules_tmp.list + ;; + *) + echo "***ERR*** bundle was not specified" && exit $? + ;; + esac + rm -rf ${BASE_DIR}/${JBR_BUNDLE} + + JRE_CONTENTS=${BASE_DIR}/${JBR_BUNDLE}/Contents + JRE_HOME=${JRE_CONTENTS}/Home + if [ -d "${JRE_CONTENTS}" ]; then + rm -rf ${JRE_CONTENTS} + fi + mkdir -p ${JRE_CONTENTS} + + JBR=${JBR_BASE_NAME}-osx-x64-b${build_number} + + ${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ + --module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || exit $? + grep -v "^JAVA_VERSION" ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release | grep -v "^MODULES" >> ${JRE_HOME}/release + cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS} + cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS} + + if [ "${bundle_type}" == "jcef" ]; then + rm -rf ${JRE_CONTENTS}/Frameworks || exit $? + rm -rf ${JRE_CONTENTS}/Helpers || exit $? + cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? + cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $? fi - $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ - --module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $JRE_HOME || exit $? - grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release - cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS - cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS - cp -a jcef_mac/Frameworks $JRE_CONTENTS || exit $? - cp -a jcef_mac/Helpers $JRE_CONTENTS || exit $? - - echo Creating $JBR.tar.gz ... - COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $? + echo Creating ${JBR}.tar.gz ... + rm -rf ${BASE_DIR}/jbr + cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr + COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $? } -JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -JBR_BASE_NAME=jbr-$JBSDK_VERSION -JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} + +if [ "${bundle_type}" == "jfx" ]; then + git apply -p0 < jb/project/tools/exclude_jcef_module.patch +fi sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ --with-version-pre= \ - --with-version-build=$JDK_BUILD_NUMBER \ - --with-version-opt=b$build_number \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --with-boot-jdk=`/usr/libexec/java_home -v 11` \ --enable-cds=yes || exit $? @@ -62,7 +91,7 @@ sh configure \ make images CONF=macosx-x86_64-normal-server-release || exit $? JSDK=build/macosx-x86_64-normal-server-release/images/jdk-bundle -JBSDK=$JBRSDK_BASE_NAME-osx-x64-b$build_number +JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} BASE_DIR=jre JBRSDK_BUNDLE=jbrsdk @@ -73,31 +102,29 @@ JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') cp -a build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-$JBSDK_VERSION_WITH_DOTS.jdk \ $BASE_DIR/$JBRSDK_BUNDLE || exit $? -echo Creating $JBSDK.tar.gz ... -cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ -cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ +if [ "$bundle_type" == "jcef" ]; then + echo Creating $JBSDK.tar.gz ... + cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ + cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ -COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ - --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ - --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - $JBRSDK_BUNDLE || exit $? + COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ + --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ + --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ + $JBRSDK_BUNDLE || exit $? +fi -JBR=$JBR_BASE_NAME-osx-x64-b$build_number -JBR_BUNDLE=jbr -JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents -JRE_HOME=$JRE_CONTENTS/Home -create_jbr +JBR_BUNDLE=jbr_${bundle_type} +create_jbr $bundle_type -JBR=$JBRLW_BASE_NAME-osx-x64-b$build_number -JBR_BUNDLE=jbrlw -JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents -JRE_HOME=$JRE_CONTENTS/Home -create_jbr "lw" +JBR_BUNDLE=jbr_${bundle_type}_lw +create_jbr "${bundle_type}_lw" -make test-image || exit $? +if [ "$bundle_type" == "jcef" ]; then + make test-image || exit $? -JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number + JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number -echo Creating $JBSDK_TEST.tar.gz ... -COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-normal-server-release/images \ - --exclude='test/jdk/demos' test || exit $? + echo Creating $JBSDK_TEST.tar.gz ... + COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-normal-server-release/images \ + --exclude='test/jdk/demos' test || exit $? +fi \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkbundles.sh b/jb/project/tools/windows/scripts/mkbundles.sh new file mode 100755 index 000000000000..3c1176683b3e --- /dev/null +++ b/jb/project/tools/windows/scripts/mkbundles.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +bash -x jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? +bash -x jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages.sh b/jb/project/tools/windows/scripts/mkimages.sh index 6e56a8870b94..58f30c84317c 100755 --- a/jb/project/tools/windows/scripts/mkimages.sh +++ b/jb/project/tools/windows/scripts/mkimages.sh @@ -4,10 +4,12 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # # $ ./java --version # openjdk 11.0.6 2020-01-14 @@ -18,58 +20,71 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +bundle_type=$4 function create_jbr { - rm -rf $BASE_DIR/$JBR_BUNDLE - if [ ! -z "$1" ]; then + case "$1" in + "${bundle_type}_lw") grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - else + ;; + "jfx") cat modules.list > modules_tmp.list - fi + ;; + "jcef") + cat modules.list > modules_tmp.list + ;; + *) + echo "***ERR*** bundle was not specified" && exit $? + ;; + esac + rm -rf ${JBR_BUNDLE} - $JSDK/bin/jlink \ - --module-path $JSDK/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE || exit $? - cp -R jcef_win_x64/* $BASE_DIR/$JBR_BUNDLE/bin + ${JSDK}/bin/jlink \ + --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? + if [ "${bundle_type}" == "jcef" ]; then + cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin + fi echo Modifying release info ... - grep -v \"^JAVA_VERSION\" $JSDK/release | grep -v \"^MODULES\" >> $BASE_DIR/$JBR_BUNDLE/release + grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release } -JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -JBR_BASE_NAME=jbr-$JBSDK_VERSION -JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -PATH="/usr/local/bin:/usr/bin:$PATH" +if [ "${bundle_type}" == "jfx" ]; then + git apply -p0 < jb/project/tools/exclude_jcef_module.patch +fi + +PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ --disable-debug-symbols \ --with-target-bits=64 \ --with-version-pre= \ - --with-version-build=$JDK_BUILD_NUMBER \ - --with-version-opt=b$build_number \ - --with-import-modules=$WORK_DIR/modular-sdk \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ + --with-import-modules=${WORK_DIR}/modular-sdk \ --with-toolchain-version=2015 \ - --with-boot-jdk=$BOOT_JDK \ + --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ --enable-cds=yes || exit 1 make clean CONF=windows-x86_64-normal-server-release || exit 1 -make images CONF=windows-x86_64-normal-server-release || exit 1 -make -d test-image || exit 1 +make JOBS=7 LOG=info images CONF=windows-x86_64-normal-server-release || exit 1 +make JOBS=7 LOG=info test-image || exit 1 JSDK=build/windows-x86_64-normal-server-release/images/jdk -JBR=$JBR_BASE_NAME-windows-x64-b$build_number -JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number +JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} BASE_DIR=build/windows-x86_64-normal-server-release/images JBRSDK_BUNDLE=jbrsdk -rm -rf $BASE_DIR/$JBRSDK_BUNDLE && rsync -a --exclude demo --exclude sample $JSDK/ $JBRSDK_BUNDLE || exit 1 -cp -R jcef_win_x64/* $JBRSDK_BUNDLE/bin +rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 +cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin -JBR_BUNDLE=jbr -create_jbr +JBR_BUNDLE=jbr_${bundle_type} +create_jbr ${bundle_type} -JBR_BUNDLE=jbrlw -create_jbr "lw" +JBR_BUNDLE=jbr_${bundle_type}_lw +create_jbr ${bundle_type}_lw diff --git a/jb/project/tools/windows/scripts/pack.sh b/jb/project/tools/windows/scripts/pack.sh index 18c4f4515b33..3d2c5636541a 100755 --- a/jb/project/tools/windows/scripts/pack.sh +++ b/jb/project/tools/windows/scripts/pack.sh @@ -4,10 +4,12 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbrlw-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # # $ ./java --version # openjdk 11.0.6 2020-01-14 @@ -18,29 +20,54 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +bundle_type=$4 + +function pack_jbr { + + case "$1" in + "${bundle_type}_lw") + JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} + ;; + "jfx") + JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} + ;; + "jcef") + JBR_BASE_NAME=jbr-${JBSDK_VERSION} + ;; + *) + echo "***ERR*** bundle was not specified" && exit $? + ;; + esac + + JBR=$JBR_BASE_NAME-windows-x64-b$build_number + echo Creating $JBR.tar.gz ... + rm -rf ${BASE_DIR}/jbr + cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr + + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1 +} JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION JBR_BASE_NAME=jbr-$JBSDK_VERSION -JBRLW_BASE_NAME=jbrlw-$JBSDK_VERSION -JSDK=build/windows-x86_64-normal-server-release/images/jdk +IMAGES_DIR=build/windows-x86_64-normal-server-release/images +JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number +BASE_DIR=. -JBRSDK_BUNDLE=jbrsdk -BASE_DIR=build/windows-x86_64-normal-server-release/images -echo Creating $JBSDK.tar.gz ... -/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 - -JBR_BUNDLE=jbr -JBR=$JBR_BASE_NAME-windows-x64-b$build_number -echo Creating $JBR.tar.gz ... -/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $JBR_BUNDLE || exit 1 +if [ "$bundle_type" == "jcef" ]; then + JBRSDK_BUNDLE=jbrsdk + echo Creating $JBSDK.tar.gz ... + /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 +fi -JBR_BUNDLE=jbrlw -JBR=$JBRLW_BASE_NAME-windows-x64-b$build_number -echo Creating $JBR.tar.gz ... -/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $JBR_BUNDLE || exit 1 +JBR_BUNDLE=jbr_${bundle_type} +pack_jbr $bundle_type +JBR_BUNDLE=jbr_${bundle_type}_lw +pack_jbr ${bundle_type}_lw -JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $BASE_DIR --exclude='test/jdk/demos' test || exit 1 \ No newline at end of file +if [ "$bundle_type" == "jcef" ]; then + JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number + echo Creating $JBRSDK_TEST.tar.gz ... + /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 +fi \ No newline at end of file From ed2dba10f05f41687f2de93236f50f6d66d00d27 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 11 Mar 2020 16:53:48 +0700 Subject: [PATCH 015/976] JBR-1643 fix intermittent fialures of Windows builds at make/Init.gmk:304 combine images and test-image into one make invocation --- jb/project/tools/windows/scripts/mkbundles.sh | 6 +++--- jb/project/tools/windows/scripts/mkimages.sh | 5 ++--- jb/project/tools/windows/scripts/pack.sh | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkbundles.sh b/jb/project/tools/windows/scripts/mkbundles.sh index 3c1176683b3e..e4e37bb19c4c 100755 --- a/jb/project/tools/windows/scripts/mkbundles.sh +++ b/jb/project/tools/windows/scripts/mkbundles.sh @@ -1,8 +1,8 @@ -#!/bin/bash +#!/bin/bash -x JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 -bash -x jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -bash -x jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file +jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? +jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages.sh b/jb/project/tools/windows/scripts/mkimages.sh index 58f30c84317c..f2eede20639a 100755 --- a/jb/project/tools/windows/scripts/mkimages.sh +++ b/jb/project/tools/windows/scripts/mkimages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # The following parameters must be specified: # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 @@ -71,8 +71,7 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --disable-ccache \ --enable-cds=yes || exit 1 make clean CONF=windows-x86_64-normal-server-release || exit 1 -make JOBS=7 LOG=info images CONF=windows-x86_64-normal-server-release || exit 1 -make JOBS=7 LOG=info test-image || exit 1 +make JOBS=7 LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 JSDK=build/windows-x86_64-normal-server-release/images/jdk JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} diff --git a/jb/project/tools/windows/scripts/pack.sh b/jb/project/tools/windows/scripts/pack.sh index 3d2c5636541a..f4fa3ade69e6 100755 --- a/jb/project/tools/windows/scripts/pack.sh +++ b/jb/project/tools/windows/scripts/pack.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # The following parameters must be specified: # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 From 7ec591d7e10424bac7c5d1b3c4089c49582c2e4e Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 13 Mar 2020 15:44:47 +0700 Subject: [PATCH 016/976] JBR-2212 add scripts for linux_x86, linux_aarch64, linux_x64_fastdebug, osx_fastdebug, windows_x86 --- jb/project/tools/linux/scripts/mkbundles.sh | 8 -- .../tools/linux/scripts/mkbundles_x64.sh | 8 ++ .../tools/linux/scripts/mkimages_aarch64.sh | 77 +++++++++++++++++ .../scripts/{mkimages.sh => mkimages_x64.sh} | 2 +- .../tools/linux/scripts/mkimages_x64_fd.sh | 72 ++++++++++++++++ .../tools/linux/scripts/mkimages_x86.sh | 73 ++++++++++++++++ jb/project/tools/mac/scripts/mkbundles.sh | 8 +- jb/project/tools/mac/scripts/mkimages.sh | 5 +- jb/project/tools/mac/scripts/mkimages_fd.sh | 83 +++++++++++++++++++ jb/project/tools/windows/scripts/mkbundles.sh | 8 -- .../tools/windows/scripts/mkbundles_x64.sh | 8 ++ .../scripts/{mkimages.sh => mkimages_x64.sh} | 2 +- .../tools/windows/scripts/mkimages_x86.sh | 57 +++++++++++++ .../windows/scripts/{pack.sh => pack_x64.sh} | 0 jb/project/tools/windows/scripts/pack_x86.sh | 45 ++++++++++ 15 files changed, 431 insertions(+), 25 deletions(-) delete mode 100755 jb/project/tools/linux/scripts/mkbundles.sh create mode 100755 jb/project/tools/linux/scripts/mkbundles_x64.sh create mode 100755 jb/project/tools/linux/scripts/mkimages_aarch64.sh rename jb/project/tools/linux/scripts/{mkimages.sh => mkimages_x64.sh} (99%) create mode 100755 jb/project/tools/linux/scripts/mkimages_x64_fd.sh create mode 100755 jb/project/tools/linux/scripts/mkimages_x86.sh create mode 100755 jb/project/tools/mac/scripts/mkimages_fd.sh delete mode 100755 jb/project/tools/windows/scripts/mkbundles.sh create mode 100755 jb/project/tools/windows/scripts/mkbundles_x64.sh rename jb/project/tools/windows/scripts/{mkimages.sh => mkimages_x64.sh} (96%) create mode 100755 jb/project/tools/windows/scripts/mkimages_x86.sh rename jb/project/tools/windows/scripts/{pack.sh => pack_x64.sh} (100%) create mode 100755 jb/project/tools/windows/scripts/pack_x86.sh diff --git a/jb/project/tools/linux/scripts/mkbundles.sh b/jb/project/tools/linux/scripts/mkbundles.sh deleted file mode 100755 index 003a44ac66e2..000000000000 --- a/jb/project/tools/linux/scripts/mkbundles.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -bash -x jb/project/tools/linux/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" -bash -x jb/project/tools/linux/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" diff --git a/jb/project/tools/linux/scripts/mkbundles_x64.sh b/jb/project/tools/linux/scripts/mkbundles_x64.sh new file mode 100755 index 000000000000..5c3ab27ff740 --- /dev/null +++ b/jb/project/tools/linux/scripts/mkbundles_x64.sh @@ -0,0 +1,8 @@ +#!/bin/bash -x + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 +script_dir=jb/project/tools/linux/scripts +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh new file mode 100755 index 000000000000..b14761f84ba5 --- /dev/null +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -0,0 +1,77 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} + +sh configure \ + --disable-warnings-as-errors \ + --with-debug-level=release \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-pre= \ + --with-version-opt=b$build_number \ + --with-boot-jdk=amazon-corretto-11.0.5.10.1-linux-aarch64 \ + --with-import-modules=./modular-sdk \ + --enable-cds=yes || exit $? +make clean CONF=linux-aarch64-normal-server-release || exit $? +make images CONF=linux-aarch64-normal-server-release test-image || exit $? + +JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number} +BASE_DIR=build/linux-aarch64-normal-server-release/images +JSDK=${BASE_DIR}/jdk +JBRSDK_BUNDLE=jbrsdk + +echo Fixing permissions +chmod -R a+r $JSDK + +rm -rf $BASE_DIR/$JBRSDK_BUNDLE +cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? + +echo Creating $JBSDK.tar.gz ... +tar -pcf $JBSDK.tar \ + --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ + -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? +gzip $JBSDK.tar || exit $? + +JBR_BUNDLE=jbr +JBR_BASE_NAME=jbr-$JBSDK_VERSION +rm -rf $BASE_DIR/$JBR_BUNDLE + +JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number +grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64 +echo Running jlink.... +${JSDK}/bin/jlink \ + --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/,$//g) \ + --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? + +echo Modifying release info ... +grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release + +echo Creating $JBR.tar.gz ... +tar -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? +gzip $JBR.tar || exit $? + +JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number +echo Creating $JBRSDK_TEST.tar.gz ... +tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? +gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh similarity index 99% rename from jb/project/tools/linux/scripts/mkimages.sh rename to jb/project/tools/linux/scripts/mkimages_x64.sh index bbf257bf8f6e..322fed871fd6 100755 --- a/jb/project/tools/linux/scripts/mkimages.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # The following parameters must be specified: # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh new file mode 100755 index 000000000000..25ff62a2254b --- /dev/null +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -0,0 +1,72 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} + +sh configure \ + --disable-warnings-as-errors \ + --with-debug-level=fastdebug \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-pre= \ + --with-version-opt=b$build_number \ + --with-import-modules=./modular-sdk \ + --enable-cds=yes || exit $? +make clean CONF=linux-x86_64-normal-server-fastdebug || exit $? +make images CONF=linux-x86_64-normal-server-fastdebug || exit $? + +JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number} +BASE_DIR=build/linux-x86_64-normal-server-fastdebug/images +JSDK=${BASE_DIR}/jdk +JBRSDK_BUNDLE=jbrsdk + +echo Fixing permissions +chmod -R a+r $JSDK + +rm -rf $BASE_DIR/$JBRSDK_BUNDLE +cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? + +echo Creating $JBSDK.tar.gz ... +tar -pcf $JBSDK.tar \ + --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ + -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? +gzip $JBSDK.tar || exit $? + +JBR_BUNDLE=jbr +JBR_BASE_NAME=jbr-$JBSDK_VERSION +rm -rf $BASE_DIR/$JBR_BUNDLE + +JBR=$JBR_BASE_NAME-linux-x64-fastdebug-b$build_number +echo Running jlink.... +${JSDK}/bin/jlink \ + --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules.list | sed s/" "//g | sed s/,$//g) \ + --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? +cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? + +echo Modifying release info ... +grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release + +echo Creating $JBR.tar.gz ... +tar -czf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? +gzip $JBR.tar || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh new file mode 100755 index 000000000000..65986698dbd4 --- /dev/null +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -0,0 +1,73 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} + +linux32 bash configure \ + --disable-warnings-as-errors \ + --with-debug-level=release \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-pre= \ + --with-version-opt=b$build_number \ + --with-boot-jdk=/jbrsdk-11.0.5-b1 \ + --enable-cds=yes || exit $? +make clean CONF=linux-x86-normal-server-release || exit $? +make images CONF=linux-x86-normal-server-release test-image || exit $? + +JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number} +BASE_DIR=build/linux-x86-normal-server-release/images +JSDK=${BASE_DIR}/jdk +JBRSDK_BUNDLE=jbrsdk + +echo Fixing permissions +chmod -R a+r $JSDK + +rm -rf $BASE_DIR/$JBRSDK_BUNDLE +cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? + +echo Creating $JBSDK.tar.gz ... +tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? +gzip $JBSDK.tar || exit $? + +JBR_BUNDLE=jbr +JBR_BASE_NAME=jbr-$JBSDK_VERSION +rm -rf $BASE_DIR/$JBR_BUNDLE + +JBR=$JBR_BASE_NAME-linux-x86-b$build_number +grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 +echo Running jlink.... +${JSDK}/bin/jlink \ + --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules.list.x86 | sed s/" "//g | sed s/,$//g) --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? + +echo Modifying release info ... +grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release + +echo Creating $JBR.tar.gz ... +tar -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $? +gzip $JBR.tar || exit $? + +JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number +echo Creating $JBRSDK_TEST.tar.gz ... +tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $? +gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkbundles.sh b/jb/project/tools/mac/scripts/mkbundles.sh index ba50d4213c4b..cf4212190f1f 100755 --- a/jb/project/tools/mac/scripts/mkbundles.sh +++ b/jb/project/tools/mac/scripts/mkbundles.sh @@ -1,8 +1,8 @@ -#!/bin/bash +#!/bin/bash -x JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 - -bash -x jb/project/tools/mac/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" -bash -x jb/project/tools/mac/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" +script_dir=jb/project/tools/mac/scripts +${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" +${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index da4dd7d948f7..42b0c326b24e 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # The following parameters must be specified: # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 @@ -99,8 +99,7 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR mkdir $BASE_DIR || exit $? JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -cp -a build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-$JBSDK_VERSION_WITH_DOTS.jdk \ - $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? if [ "$bundle_type" == "jcef" ]; then echo Creating $JBSDK.tar.gz ... diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh new file mode 100755 index 000000000000..6aa48f759811 --- /dev/null +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -0,0 +1,83 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} + +sh configure \ + --disable-warnings-as-errors \ + --with-debug-level=fastdebug \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-pre= \ + --with-version-opt=b$build_number \ + --with-import-modules=./modular-sdk \ + --with-boot-jdk=`/usr/libexec/java_home -v 11` \ + --enable-cds=yes || exit $? +make clean CONF=macosx-x86_64-normal-server-fastdebug || exit $? +make images CONF=macosx-x86_64-normal-server-fastdebug || exit $? + +JSDK=build/macosx-x86_64-normal-server-fastdebug/images/jdk-bundle +JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} + +BASE_DIR=jre +JBRSDK_BUNDLE=jbrsdk + +rm -rf $BASE_DIR +mkdir $BASE_DIR || exit $? +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? + +echo Creating $JBSDK.tar.gz ... +cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ +cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents + +COPYFILE_DISABLE=1 \ + tar -pczf ${JBSDK}.tar.gz -C ${BASE_DIR} \ + --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ + --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ + ${JBRSDK_BUNDLE} || exit $? + +JBR_BUNDLE=jbr +JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents +JRE_HOME=$JRE_CONTENTS/Home + JBR_BASE_NAME=jbr-$JBSDK_VERSION + +mkdir -p $JRE_CONTENTS + +if [ -d "$JRE_HOME" ]; then + rm -rf $JRE_HOME +fi + +JBR=${JBR_BASE_NAME}-osx-x64-fastdebug-b${build_number} + +$BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ + --module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules.list | sed s/" "//g) --output $JRE_HOME || exit $? +grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release +cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS +cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS +cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? +cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $? + + +echo Creating $JBR.tar.gz ... +COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $? diff --git a/jb/project/tools/windows/scripts/mkbundles.sh b/jb/project/tools/windows/scripts/mkbundles.sh deleted file mode 100755 index e4e37bb19c4c..000000000000 --- a/jb/project/tools/windows/scripts/mkbundles.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -x - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -jb/project/tools/windows/scripts/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkbundles_x64.sh b/jb/project/tools/windows/scripts/mkbundles_x64.sh new file mode 100755 index 000000000000..6c7d124ee86c --- /dev/null +++ b/jb/project/tools/windows/scripts/mkbundles_x64.sh @@ -0,0 +1,8 @@ +#!/bin/bash -x + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 +script_dir=jb/project/tools/windows/scripts +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh similarity index 96% rename from jb/project/tools/windows/scripts/mkimages.sh rename to jb/project/tools/windows/scripts/mkimages_x64.sh index f2eede20639a..c509a52c0913 100755 --- a/jb/project/tools/windows/scripts/mkimages.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -71,7 +71,7 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --disable-ccache \ --enable-cds=yes || exit 1 make clean CONF=windows-x86_64-normal-server-release || exit 1 -make JOBS=7 LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 +make LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 JSDK=build/windows-x86_64-normal-server-release/images/jdk JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh new file mode 100755 index 000000000000..6aa3f19bb6cf --- /dev/null +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -0,0 +1,57 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +WORK_DIR=$(pwd) + +PATH="/usr/local/bin:/usr/bin:${PATH}" +./configure \ + --disable-warnings-as-errors \ + --disable-debug-symbols \ + --with-target-bits=32 \ + --with-version-pre= \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ + --with-toolchain-version=2015 \ + --with-boot-jdk=${BOOT_JDK} \ + --disable-ccache \ + --enable-cds=yes || exit 1 +make clean CONF=windows-x86-normal-server-release || exit 1 +make LOG=info images CONF=windows-x86-normal-server-release test-image || exit 1 + +JBSDK=${JBRSDK_BASE_NAME}-windows-x86-b${build_number} +BASE_DIR=build/windows-x86-normal-server-release/images +JSDK=${BASE_DIR}/jdk +JBRSDK_BUNDLE=jbrsdk + +rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 + +JBR_BUNDLE=jbr +rm -rf ${JBR_BUNDLE} +grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 +${JSDK}/bin/jlink \ + --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ + --add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? + +echo Modifying release info ... +grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release diff --git a/jb/project/tools/windows/scripts/pack.sh b/jb/project/tools/windows/scripts/pack_x64.sh similarity index 100% rename from jb/project/tools/windows/scripts/pack.sh rename to jb/project/tools/windows/scripts/pack_x64.sh diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh new file mode 100755 index 000000000000..e135a80570f4 --- /dev/null +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -0,0 +1,45 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 +# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to bu built; possible values: +# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created +# jfx - the bundle 1) jbr with javafx only will be created +# +# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# +# $ ./java --version +# openjdk 11.0.6 2020-01-14 +# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) +# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# + +JBSDK_VERSION=$1 +JDK_BUILD_NUMBER=$2 +build_number=$3 + +JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION +JBR_BASE_NAME=jbr-$JBSDK_VERSION + +IMAGES_DIR=build/windows-x86-normal-server-release/images +JSDK=$IMAGES_DIR/jdk +JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number +BASE_DIR=. + +JBRSDK_BUNDLE=jbrsdk +echo Creating $JBSDK.tar.gz ... +/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 + +JBR_BUNDLE=jbr +JBR_BASE_NAME=jbr-${JBSDK_VERSION} + +JBR=$JBR_BASE_NAME-windows-x86-b$build_number +echo Creating $JBR.tar.gz ... +/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR ${JBR_BUNDLE} || exit 1 + +JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x86-b$build_number +echo Creating $JBRSDK_TEST.tar.gz ... +/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 From 55e299a6b2e2962b981caa24002d524549711815 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 19 Mar 2020 15:21:15 +0700 Subject: [PATCH 017/976] JBR-2217 provide JCEF-only (no JavaFX) bundle for master/202 branches --- jb/project/tools/exclude_jfx_module.patch | 21 +++++++++ .../tools/linux/scripts/mkbundles_x64.sh | 5 +- .../tools/linux/scripts/mkimages_x64.sh | 47 ++++++++++--------- jb/project/tools/mac/scripts/mkbundles.sh | 5 +- jb/project/tools/mac/scripts/mkimages.sh | 37 ++++++++------- .../tools/windows/scripts/mkbundles_x64.sh | 3 +- .../tools/windows/scripts/mkimages_x64.sh | 41 ++++++++++------ jb/project/tools/windows/scripts/pack_x64.sh | 13 +++-- 8 files changed, 108 insertions(+), 64 deletions(-) create mode 100644 jb/project/tools/exclude_jfx_module.patch diff --git a/jb/project/tools/exclude_jfx_module.patch b/jb/project/tools/exclude_jfx_module.patch new file mode 100644 index 000000000000..ba7c9b493d43 --- /dev/null +++ b/jb/project/tools/exclude_jfx_module.patch @@ -0,0 +1,21 @@ +Index: modules.list +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +--- modules.list (revision 57ff1dba25206f9f078b48995aa8744e51b1dd2a) ++++ modules.list (date 1584500341724) +@@ -20,13 +20,6 @@ + java.transaction.xa, + java.xml, + java.xml.crypto, +-javafx.base, +-javafx.controls, +-javafx.fxml, +-javafx.graphics, +-javafx.media, +-javafx.swing, +-javafx.web, + jdk.accessibility, + jdk.aot, + jdk.charsets, diff --git a/jb/project/tools/linux/scripts/mkbundles_x64.sh b/jb/project/tools/linux/scripts/mkbundles_x64.sh index 5c3ab27ff740..d22ed3c785ab 100755 --- a/jb/project/tools/linux/scripts/mkbundles_x64.sh +++ b/jb/project/tools/linux/scripts/mkbundles_x64.sh @@ -4,5 +4,6 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 script_dir=jb/project/tools/linux/scripts -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 322fed871fd6..68ecf0d12d01 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -26,22 +26,22 @@ function create_jbr { case "$1" in "${bundle_type}_lw") - JBR_BASE_NAME=jbr_${bundle_type}_lw-$JBSDK_VERSION + JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list ;; - "jfx") - JBR_BASE_NAME=jbr_${bundle_type}-$JBSDK_VERSION + "jfx" | "jcef") + JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} cat modules.list > modules_tmp.list ;; - "jcef") - JBR_BASE_NAME=jbr-$JBSDK_VERSION + "jfx_jcef") + JBR_BASE_NAME=jbr-${JBSDK_VERSION} cat modules.list > modules_tmp.list ;; *) - echo "***ERR*** bundle was not specified" && exit $? + echo "***ERR*** bundle was not specified" && exit 1 ;; esac - rm -rf $BASE_DIR/$JBR_BUNDLE + rm -rf ${BASE_DIR}/${JBR_BUNDLE} JBR=$JBR_BASE_NAME-linux-x64-b$build_number @@ -50,7 +50,7 @@ function create_jbr { --module-path $JSDK/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE - if [ "$bundle_type" == "jcef" ]; then + if [[ "$bundle_type" == *jcef* ]]; then cp -R $BASE_DIR/$JBR_BUNDLE $BASE_DIR/jbr cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? fi @@ -61,24 +61,30 @@ function create_jbr { cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $? gzip $JBR.tar || exit $? + rm -rf ${BASE_DIR}/${JBR_BUNDLE} } JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -if [ "$bundle_type" == "jfx" ]; then - git apply -p0 < jb/project/tools/exclude_jcef_module.patch -fi +git checkout -- modules.list src/java.desktop/share/classes/module-info.java +case "$bundle_type" in + "jfx") + git apply -p0 < jb/project/tools/exclude_jcef_module.patch + ;; + "jcef") + git apply -p0 < jb/project/tools/exclude_jfx_module.patch + ;; +esac sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ - --with-version-build=$JDK_BUILD_NUMBER \ --with-version-pre= \ - --with-version-opt=b$build_number \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --enable-cds=yes || exit $? -make clean CONF=linux-x86_64-normal-server-release || exit $? make images CONF=linux-x86_64-normal-server-release || exit $? JSDK=build/linux-x86_64-normal-server-release/images/jdk @@ -93,21 +99,20 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? -if [ "$bundle_type" == "jcef" ]; then +if [[ "$bundle_type" == *jcef* ]]; then cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? - +fi +if [ "$bundle_type" == "jfx_jcef" ]; then echo Creating $JBSDK.tar.gz ... - tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR $JBRSDK_BUNDLE || exit $? + tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ + -C $BASE_DIR $JBRSDK_BUNDLE || exit $? gzip $JBSDK.tar || exit $? fi JBR_BUNDLE=jbr_${bundle_type} create_jbr ${bundle_type} -JBR_BUNDLE=jbr_${bundle_type}_lw -create_jbr ${bundle_type}_lw - -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jfx_jcef" ]; then make test-image || exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number diff --git a/jb/project/tools/mac/scripts/mkbundles.sh b/jb/project/tools/mac/scripts/mkbundles.sh index cf4212190f1f..f8c3fff67d7c 100755 --- a/jb/project/tools/mac/scripts/mkbundles.sh +++ b/jb/project/tools/mac/scripts/mkbundles.sh @@ -4,5 +4,6 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 script_dir=jb/project/tools/mac/scripts -${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" -${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" +${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? +${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? +${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 42b0c326b24e..8527f4a0a530 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -29,16 +29,16 @@ function create_jbr { JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list ;; - "jfx") + "jfx" | "jcef") JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} cat modules.list > modules_tmp.list ;; - "jcef") + "jfx_jcef") JBR_BASE_NAME=jbr-${JBSDK_VERSION} cat modules.list > modules_tmp.list ;; *) - echo "***ERR*** bundle was not specified" && exit $? + echo "***ERR*** bundle was not specified" && exit 1 ;; esac rm -rf ${BASE_DIR}/${JBR_BUNDLE} @@ -59,7 +59,7 @@ function create_jbr { cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS} cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS} - if [ "${bundle_type}" == "jcef" ]; then + if [[ "${bundle_type}" == *jcef* ]]; then rm -rf ${JRE_CONTENTS}/Frameworks || exit $? rm -rf ${JRE_CONTENTS}/Helpers || exit $? cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? @@ -70,13 +70,20 @@ function create_jbr { rm -rf ${BASE_DIR}/jbr cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $? + rm -rf ${BASE_DIR}/${JBR_BUNDLE} } JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -if [ "${bundle_type}" == "jfx" ]; then - git apply -p0 < jb/project/tools/exclude_jcef_module.patch -fi +git checkout -- modules.list src/java.desktop/share/classes/module-info.java +case "$bundle_type" in + "jfx") + git apply -p0 < jb/project/tools/exclude_jcef_module.patch + ;; + "jcef") + git apply -p0 < jb/project/tools/exclude_jfx_module.patch + ;; +esac sh configure \ --disable-warnings-as-errors \ @@ -101,11 +108,12 @@ mkdir $BASE_DIR || exit $? JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? -if [ "$bundle_type" == "jcef" ]; then - echo Creating $JBSDK.tar.gz ... +if [[ "$bundle_type" == *jcef* ]]; then cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ - +fi +if [ "$bundle_type" == "jfx_jcef" ]; then + echo Creating $JBSDK.tar.gz ... COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ @@ -113,17 +121,14 @@ if [ "$bundle_type" == "jcef" ]; then fi JBR_BUNDLE=jbr_${bundle_type} -create_jbr $bundle_type - -JBR_BUNDLE=jbr_${bundle_type}_lw -create_jbr "${bundle_type}_lw" +create_jbr "${bundle_type}" || exit $? -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jfx_jcef" ]; then make test-image || exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number - echo Creating $JBSDK_TEST.tar.gz ... + echo Creating $JBRSDK_TEST.tar.gz ... COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-normal-server-release/images \ --exclude='test/jdk/demos' test || exit $? fi \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkbundles_x64.sh b/jb/project/tools/windows/scripts/mkbundles_x64.sh index 6c7d124ee86c..38704d02399f 100755 --- a/jb/project/tools/windows/scripts/mkbundles_x64.sh +++ b/jb/project/tools/windows/scripts/mkbundles_x64.sh @@ -5,4 +5,5 @@ JDK_BUILD_NUMBER=$2 build_number=$3 script_dir=jb/project/tools/windows/scripts ${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? \ No newline at end of file +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? +${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index c509a52c0913..1d76dcb1eb91 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -28,14 +28,11 @@ function create_jbr { "${bundle_type}_lw") grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list ;; - "jfx") - cat modules.list > modules_tmp.list - ;; - "jcef") + "jfx" | "jcef" | "jfx_jcef") cat modules.list > modules_tmp.list ;; *) - echo "***ERR*** bundle was not specified" && exit $? + echo "***ERR*** bundle was not specified" && exit 1 ;; esac rm -rf ${JBR_BUNDLE} @@ -43,7 +40,8 @@ function create_jbr { ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? - if [ "${bundle_type}" == "jcef" ]; then + if [[ "${bundle_type}" == *jcef* ]] + then cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin fi echo Modifying release info ... @@ -53,9 +51,17 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -if [ "${bundle_type}" == "jfx" ]; then - git apply -p0 < jb/project/tools/exclude_jcef_module.patch -fi +git checkout -- modules.list src/java.desktop/share/classes/module-info.java +case "$bundle_type" in + "jfx") + echo "Excluding jcef modules" + git apply -p0 < jb/project/tools/exclude_jcef_module.patch + ;; + "jcef") + echo "Excluding jfx modules" + git apply -p0 < jb/project/tools/exclude_jfx_module.patch + ;; +esac PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ @@ -70,12 +76,17 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ --enable-cds=yes || exit 1 -make clean CONF=windows-x86_64-normal-server-release || exit 1 -make LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 -JSDK=build/windows-x86_64-normal-server-release/images/jdk -JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} +if [ "$bundle_type" == "jfx_jcef" ]; then + make LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 +else + make LOG=info images CONF=windows-x86_64-normal-server-release || exit 1 +fi +JSDK=build/windows-x86_64-normal-server-release/images/jdk +if [[ "$bundle_type" == *jcef* ]]; then + JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} +fi BASE_DIR=build/windows-x86_64-normal-server-release/images JBRSDK_BUNDLE=jbrsdk @@ -85,5 +96,5 @@ cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin JBR_BUNDLE=jbr_${bundle_type} create_jbr ${bundle_type} -JBR_BUNDLE=jbr_${bundle_type}_lw -create_jbr ${bundle_type}_lw +#JBR_BUNDLE=jbr_${bundle_type}_lw +#create_jbr ${bundle_type}_lw diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index f4fa3ade69e6..b88b6f818b6b 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -28,14 +28,14 @@ function pack_jbr { "${bundle_type}_lw") JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} ;; - "jfx") + "jfx" | "jcef") JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} ;; - "jcef") + "jfx_jcef") JBR_BASE_NAME=jbr-${JBSDK_VERSION} ;; *) - echo "***ERR*** bundle was not specified" && exit $? + echo "***ERR*** bundle was not specified" && exit 1 ;; esac @@ -45,6 +45,7 @@ function pack_jbr { cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1 + #rm -rf ${BASE_DIR}/${JBR_BUNDLE} } JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION @@ -55,7 +56,7 @@ JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jfx_jcef" ]; then JBRSDK_BUNDLE=jbrsdk echo Creating $JBSDK.tar.gz ... /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 @@ -63,10 +64,8 @@ fi JBR_BUNDLE=jbr_${bundle_type} pack_jbr $bundle_type -JBR_BUNDLE=jbr_${bundle_type}_lw -pack_jbr ${bundle_type}_lw -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jfx_jcef" ]; then JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 From 06c3058d759f9369b8f0abb8fe91e7953b7e6bd8 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 23 Apr 2020 06:28:58 +0700 Subject: [PATCH 018/976] JBR-2320 add jdk.attach module into JBR --- jb/project/tools/exclude_jcef_module.patch | 12 ++++++------ jb/project/tools/exclude_jfx_module.patch | 6 +++--- modules.list | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/jb/project/tools/exclude_jcef_module.patch b/jb/project/tools/exclude_jcef_module.patch index 9c60d4cacb9e..bc9a14598756 100644 --- a/jb/project/tools/exclude_jcef_module.patch +++ b/jb/project/tools/exclude_jcef_module.patch @@ -3,8 +3,8 @@ IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- src/java.desktop/share/classes/module-info.java (revision 08d1926f8b7c74da0e1144e0ce5912e7589c4688) -+++ src/java.desktop/share/classes/module-info.java (date 1583207610780) +--- src/java.desktop/share/classes/module-info.java (revision 5ae6630e3ebc71beb9f9df63b1b5bc19c9405d1f) ++++ src/java.desktop/share/classes/module-info.java (date 1588168285537) @@ -109,10 +109,7 @@ // see make/GensrcModuleInfo.gmk exports sun.awt to @@ -14,7 +14,7 @@ Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP - - exports java.awt.peer to jcef; + jdk.unsupported.desktop; - + exports java.awt.dnd.peer to jdk.unsupported.desktop; exports sun.awt.dnd to jdk.unsupported.desktop; Index: modules.list @@ -22,9 +22,9 @@ IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- modules.list (revision 08d1926f8b7c74da0e1144e0ce5912e7589c4688) -+++ modules.list (date 1583207610776) -@@ -60,5 +60,4 @@ +--- modules.list (revision 5ae6630e3ebc71beb9f9df63b1b5bc19c9405d1f) ++++ modules.list (date 1588168285505) +@@ -61,5 +61,4 @@ jdk.unsupported, jdk.xml.dom, jdk.zipfs, diff --git a/jb/project/tools/exclude_jfx_module.patch b/jb/project/tools/exclude_jfx_module.patch index ba7c9b493d43..d5a4cf4aa8f9 100644 --- a/jb/project/tools/exclude_jfx_module.patch +++ b/jb/project/tools/exclude_jfx_module.patch @@ -3,8 +3,8 @@ IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- modules.list (revision 57ff1dba25206f9f078b48995aa8744e51b1dd2a) -+++ modules.list (date 1584500341724) +--- modules.list (revision ab073976c4f85f154ff1421b7ac888eee86b6595) ++++ modules.list (date 1588171510146) @@ -20,13 +20,6 @@ java.transaction.xa, java.xml, @@ -18,4 +18,4 @@ Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -javafx.web, jdk.accessibility, jdk.aot, - jdk.charsets, + jdk.attach, diff --git a/modules.list b/modules.list index 5dca7ca4dfd9..6dd7546add45 100644 --- a/modules.list +++ b/modules.list @@ -29,6 +29,7 @@ javafx.swing, javafx.web, jdk.accessibility, jdk.aot, +jdk.attach, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, From 292bb94ebd77d421a070507b7f8b4daace608b9a Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sat, 25 Apr 2020 08:39:02 +0700 Subject: [PATCH 019/976] JBR-2324 address new layout in mac jcef 80.0.4+g74f7b0c+chromium-80.0.3987.122 --- jb/project/tools/mac/scripts/mkimages.sh | 3 --- jb/project/tools/mac/scripts/sign.sh | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 8527f4a0a530..7b9db85d7639 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -61,9 +61,7 @@ function create_jbr { if [[ "${bundle_type}" == *jcef* ]]; then rm -rf ${JRE_CONTENTS}/Frameworks || exit $? - rm -rf ${JRE_CONTENTS}/Helpers || exit $? cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? - cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $? fi echo Creating ${JBR}.tar.gz ... @@ -110,7 +108,6 @@ cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? if [[ "$bundle_type" == *jcef* ]]; then cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ - cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ fi if [ "$bundle_type" == "jfx_jcef" ]; then echo Creating $JBSDK.tar.gz ... diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index e4d6e5526ba9..d9f9f646a57b 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -27,8 +27,7 @@ log "Signing libraries and executables..." for f in \ "Contents/Home/bin" \ "Contents/Home/lib" \ - "Contents/Frameworks" \ - "Contents/Helpers"; do + "Contents/Frameworks"; do if [ -d "$APP_DIRECTORY/$f" ]; then find "$APP_DIRECTORY/$f" \ -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ From 2bf5e9eb952db7cae7c900f0fed69a04be77ba45 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 8 May 2020 16:39:27 +0700 Subject: [PATCH 020/976] JBR-2291 add vendor info into bundles --- jb/project/tools/common.sh | 3 +++ .../tools/linux/scripts/mkimages_aarch64.sh | 14 +++++++++++--- jb/project/tools/linux/scripts/mkimages_x64.sh | 8 ++++++++ jb/project/tools/linux/scripts/mkimages_x64_fd.sh | 14 ++++++++++++-- jb/project/tools/linux/scripts/mkimages_x86.sh | 13 +++++++++++-- jb/project/tools/mac/scripts/mkimages.sh | 8 +++++++- jb/project/tools/mac/scripts/mkimages_fd.sh | 15 +++++++++++---- jb/project/tools/windows/scripts/mkimages_x64.sh | 9 ++++++++- jb/project/tools/windows/scripts/mkimages_x86.sh | 10 +++++++++- 9 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 jb/project/tools/common.sh diff --git a/jb/project/tools/common.sh b/jb/project/tools/common.sh new file mode 100644 index 000000000000..9a9ebe7f7d7d --- /dev/null +++ b/jb/project/tools/common.sh @@ -0,0 +1,3 @@ +VENDOR_NAME="JetBrains s.r.o." +VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}" +[ -z ${bundle_type} ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index b14761f84ba5..bbddcb137f0b 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -21,15 +21,20 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh + JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ - --with-version-build=$JDK_BUILD_NUMBER \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ - --with-version-opt=b$build_number \ - --with-boot-jdk=amazon-corretto-11.0.5.10.1-linux-aarch64 \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --enable-cds=yes || exit $? make clean CONF=linux-aarch64-normal-server-release || exit $? @@ -47,6 +52,9 @@ rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? echo Creating $JBSDK.tar.gz ... +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + tar -pcf $JBSDK.tar \ --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 68ecf0d12d01..57d2be5fa06c 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -21,6 +21,9 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh function create_jbr { @@ -79,6 +82,8 @@ esac sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ @@ -104,6 +109,9 @@ if [[ "$bundle_type" == *jcef* ]]; then fi if [ "$bundle_type" == "jfx_jcef" ]; then echo Creating $JBSDK.tar.gz ... + sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release + mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ -C $BASE_DIR $JBRSDK_BUNDLE || exit $? gzip $JBSDK.tar || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh index 25ff62a2254b..d7f054499b93 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -21,14 +21,21 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh + + JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} sh configure \ --disable-warnings-as-errors \ --with-debug-level=fastdebug \ - --with-version-build=$JDK_BUILD_NUMBER \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ - --with-version-opt=b$build_number \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --enable-cds=yes || exit $? make clean CONF=linux-x86_64-normal-server-fastdebug || exit $? @@ -47,6 +54,9 @@ cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? echo Creating $JBSDK.tar.gz ... +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + tar -pcf $JBSDK.tar \ --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 65986698dbd4..7ef7ac5d1a14 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -21,14 +21,20 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh + JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} linux32 bash configure \ --disable-warnings-as-errors \ --with-debug-level=release \ - --with-version-build=$JDK_BUILD_NUMBER \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ - --with-version-opt=b$build_number \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b${build_number} \ --with-boot-jdk=/jbrsdk-11.0.5-b1 \ --enable-cds=yes || exit $? make clean CONF=linux-x86-normal-server-release || exit $? @@ -46,6 +52,9 @@ rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? echo Creating $JBSDK.tar.gz ... +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? gzip $JBSDK.tar || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 7b9db85d7639..81511eeaf140 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -21,6 +21,9 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh function create_jbr { @@ -86,6 +89,8 @@ esac sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ @@ -103,7 +108,6 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR mkdir $BASE_DIR || exit $? -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? if [[ "$bundle_type" == *jcef* ]]; then @@ -111,6 +115,8 @@ if [[ "$bundle_type" == *jcef* ]]; then fi if [ "$bundle_type" == "jfx_jcef" ]; then echo Creating $JBSDK.tar.gz ... + sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release + mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh index 6aa48f759811..50130e4ec231 100755 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -21,14 +21,20 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh + JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} sh configure \ --disable-warnings-as-errors \ --with-debug-level=fastdebug \ - --with-version-build=$JDK_BUILD_NUMBER \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ - --with-version-opt=b$build_number \ + --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --with-boot-jdk=`/usr/libexec/java_home -v 11` \ --enable-cds=yes || exit $? @@ -48,7 +54,9 @@ cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? echo Creating $JBSDK.tar.gz ... cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ -cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents + +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release COPYFILE_DISABLE=1 \ tar -pczf ${JBSDK}.tar.gz -C ${BASE_DIR} \ @@ -76,7 +84,6 @@ grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? -cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $? echo Creating $JBR.tar.gz ... diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 1d76dcb1eb91..a70d466998f1 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -21,6 +21,9 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh function create_jbr { @@ -45,7 +48,7 @@ function create_jbr { cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin fi echo Modifying release info ... - grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release + cat ${JSDK}/release | tr -d '\r' | grep -v 'JAVA_VERSION' | grep -v 'MODULES' >> ${JBR_BUNDLE}/release } JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} @@ -68,6 +71,8 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --disable-warnings-as-errors \ --disable-debug-symbols \ --with-target-bits=64 \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ @@ -92,6 +97,8 @@ JBRSDK_BUNDLE=jbrsdk rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin +sed 's/JBR/JBRSDK/g' ${JSDK}/release > release +mv release ${JBRSDK_BUNDLE}/release JBR_BUNDLE=jbr_${bundle_type} create_jbr ${bundle_type} diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 6aa3f19bb6cf..68c15e73f3ce 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -21,6 +21,10 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') + +source jb/project/tools/common.sh + JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) @@ -29,6 +33,8 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --disable-warnings-as-errors \ --disable-debug-symbols \ --with-target-bits=32 \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ @@ -45,6 +51,8 @@ JSDK=${BASE_DIR}/jdk JBRSDK_BUNDLE=jbrsdk rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 +sed 's/JBR/JBRSDK/g' ${JSDK}/release > release +mv release ${JBRSDK_BUNDLE}/release JBR_BUNDLE=jbr rm -rf ${JBR_BUNDLE} @@ -54,4 +62,4 @@ ${JSDK}/bin/jlink \ --add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? echo Modifying release info ... -grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release +#grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release From 095f01a00cac5a7a2fbe5bc8feb9c9083fd46cec Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 15 May 2020 10:10:34 +0700 Subject: [PATCH 021/976] change BOOT_JDK, fix target names --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 1 + jb/project/tools/mac/scripts/mkimages.sh | 8 ++++---- jb/project/tools/mac/scripts/mkimages_fd.sh | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index bbddcb137f0b..e4cb4688499c 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -36,6 +36,7 @@ sh configure \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ + --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? make clean CONF=linux-aarch64-normal-server-release || exit $? make images CONF=linux-aarch64-normal-server-release test-image || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 81511eeaf140..9410b43afa2c 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -95,12 +95,12 @@ sh configure \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ - --with-boot-jdk=`/usr/libexec/java_home -v 11` \ + --with-boot-jdk=`/usr/libexec/java_home -v 14` \ --enable-cds=yes || exit $? -make images CONF=macosx-x86_64-normal-server-release || exit $? +make images CONF=macosx-x86_64-server-release || exit $? -JSDK=build/macosx-x86_64-normal-server-release/images/jdk-bundle +JSDK=build/macosx-x86_64-server-release/images/jdk-bundle JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} BASE_DIR=jre @@ -132,6 +132,6 @@ if [ "$bundle_type" == "jfx_jcef" ]; then JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... - COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-normal-server-release/images \ + COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ --exclude='test/jdk/demos' test || exit $? fi \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh index 50130e4ec231..b4f446b9ca7f 100755 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -36,12 +36,12 @@ sh configure \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ - --with-boot-jdk=`/usr/libexec/java_home -v 11` \ + --with-boot-jdk=`/usr/libexec/java_home -v 14` \ --enable-cds=yes || exit $? -make clean CONF=macosx-x86_64-normal-server-fastdebug || exit $? -make images CONF=macosx-x86_64-normal-server-fastdebug || exit $? +make clean CONF=macosx-x86_64-server-fastdebug || exit $? +make images CONF=macosx-x86_64-server-fastdebug || exit $? -JSDK=build/macosx-x86_64-normal-server-fastdebug/images/jdk-bundle +JSDK=build/macosx-x86_64-server-fastdebug/images/jdk-bundle JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} BASE_DIR=jre From c35a9566f67c089d193e9833457c3d97ca084b01 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 15 May 2020 12:08:17 +0700 Subject: [PATCH 022/976] split checkout before building JBR+JFX or JBR+JCEF on two separate commands --- jb/project/tools/linux/scripts/mkimages_x64.sh | 3 ++- jb/project/tools/mac/scripts/mkimages.sh | 3 ++- jb/project/tools/windows/scripts/mkimages_x64.sh | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 57d2be5fa06c..c99305b1f640 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -69,7 +69,8 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -git checkout -- modules.list src/java.desktop/share/classes/module-info.java +git checkout -- modules.list +git checkout -- src/java.desktop/share/classes/module-info.java case "$bundle_type" in "jfx") git apply -p0 < jb/project/tools/exclude_jcef_module.patch diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 9410b43afa2c..e5606d80d10f 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -76,7 +76,8 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -git checkout -- modules.list src/java.desktop/share/classes/module-info.java +git checkout -- modules.list +git checkout -- src/java.desktop/share/classes/module-info.java case "$bundle_type" in "jfx") git apply -p0 < jb/project/tools/exclude_jcef_module.patch diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index a70d466998f1..85e914659257 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -54,7 +54,8 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -git checkout -- modules.list src/java.desktop/share/classes/module-info.java +git checkout -- modules.list +git checkout -- src/java.desktop/share/classes/module-info.java case "$bundle_type" in "jfx") echo "Excluding jcef modules" From b83fb04f5a8bdd657df74536af3ad23ccf731845 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 15 May 2020 12:10:04 +0700 Subject: [PATCH 023/976] add exec permitions to configure --- configure | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 configure diff --git a/configure b/configure old mode 100644 new mode 100755 From 8c14b52e8d8dafccb9e314ad7003f2fdf66f9950 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 15 May 2020 18:19:52 +0700 Subject: [PATCH 024/976] JBR-2394 replace --disable-debug-symbols with --with-native-debug-symbols=none --- jb/project/tools/windows/scripts/mkimages_x64.sh | 2 +- jb/project/tools/windows/scripts/mkimages_x86.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 85e914659257..48feff4c4270 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -70,7 +70,7 @@ esac PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ - --disable-debug-symbols \ + --with-native-debug-symbols=none \ --with-target-bits=64 \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 68c15e73f3ce..30c8c8cc777f 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -31,7 +31,7 @@ WORK_DIR=$(pwd) PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ - --disable-debug-symbols \ + --with-native-debug-symbols=none \ --with-target-bits=32 \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ From ed1e7bf358751d89afac99fb62ab38a2da2f58a4 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 15 May 2020 18:23:16 +0700 Subject: [PATCH 025/976] JBR-2396 fix CONF names --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 6 +++--- jb/project/tools/linux/scripts/mkimages_x64.sh | 7 ++++--- jb/project/tools/linux/scripts/mkimages_x64_fd.sh | 6 +++--- jb/project/tools/linux/scripts/mkimages_x86.sh | 6 +++--- jb/project/tools/windows/scripts/mkimages_x64.sh | 8 ++++---- jb/project/tools/windows/scripts/mkimages_x86.sh | 6 +++--- jb/project/tools/windows/scripts/pack_x64.sh | 2 +- jb/project/tools/windows/scripts/pack_x86.sh | 2 +- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index e4cb4688499c..f584a0642b56 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -38,11 +38,11 @@ sh configure \ --with-import-modules=./modular-sdk \ --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? -make clean CONF=linux-aarch64-normal-server-release || exit $? -make images CONF=linux-aarch64-normal-server-release test-image || exit $? +make clean CONF=linux-aarch64-server-release || exit $? +make images CONF=linux-aarch64-server-release test-image || exit $? JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number} -BASE_DIR=build/linux-aarch64-normal-server-release/images +BASE_DIR=build/linux-aarch64-server-release/images JSDK=${BASE_DIR}/jdk JBRSDK_BUNDLE=jbrsdk diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index c99305b1f640..d088c8ec6108 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -89,17 +89,18 @@ sh configure \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ + --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? -make images CONF=linux-x86_64-normal-server-release || exit $? +make images CONF=linux-x86_64-server-release || exit $? -JSDK=build/linux-x86_64-normal-server-release/images/jdk +JSDK=build/linux-x86_64-server-release/images/jdk JBSDK=$JBRSDK_BASE_NAME-linux-x64-b$build_number echo Fixing permissions chmod -R a+r $JSDK -BASE_DIR=build/linux-x86_64-normal-server-release/images +BASE_DIR=build/linux-x86_64-server-release/images JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR/$JBRSDK_BUNDLE diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh index d7f054499b93..a29ce3976bb4 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -38,11 +38,11 @@ sh configure \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ --enable-cds=yes || exit $? -make clean CONF=linux-x86_64-normal-server-fastdebug || exit $? -make images CONF=linux-x86_64-normal-server-fastdebug || exit $? +make clean CONF=linux-x86_64-server-fastdebug || exit $? +make images CONF=linux-x86_64-server-fastdebug || exit $? JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number} -BASE_DIR=build/linux-x86_64-normal-server-fastdebug/images +BASE_DIR=build/linux-x86_64-server-fastdebug/images JSDK=${BASE_DIR}/jdk JBRSDK_BUNDLE=jbrsdk diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 7ef7ac5d1a14..00a47b893ff0 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -37,11 +37,11 @@ linux32 bash configure \ --with-version-opt=b${build_number} \ --with-boot-jdk=/jbrsdk-11.0.5-b1 \ --enable-cds=yes || exit $? -make clean CONF=linux-x86-normal-server-release || exit $? -make images CONF=linux-x86-normal-server-release test-image || exit $? +make clean CONF=linux-x86-server-release || exit $? +make images CONF=linux-x86-server-release test-image || exit $? JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number} -BASE_DIR=build/linux-x86-normal-server-release/images +BASE_DIR=build/linux-x86-server-release/images JSDK=${BASE_DIR}/jdk JBRSDK_BUNDLE=jbrsdk diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 48feff4c4270..d3a3901a119a 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -84,16 +84,16 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --enable-cds=yes || exit 1 if [ "$bundle_type" == "jfx_jcef" ]; then - make LOG=info images CONF=windows-x86_64-normal-server-release test-image || exit 1 + make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1 else - make LOG=info images CONF=windows-x86_64-normal-server-release || exit 1 + make LOG=info images CONF=windows-x86_64-server-release || exit 1 fi -JSDK=build/windows-x86_64-normal-server-release/images/jdk +JSDK=build/windows-x86_64-server-release/images/jdk if [[ "$bundle_type" == *jcef* ]]; then JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} fi -BASE_DIR=build/windows-x86_64-normal-server-release/images +BASE_DIR=build/windows-x86_64-server-release/images JBRSDK_BUNDLE=jbrsdk rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 30c8c8cc777f..094c4ad7e2af 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -42,11 +42,11 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ --enable-cds=yes || exit 1 -make clean CONF=windows-x86-normal-server-release || exit 1 -make LOG=info images CONF=windows-x86-normal-server-release test-image || exit 1 +make clean CONF=windows-x86-server-release || exit 1 +make LOG=info images CONF=windows-x86-server-release test-image || exit 1 JBSDK=${JBRSDK_BASE_NAME}-windows-x86-b${build_number} -BASE_DIR=build/windows-x86-normal-server-release/images +BASE_DIR=build/windows-x86-server-release/images JSDK=${BASE_DIR}/jdk JBRSDK_BUNDLE=jbrsdk diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index b88b6f818b6b..7677cbcbaf4c 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -51,7 +51,7 @@ function pack_jbr { JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION JBR_BASE_NAME=jbr-$JBSDK_VERSION -IMAGES_DIR=build/windows-x86_64-normal-server-release/images +IMAGES_DIR=build/windows-x86_64-server-release/images JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index e135a80570f4..c254d53cf6e9 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -24,7 +24,7 @@ build_number=$3 JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION JBR_BASE_NAME=jbr-$JBSDK_VERSION -IMAGES_DIR=build/windows-x86-normal-server-release/images +IMAGES_DIR=build/windows-x86-server-release/images JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number BASE_DIR=. From 003f6f25b52c3ca9b2e747230c4a00434d4a6b20 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 19 May 2020 16:27:40 +0700 Subject: [PATCH 026/976] JDK14: exclude dependencies on jcef in x86, fastdebug builds --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 2 ++ jb/project/tools/linux/scripts/mkimages_x64_fd.sh | 2 ++ jb/project/tools/linux/scripts/mkimages_x86.sh | 2 ++ jb/project/tools/mac/scripts/mkimages_fd.sh | 2 ++ jb/project/tools/windows/scripts/mkimages_x86.sh | 2 ++ 5 files changed, 10 insertions(+) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index f584a0642b56..2498ed1000a4 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -27,6 +27,8 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch + sh configure \ --disable-warnings-as-errors \ --with-debug-level=release \ diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh index a29ce3976bb4..aa2a0b6b8b41 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -28,6 +28,8 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch + sh configure \ --disable-warnings-as-errors \ --with-debug-level=fastdebug \ diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 00a47b893ff0..b0e6b689124d 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -27,6 +27,8 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch + linux32 bash configure \ --disable-warnings-as-errors \ --with-debug-level=release \ diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh index b4f446b9ca7f..42053166104d 100755 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -27,6 +27,8 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch + sh configure \ --disable-warnings-as-errors \ --with-debug-level=fastdebug \ diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 094c4ad7e2af..53026d92f922 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -28,6 +28,8 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch + PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ From f11cdc26afb59478bd380b0b13ced235b2bfd606 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 19 May 2020 18:11:04 +0700 Subject: [PATCH 027/976] JBR-2409 fix prameters for configure --- jb/project/tools/windows/scripts/mkimages_x64.sh | 3 +-- jb/project/tools/windows/scripts/mkimages_x86.sh | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index d3a3901a119a..77e6dd106a43 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -70,15 +70,14 @@ esac PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ - --with-native-debug-symbols=none \ --with-target-bits=64 \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ + --with-toolchain-version=${TOOLCHAIN_VERSION} \ --with-import-modules=${WORK_DIR}/modular-sdk \ - --with-toolchain-version=2015 \ --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ --enable-cds=yes || exit 1 diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 53026d92f922..e93359abe4f4 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -40,7 +40,7 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ - --with-toolchain-version=2015 \ + --with-toolchain-version=${TOOLCHAIN_VERSION} \ --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ --enable-cds=yes || exit 1 From 6482b30d1e1e614fa1e5e134da37f69e536ee854 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 17 May 2020 05:26:32 +0700 Subject: [PATCH 028/976] JBR-2395 eliminate JavaFX from JBR --- jb/project/tools/exclude_jcef_module.patch | 39 ++++----- jb/project/tools/exclude_jfx_module.patch | 21 ----- .../tools/linux/scripts/mkbundles_x64.sh | 9 -- .../tools/linux/scripts/mkimages_aarch64.sh | 3 - .../tools/linux/scripts/mkimages_x64.sh | 75 ++++++----------- .../tools/linux/scripts/mkimages_x64_fd.sh | 4 +- .../tools/linux/scripts/mkimages_x86.sh | 5 +- jb/project/tools/mac/scripts/mkbundles.sh | 9 -- jb/project/tools/mac/scripts/mkimages.sh | 82 +++++++------------ jb/project/tools/mac/scripts/mkimages_fd.sh | 7 +- .../tools/windows/scripts/mkbundles_x64.sh | 9 -- .../tools/windows/scripts/mkimages_x64.sh | 57 ++++--------- .../tools/windows/scripts/mkimages_x86.sh | 1 - jb/project/tools/windows/scripts/pack_x64.sh | 47 ++++------- modules.list | 7 -- 15 files changed, 112 insertions(+), 263 deletions(-) delete mode 100644 jb/project/tools/exclude_jfx_module.patch delete mode 100755 jb/project/tools/linux/scripts/mkbundles_x64.sh delete mode 100755 jb/project/tools/mac/scripts/mkbundles.sh delete mode 100755 jb/project/tools/windows/scripts/mkbundles_x64.sh diff --git a/jb/project/tools/exclude_jcef_module.patch b/jb/project/tools/exclude_jcef_module.patch index bc9a14598756..43274c19588a 100644 --- a/jb/project/tools/exclude_jcef_module.patch +++ b/jb/project/tools/exclude_jcef_module.patch @@ -1,33 +1,34 @@ +Index: modules.list +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +--- modules.list (revision a73d4ecbefe65fd6d79b78663d916ff71b5346f7) ++++ modules.list (date 1589581743550) +@@ -54,5 +54,4 @@ + jdk.unsupported, + jdk.xml.dom, + jdk.zipfs, +-jdk.hotspot.agent, +-jcef ++jdk.hotspot.agent Index: src/java.desktop/share/classes/module-info.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- src/java.desktop/share/classes/module-info.java (revision 5ae6630e3ebc71beb9f9df63b1b5bc19c9405d1f) -+++ src/java.desktop/share/classes/module-info.java (date 1588168285537) -@@ -109,10 +109,7 @@ +--- src/java.desktop/share/classes/module-info.java (revision a73d4ecbefe65fd6d79b78663d916ff71b5346f7) ++++ src/java.desktop/share/classes/module-info.java (date 1589581743547) +@@ -109,11 +109,7 @@ // see make/GensrcModuleInfo.gmk exports sun.awt to jdk.accessibility, - jdk.unsupported.desktop, - jcef; - -- exports java.awt.peer to jcef; +- exports sun.lwawt.macosx to jcef; +- exports sun.lwawt to jcef; + jdk.unsupported.desktop; - + exports java.awt.dnd.peer to jdk.unsupported.desktop; exports sun.awt.dnd to jdk.unsupported.desktop; -Index: modules.list -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== ---- modules.list (revision 5ae6630e3ebc71beb9f9df63b1b5bc19c9405d1f) -+++ modules.list (date 1588168285505) -@@ -61,5 +61,4 @@ - jdk.unsupported, - jdk.xml.dom, - jdk.zipfs, --jdk.hotspot.agent, --jcef -+jdk.hotspot.agent diff --git a/jb/project/tools/exclude_jfx_module.patch b/jb/project/tools/exclude_jfx_module.patch deleted file mode 100644 index d5a4cf4aa8f9..000000000000 --- a/jb/project/tools/exclude_jfx_module.patch +++ /dev/null @@ -1,21 +0,0 @@ -Index: modules.list -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== ---- modules.list (revision ab073976c4f85f154ff1421b7ac888eee86b6595) -+++ modules.list (date 1588171510146) -@@ -20,13 +20,6 @@ - java.transaction.xa, - java.xml, - java.xml.crypto, --javafx.base, --javafx.controls, --javafx.fxml, --javafx.graphics, --javafx.media, --javafx.swing, --javafx.web, - jdk.accessibility, - jdk.aot, - jdk.attach, diff --git a/jb/project/tools/linux/scripts/mkbundles_x64.sh b/jb/project/tools/linux/scripts/mkbundles_x64.sh deleted file mode 100755 index d22ed3c785ab..000000000000 --- a/jb/project/tools/linux/scripts/mkbundles_x64.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -x - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -script_dir=jb/project/tools/linux/scripts -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 2498ed1000a4..8e35ad8150dd 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index d088c8ec6108..3089cc6045b7 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -5,8 +5,8 @@ # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build # bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created +# jcef - the bundles with jcef +# empty - the bundles without jcef # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -27,23 +27,14 @@ source jb/project/tools/common.sh function create_jbr { - case "$1" in - "${bundle_type}_lw") - JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} - grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - ;; - "jfx" | "jcef") - JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - ;; - "jfx_jcef") - JBR_BASE_NAME=jbr-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - ;; - *) - echo "***ERR*** bundle was not specified" && exit 1 - ;; - esac + if [ -z "${bundle_type}" ]; then + JBR_BUNDLE=jbr + else + JBR_BUNDLE=jbr_${bundle_type} + fi + JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} + cat modules.list > modules_tmp.list + rm -rf ${BASE_DIR}/jbr rm -rf ${BASE_DIR}/${JBR_BUNDLE} JBR=$JBR_BASE_NAME-linux-x64-b$build_number @@ -53,15 +44,13 @@ function create_jbr { --module-path $JSDK/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE - if [[ "$bundle_type" == *jcef* ]]; then - cp -R $BASE_DIR/$JBR_BUNDLE $BASE_DIR/jbr + if [ ! -z "${bundle_type}" ]; then + cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? fi grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release echo Creating $JBR.tar.gz ... - rm -rf ${BASE_DIR}/jbr - cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $? gzip $JBR.tar || exit $? rm -rf ${BASE_DIR}/${JBR_BUNDLE} @@ -71,14 +60,7 @@ JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION git checkout -- modules.list git checkout -- src/java.desktop/share/classes/module-info.java -case "$bundle_type" in - "jfx") - git apply -p0 < jb/project/tools/exclude_jcef_module.patch - ;; - "jcef") - git apply -p0 < jb/project/tools/exclude_jfx_module.patch - ;; -esac +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch sh configure \ --disable-warnings-as-errors \ @@ -109,25 +91,20 @@ cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? if [[ "$bundle_type" == *jcef* ]]; then cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? fi -if [ "$bundle_type" == "jfx_jcef" ]; then - echo Creating $JBSDK.tar.gz ... - sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release - mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - - tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR $JBRSDK_BUNDLE || exit $? - gzip $JBSDK.tar || exit $? -fi +echo Creating $JBSDK.tar.gz ... +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + +tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ + -C $BASE_DIR $JBRSDK_BUNDLE || exit $? +gzip $JBSDK.tar || exit $? -JBR_BUNDLE=jbr_${bundle_type} -create_jbr ${bundle_type} +create_jbr || exit $? -if [ "$bundle_type" == "jfx_jcef" ]; then - make test-image || exit $? +make test-image || exit $? - JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number +JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number - echo Creating $JBSDK_TEST.tar.gz ... - tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? - gzip $JBRSDK_TEST.tar || exit $? -fi \ No newline at end of file +echo Creating $JBSDK_TEST.tar.gz ... +tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? +gzip $JBRSDK_TEST.tar || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh index aa2a0b6b8b41..5116085eb244 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -39,6 +36,7 @@ sh configure \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ --with-import-modules=./modular-sdk \ + --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? make clean CONF=linux-x86_64-server-fastdebug || exit $? make images CONF=linux-x86_64-server-fastdebug || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index b0e6b689124d..733f42fbeecf 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -37,7 +34,7 @@ linux32 bash configure \ --with-version-pre= \ --with-version-build=$JDK_BUILD_NUMBER \ --with-version-opt=b${build_number} \ - --with-boot-jdk=/jbrsdk-11.0.5-b1 \ + --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? make clean CONF=linux-x86-server-release || exit $? make images CONF=linux-x86-server-release test-image || exit $? diff --git a/jb/project/tools/mac/scripts/mkbundles.sh b/jb/project/tools/mac/scripts/mkbundles.sh deleted file mode 100755 index f8c3fff67d7c..000000000000 --- a/jb/project/tools/mac/scripts/mkbundles.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -x - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -script_dir=jb/project/tools/mac/scripts -${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? -${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index e5606d80d10f..c5428224c6ed 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -5,8 +5,8 @@ # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build # bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created +# jcef - the bundles with jcef +# empty - the bundles without jcef # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -22,28 +22,20 @@ JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +MAJOR_JBSDK_VERSION=$(echo $JBSDK_VERSION_WITH_DOTS | awk -F "." '{print $1}') source jb/project/tools/common.sh function create_jbr { - case "$1" in - "${bundle_type}_lw") - JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} - grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - ;; - "jfx" | "jcef") - JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - ;; - "jfx_jcef") - JBR_BASE_NAME=jbr-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - ;; - *) - echo "***ERR*** bundle was not specified" && exit 1 - ;; - esac + if [ -z "${bundle_type}" ]; then + JBR_BUNDLE=jbr + else + JBR_BUNDLE=jbr_${bundle_type} + fi + JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} + cat modules.list > modules_tmp.list + rm -rf ${BASE_DIR}/jbr rm -rf ${BASE_DIR}/${JBR_BUNDLE} JRE_CONTENTS=${BASE_DIR}/${JBR_BUNDLE}/Contents @@ -55,6 +47,7 @@ function create_jbr { JBR=${JBR_BASE_NAME}-osx-x64-b${build_number} + echo Running jlink.... ${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ --module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || exit $? @@ -62,14 +55,11 @@ function create_jbr { cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS} cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS} - if [[ "${bundle_type}" == *jcef* ]]; then - rm -rf ${JRE_CONTENTS}/Frameworks || exit $? - cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? - fi + rm -rf ${JRE_CONTENTS}/Frameworks || exit $? + [ ! -z "${bundle_type}" ] && (cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?) echo Creating ${JBR}.tar.gz ... - rm -rf ${BASE_DIR}/jbr - cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr + [ ! -z "${bundle_type}" ] && cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $? rm -rf ${BASE_DIR}/${JBR_BUNDLE} } @@ -78,14 +68,7 @@ JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} git checkout -- modules.list git checkout -- src/java.desktop/share/classes/module-info.java -case "$bundle_type" in - "jfx") - git apply -p0 < jb/project/tools/exclude_jcef_module.patch - ;; - "jcef") - git apply -p0 < jb/project/tools/exclude_jfx_module.patch - ;; -esac +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch sh configure \ --disable-warnings-as-errors \ @@ -109,30 +92,25 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR mkdir $BASE_DIR || exit $? -cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? if [[ "$bundle_type" == *jcef* ]]; then cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ fi -if [ "$bundle_type" == "jfx_jcef" ]; then - echo Creating $JBSDK.tar.gz ... - sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release - mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release - COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ - --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ - --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - $JBRSDK_BUNDLE || exit $? -fi +echo Creating $JBSDK.tar.gz ... +sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release +mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release +COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ + --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ + --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ + $JBRSDK_BUNDLE || exit $? -JBR_BUNDLE=jbr_${bundle_type} -create_jbr "${bundle_type}" || exit $? +create_jbr || exit $? -if [ "$bundle_type" == "jfx_jcef" ]; then - make test-image || exit $? +make test-image || exit $? - JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number +JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number - echo Creating $JBRSDK_TEST.tar.gz ... - COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ - --exclude='test/jdk/demos' test || exit $? -fi \ No newline at end of file +echo Creating $JBRSDK_TEST.tar.gz ... +COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ + --exclude='test/jdk/demos' test || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh index 42053166104d..a0a9af086552 100755 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -22,6 +19,7 @@ JDK_BUILD_NUMBER=$2 build_number=$3 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +MAJOR_JBSDK_VERSION=$(echo $JBSDK_VERSION_WITH_DOTS | awk -F "." '{print $1}') source jb/project/tools/common.sh @@ -51,8 +49,7 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR mkdir $BASE_DIR || exit $? -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? echo Creating $JBSDK.tar.gz ... cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ diff --git a/jb/project/tools/windows/scripts/mkbundles_x64.sh b/jb/project/tools/windows/scripts/mkbundles_x64.sh deleted file mode 100755 index 38704d02399f..000000000000 --- a/jb/project/tools/windows/scripts/mkbundles_x64.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -x - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -script_dir=jb/project/tools/windows/scripts -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $? -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $? -${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 77e6dd106a43..ca6c452e3149 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -5,8 +5,8 @@ # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build # bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created +# jcef - the bundles with jcef +# empty - the bundles without jcef # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -27,26 +27,20 @@ source jb/project/tools/common.sh function create_jbr { - case "$1" in - "${bundle_type}_lw") - grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list - ;; - "jfx" | "jcef" | "jfx_jcef") - cat modules.list > modules_tmp.list - ;; - *) - echo "***ERR*** bundle was not specified" && exit 1 - ;; - esac + if [ -z "${bundle_type}" ]; then + JBR_BUNDLE=jbr + else + JBR_BUNDLE=jbr_${bundle_type} + fi + cat modules.list > modules_tmp.list rm -rf ${JBR_BUNDLE} + echo Running jlink.... ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? - if [[ "${bundle_type}" == *jcef* ]] - then - cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin - fi + + [ ! -z "${bundle_type}" ] && (cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin || exit $?) echo Modifying release info ... cat ${JSDK}/release | tr -d '\r' | grep -v 'JAVA_VERSION' | grep -v 'MODULES' >> ${JBR_BUNDLE}/release } @@ -56,19 +50,10 @@ WORK_DIR=$(pwd) git checkout -- modules.list git checkout -- src/java.desktop/share/classes/module-info.java -case "$bundle_type" in - "jfx") - echo "Excluding jcef modules" - git apply -p0 < jb/project/tools/exclude_jcef_module.patch - ;; - "jcef") - echo "Excluding jfx modules" - git apply -p0 < jb/project/tools/exclude_jfx_module.patch - ;; -esac +[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch PATH="/usr/local/bin:/usr/bin:${PATH}" -./configure \ +sh ./configure \ --disable-warnings-as-errors \ --with-target-bits=64 \ --with-vendor-name="${VENDOR_NAME}" \ @@ -82,16 +67,10 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --disable-ccache \ --enable-cds=yes || exit 1 -if [ "$bundle_type" == "jfx_jcef" ]; then - make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1 -else - make LOG=info images CONF=windows-x86_64-server-release || exit 1 -fi +make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1 JSDK=build/windows-x86_64-server-release/images/jdk -if [[ "$bundle_type" == *jcef* ]]; then - JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} -fi +JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} BASE_DIR=build/windows-x86_64-server-release/images JBRSDK_BUNDLE=jbrsdk @@ -100,8 +79,4 @@ cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin sed 's/JBR/JBRSDK/g' ${JSDK}/release > release mv release ${JBRSDK_BUNDLE}/release -JBR_BUNDLE=jbr_${bundle_type} -create_jbr ${bundle_type} - -#JBR_BUNDLE=jbr_${bundle_type}_lw -#create_jbr ${bundle_type}_lw +create_jbr || exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index e93359abe4f4..904867f7ea85 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -33,7 +33,6 @@ WORK_DIR=$(pwd) PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ --disable-warnings-as-errors \ - --with-native-debug-symbols=none \ --with-target-bits=32 \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 7677cbcbaf4c..e701ff354198 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -4,9 +4,8 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created +# jcef - the bundles with jcef +# empty - the bundles without jcef # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -24,28 +23,19 @@ bundle_type=$4 function pack_jbr { - case "$1" in - "${bundle_type}_lw") - JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION} - ;; - "jfx" | "jcef") - JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION} - ;; - "jfx_jcef") - JBR_BASE_NAME=jbr-${JBSDK_VERSION} - ;; - *) - echo "***ERR*** bundle was not specified" && exit 1 - ;; - esac + if [ -z "${bundle_type}" ]; then + JBR_BUNDLE=jbr + else + JBR_BUNDLE=jbr_${bundle_type} + rm -rf ${BASE_DIR}/jbr + cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr + fi + JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} JBR=$JBR_BASE_NAME-windows-x64-b$build_number echo Creating $JBR.tar.gz ... - rm -rf ${BASE_DIR}/jbr - cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1 - #rm -rf ${BASE_DIR}/${JBR_BUNDLE} } JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION @@ -56,17 +46,12 @@ JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. -if [ "$bundle_type" == "jfx_jcef" ]; then - JBRSDK_BUNDLE=jbrsdk - echo Creating $JBSDK.tar.gz ... - /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 -fi +JBRSDK_BUNDLE=jbrsdk +echo Creating $JBSDK.tar.gz ... +/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 -JBR_BUNDLE=jbr_${bundle_type} pack_jbr $bundle_type -if [ "$bundle_type" == "jfx_jcef" ]; then - JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number - echo Creating $JBRSDK_TEST.tar.gz ... - /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 -fi \ No newline at end of file +JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number +echo Creating $JBRSDK_TEST.tar.gz ... +/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 diff --git a/modules.list b/modules.list index 6dd7546add45..75c66fab3060 100644 --- a/modules.list +++ b/modules.list @@ -20,13 +20,6 @@ java.sql.rowset, java.transaction.xa, java.xml, java.xml.crypto, -javafx.base, -javafx.controls, -javafx.fxml, -javafx.graphics, -javafx.media, -javafx.swing, -javafx.web, jdk.accessibility, jdk.aot, jdk.attach, From d3f3036094d28a0eccf3e09e96cbf7d5cbd26653 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 10 Jun 2020 10:07:07 +0700 Subject: [PATCH 029/976] JBR-2473 modify building scripts to add dcevm clauses, add git config to docker image (cherry picked from commit 2620c62848a2f58e7f957dcb1ed9764ef27ddc80) --- .../tools/linux/scripts/mkimages_aarch64.sh | 2 +- .../tools/linux/scripts/mkimages_x64.sh | 36 ++++++++++--------- .../tools/linux/scripts/mkimages_x64_fd.sh | 2 +- .../tools/linux/scripts/mkimages_x86.sh | 2 +- jb/project/tools/mac/scripts/mkimages.sh | 36 ++++++++++--------- jb/project/tools/mac/scripts/mkimages_fd.sh | 2 +- .../{ => patches}/exclude_jcef_module.patch | 15 ++++---- .../tools/windows/scripts/mkimages_x64.sh | 16 ++++++--- .../tools/windows/scripts/mkimages_x86.sh | 2 +- jb/project/tools/windows/scripts/pack_x64.sh | 16 +++++---- 10 files changed, 73 insertions(+), 56 deletions(-) rename jb/project/tools/{ => patches}/exclude_jcef_module.patch (66%) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 8e35ad8150dd..348038f514d7 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -24,7 +24,7 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ --disable-warnings-as-errors \ diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 3089cc6045b7..44521cda9da5 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -58,9 +58,9 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -git checkout -- modules.list -git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +#git checkout -- modules.list +#git checkout -- src/java.desktop/share/classes/module-info.java +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ --disable-warnings-as-errors \ @@ -88,23 +88,27 @@ JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? -if [[ "$bundle_type" == *jcef* ]]; then +if [ ! -z "$bundle_type" ]; then cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? fi -echo Creating $JBSDK.tar.gz ... -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - -tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR $JBRSDK_BUNDLE || exit $? -gzip $JBSDK.tar || exit $? +if [ "$bundle_type" == "jcef" ]; then + echo Creating $JBSDK.tar.gz ... + sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release + mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release + + tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ + -C $BASE_DIR $JBRSDK_BUNDLE || exit $? + gzip $JBSDK.tar || exit $? +fi create_jbr || exit $? -make test-image || exit $? +if [ "$bundle_type" == "jcef" ]; then + make test-image || exit $? -JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number + JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number -echo Creating $JBSDK_TEST.tar.gz ... -tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? + echo Creating $JBSDK_TEST.tar.gz ... + tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? + gzip $JBRSDK_TEST.tar || exit $? +fi diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh index 5116085eb244..75b9c15addcb 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh @@ -25,7 +25,7 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ --disable-warnings-as-errors \ diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 733f42fbeecf..3788a2515fe5 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -24,7 +24,7 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) linux32 bash configure \ --disable-warnings-as-errors \ diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index c5428224c6ed..9cb132d5193a 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -66,9 +66,9 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -git checkout -- modules.list -git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +#git checkout -- modules.list +#git checkout -- src/java.desktop/share/classes/module-info.java +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ --disable-warnings-as-errors \ @@ -94,23 +94,27 @@ rm -rf $BASE_DIR mkdir $BASE_DIR || exit $? cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? -if [[ "$bundle_type" == *jcef* ]]; then +if [[ ! -z "$bundle_type" ]]; then cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ fi -echo Creating $JBSDK.tar.gz ... -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release -COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ - --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ - --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - $JBRSDK_BUNDLE || exit $? +if [ "$bundle_type" == "jcef" ]; then + echo Creating $JBSDK.tar.gz ... + sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release + mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release + COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ + --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ + --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ + $JBRSDK_BUNDLE || exit $? +fi create_jbr || exit $? -make test-image || exit $? +if [ "$bundle_type" == "jcef" ]; then + make test-image || exit $? -JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number + JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ - --exclude='test/jdk/demos' test || exit $? + echo Creating $JBRSDK_TEST.tar.gz ... + COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ + --exclude='test/jdk/demos' test || exit $? +fi \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh index a0a9af086552..4e0b2ec3c24d 100755 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ b/jb/project/tools/mac/scripts/mkimages_fd.sh @@ -25,7 +25,7 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ --disable-warnings-as-errors \ diff --git a/jb/project/tools/exclude_jcef_module.patch b/jb/project/tools/patches/exclude_jcef_module.patch similarity index 66% rename from jb/project/tools/exclude_jcef_module.patch rename to jb/project/tools/patches/exclude_jcef_module.patch index 43274c19588a..d9e9c2afdcde 100644 --- a/jb/project/tools/exclude_jcef_module.patch +++ b/jb/project/tools/patches/exclude_jcef_module.patch @@ -3,9 +3,9 @@ IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- modules.list (revision a73d4ecbefe65fd6d79b78663d916ff71b5346f7) -+++ modules.list (date 1589581743550) -@@ -54,5 +54,4 @@ +--- modules.list (revision 834c441b0f9d1a705a77f67768fa5e0411067b12) ++++ modules.list (date 1596011136827) +@@ -53,5 +53,4 @@ jdk.unsupported, jdk.xml.dom, jdk.zipfs, @@ -17,17 +17,16 @@ IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== ---- src/java.desktop/share/classes/module-info.java (revision a73d4ecbefe65fd6d79b78663d916ff71b5346f7) -+++ src/java.desktop/share/classes/module-info.java (date 1589581743547) -@@ -109,11 +109,7 @@ +--- src/java.desktop/share/classes/module-info.java (revision 834c441b0f9d1a705a77f67768fa5e0411067b12) ++++ src/java.desktop/share/classes/module-info.java (date 1596011136835) +@@ -109,10 +109,7 @@ // see make/GensrcModuleInfo.gmk exports sun.awt to jdk.accessibility, - jdk.unsupported.desktop, - jcef; - -- exports sun.lwawt.macosx to jcef; -- exports sun.lwawt to jcef; +- exports java.awt.peer to jcef; + jdk.unsupported.desktop; exports java.awt.dnd.peer to jdk.unsupported.desktop; diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index ca6c452e3149..43c2297b5e15 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -48,9 +48,9 @@ function create_jbr { JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -git checkout -- modules.list -git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +#git checkout -- modules.list +#git checkout -- src/java.desktop/share/classes/module-info.java +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) PATH="/usr/local/bin:/usr/bin:${PATH}" sh ./configure \ @@ -67,10 +67,16 @@ sh ./configure \ --disable-ccache \ --enable-cds=yes || exit 1 -make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1 +if [ "$bundle_type" == "jcef" ]; then + make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1else +fi + + JSDK=build/windows-x86_64-server-release/images/jdk -JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} +if [[ "$bundle_type" == "jcef" ]]; then + JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} +fi BASE_DIR=build/windows-x86_64-server-release/images JBRSDK_BUNDLE=jbrsdk diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 904867f7ea85..14378ff41551 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -28,7 +28,7 @@ source jb/project/tools/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -[ -z "$bundle_type" ] && git apply -p0 < jb/project/tools/exclude_jcef_module.patch +[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index e701ff354198..8f911aa22f60 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -46,12 +46,16 @@ JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. -JBRSDK_BUNDLE=jbrsdk -echo Creating $JBSDK.tar.gz ... -/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 +if [ "$bundle_type" == "jcef" ]; then + JBRSDK_BUNDLE=jbrsdk + echo Creating $JBSDK.tar.gz ... + /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 +fi pack_jbr $bundle_type -JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 +if [ "$bundle_type" == "jcef" ]; then + JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number + echo Creating $JBRSDK_TEST.tar.gz ... + /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 +fi \ No newline at end of file From d4113ecf88fc3e4b4b534044f7a9dc7d4e7419ca Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 13 Dec 2019 15:13:12 +0300 Subject: [PATCH 030/976] JBR-2016 add jcef module and export packages to it (cherry picked from commit cf997f71c6a4e6568cf17d587743e6e38ca46010) --- src/java.desktop/share/classes/module-info.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java index ff39372d4428..442fa00c44a0 100644 --- a/src/java.desktop/share/classes/module-info.java +++ b/src/java.desktop/share/classes/module-info.java @@ -119,8 +119,7 @@ jdk.unsupported.desktop, jcef; - exports sun.lwawt.macosx to jcef; - exports sun.lwawt to jcef; + exports java.awt.peer to jcef; exports java.awt.dnd.peer to jdk.unsupported.desktop; exports sun.awt.dnd to jdk.unsupported.desktop; From f4ed47fdc95b8de4ba08a6a2d6838d49945d19ee Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 2 Oct 2020 06:29:44 +0700 Subject: [PATCH 031/976] JBR-2758 refactor building scripts to apply patches adding required modules instead of excluding Add jogl and gluegen modules to support jcef osr mode --- jb/project/tools/common.sh | 7 ++ .../tools/linux/scripts/mkimages_x64.sh | 89 ++++++++++++------- .../tools/linux/scripts/mkimages_x64_fd.sh | 82 ----------------- jb/project/tools/mac/scripts/mkimages.sh | 88 +++++++++++------- jb/project/tools/mac/scripts/mkimages_fd.sh | 89 ------------------- .../tools/patches/add_jcef_module.patch | 30 +++++++ .../tools/patches/exclude_jcef_module.patch | 33 ------- .../tools/windows/scripts/mkimages_x64.sh | 79 ++++++++++------ .../tools/windows/scripts/mkimages_x86.sh | 3 - jb/project/tools/windows/scripts/pack_x64.sh | 32 +++++-- jb/project/tools/windows/scripts/pack_x86.sh | 3 - modules.list | 3 +- .../share/classes/module-info.java | 5 +- 13 files changed, 229 insertions(+), 314 deletions(-) delete mode 100755 jb/project/tools/linux/scripts/mkimages_x64_fd.sh delete mode 100755 jb/project/tools/mac/scripts/mkimages_fd.sh create mode 100644 jb/project/tools/patches/add_jcef_module.patch delete mode 100644 jb/project/tools/patches/exclude_jcef_module.patch diff --git a/jb/project/tools/common.sh b/jb/project/tools/common.sh index 9a9ebe7f7d7d..245b10956638 100644 --- a/jb/project/tools/common.sh +++ b/jb/project/tools/common.sh @@ -1,3 +1,10 @@ VENDOR_NAME="JetBrains s.r.o." VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}" [ -z ${bundle_type} ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" + +do_reset_changes=0 +function do_exit() { + exit_code=$1 + [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + exit $exit_code +} diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 44521cda9da5..956792df513e 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -1,12 +1,13 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles with jcef -# empty - the bundles without jcef +# bundle_type - specifies bundle to be built; possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -16,12 +17,19 @@ # OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # +# Environment variables: +# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. +# By default imported modules should be located in ./modular-sdk +# JCEF_PATH - specifies the path to the directory with JCEF binaries. +# By default JCEF binaries should be located in ./jcef_linux_x64 JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" +JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64} source jb/project/tools/common.sh @@ -46,69 +54,88 @@ function create_jbr { if [ ! -z "${bundle_type}" ]; then cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? + cp -R ${JCEF_PATH}/* $BASE_DIR/$JBR_BUNDLE/lib || do_exit $? fi grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release echo Creating $JBR.tar.gz ... - tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $? - gzip $JBR.tar || exit $? + tar -pcf $JBR.tar -C $BASE_DIR jbr || do_exit $? + [ -f "$JBR.tar.gz" ] && rm "$JBR.tar.gz" + gzip $JBR.tar || do_exit $? rm -rf ${BASE_DIR}/${JBR_BUNDLE} } -JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION - -#git checkout -- modules.list -#git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) +JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=linux-x86_64-server-release +JBSDK=${JBRSDK_BASE_NAME}-linux-x64-b${build_number} +case "$bundle_type" in + "jcef") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch + do_reset_changes=1 + ;; + "nomod" | "") + bundle_type="" + WITH_IMPORT_MODULES="" + ;; + "fd") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch + do_reset_changes=1 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=linux-x86_64-server-fastdebug + JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number} + ;; +esac sh configure \ --disable-warnings-as-errors \ - --with-debug-level=release \ + $WITH_DEBUG_LEVEL \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ - --with-import-modules=./modular-sdk \ + $WITH_IMPORT_MODULES \ --with-boot-jdk=${BOOT_JDK} \ - --enable-cds=yes || exit $? + --enable-cds=yes || do_exit $? -make images CONF=linux-x86_64-server-release || exit $? +make clean CONF=$RELEASE_NAME || exit $? +make images CONF=$RELEASE_NAME || do_exit $? -JSDK=build/linux-x86_64-server-release/images/jdk -JBSDK=$JBRSDK_BASE_NAME-linux-x64-b$build_number +JSDK=build/$RELEASE_NAME/images/jdk echo Fixing permissions chmod -R a+r $JSDK -BASE_DIR=build/linux-x86_64-server-release/images +BASE_DIR=build/$RELEASE_NAME/images JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR/$JBRSDK_BUNDLE -cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? +cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || do_exit $? -if [ ! -z "$bundle_type" ]; then - cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? -fi -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + cp -R ${JCEF_PATH}/* $BASE_DIR/$JBRSDK_BUNDLE/lib || do_exit $? echo Creating $JBSDK.tar.gz ... sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR $JBRSDK_BUNDLE || exit $? - gzip $JBSDK.tar || exit $? + -C $BASE_DIR $JBRSDK_BUNDLE || do_exit $? + [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" + gzip $JBSDK.tar || do_exit $? fi -create_jbr || exit $? +create_jbr || do_exit $? if [ "$bundle_type" == "jcef" ]; then - make test-image || exit $? + make test-image CONF=$RELEASE_NAME || do_exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number echo Creating $JBSDK_TEST.tar.gz ... - tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? - gzip $JBRSDK_TEST.tar || exit $? + tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || do_exit $? + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + gzip $JBRSDK_TEST.tar || do_exit $? fi + +do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh b/jb/project/tools/linux/scripts/mkimages_x64_fd.sh deleted file mode 100755 index 75b9c15addcb..000000000000 --- a/jb/project/tools/linux/scripts/mkimages_x64_fd.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -x - -# The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) -# - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') - -source jb/project/tools/common.sh - - -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} - -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - -sh configure \ - --disable-warnings-as-errors \ - --with-debug-level=fastdebug \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ - --with-version-opt=b${build_number} \ - --with-import-modules=./modular-sdk \ - --with-boot-jdk=${BOOT_JDK} \ - --enable-cds=yes || exit $? -make clean CONF=linux-x86_64-server-fastdebug || exit $? -make images CONF=linux-x86_64-server-fastdebug || exit $? - -JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number} -BASE_DIR=build/linux-x86_64-server-fastdebug/images -JSDK=${BASE_DIR}/jdk -JBRSDK_BUNDLE=jbrsdk - -echo Fixing permissions -chmod -R a+r $JSDK - -rm -rf $BASE_DIR/$JBRSDK_BUNDLE -cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? -cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $? - -echo Creating $JBSDK.tar.gz ... -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - -tar -pcf $JBSDK.tar \ - --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? -gzip $JBSDK.tar || exit $? - -JBR_BUNDLE=jbr -JBR_BASE_NAME=jbr-$JBSDK_VERSION -rm -rf $BASE_DIR/$JBR_BUNDLE - -JBR=$JBR_BASE_NAME-linux-x64-fastdebug-b$build_number -echo Running jlink.... -${JSDK}/bin/jlink \ - --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list | sed s/" "//g | sed s/,$//g) \ - --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? -cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $? - -echo Modifying release info ... -grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release - -echo Creating $JBR.tar.gz ... -tar -czf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? -gzip $JBR.tar || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 9cb132d5193a..55f026c8d79a 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -1,12 +1,13 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles with jcef -# empty - the bundles without jcef +# bundle_type - specifies bundle to be built; possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -16,12 +17,19 @@ # OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # +# Environment variables: +# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. +# By default imported modules should be located in ./modular-sdk +# JCEF_PATH - specifies the path to the directory with JCEF binaries. +# By default JCEF binaries should be located in ./jcef_mac JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" +JCEF_PATH=${JCEF_PATH:=./jcef_mac} MAJOR_JBSDK_VERSION=$(echo $JBSDK_VERSION_WITH_DOTS | awk -F "." '{print $1}') source jb/project/tools/common.sh @@ -50,71 +58,89 @@ function create_jbr { echo Running jlink.... ${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ --module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || exit $? + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || do_exit $? grep -v "^JAVA_VERSION" ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release | grep -v "^MODULES" >> ${JRE_HOME}/release cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS} cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS} - rm -rf ${JRE_CONTENTS}/Frameworks || exit $? - [ ! -z "${bundle_type}" ] && (cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?) + rm -rf ${JRE_CONTENTS}/Frameworks || do_exit $? + [ ! -z "${bundle_type}" ] && (cp -a ${JCEF_PATH}/Frameworks ${JRE_CONTENTS} || do_exit $?) echo Creating ${JBR}.tar.gz ... [ ! -z "${bundle_type}" ] && cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $? + COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || do_exit $? rm -rf ${BASE_DIR}/${JBR_BUNDLE} } JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} - -#git checkout -- modules.list -#git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=macosx-x86_64-server-release +JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} +case "$bundle_type" in + "jcef") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + do_reset_changes=1 + ;; + "nomod" | "") + bundle_type="" + WITH_IMPORT_MODULES="" + ;; + "fd") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + do_reset_changes=1 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=macosx-x86_64-server-fastdebug + JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} + ;; +esac sh configure \ --disable-warnings-as-errors \ - --with-debug-level=release \ + $WITH_DEBUG_LEVEL \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ - --with-import-modules=./modular-sdk \ + $WITH_IMPORT_MODULES \ --with-boot-jdk=`/usr/libexec/java_home -v 14` \ - --enable-cds=yes || exit $? + --enable-cds=yes || do_exit $? -make images CONF=macosx-x86_64-server-release || exit $? +make clean CONF=$RELEASE_NAME || do_exit $? +make images CONF=$RELEASE_NAME || do_exit $? -JSDK=build/macosx-x86_64-server-release/images/jdk-bundle -JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} +JSDK=build/$RELEASE_NAME/images/jdk-bundle BASE_DIR=jre JBRSDK_BUNDLE=jbrsdk rm -rf $BASE_DIR -mkdir $BASE_DIR || exit $? -cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? +mkdir $BASE_DIR || do_exit $? +cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || do_exit $? -if [[ ! -z "$bundle_type" ]]; then - cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ -fi -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + cp -a ${JCEF_PATH}/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ echo Creating $JBSDK.tar.gz ... sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release + [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - $JBRSDK_BUNDLE || exit $? + $JBRSDK_BUNDLE || do_exit $? fi -create_jbr || exit $? +create_jbr || do_exit $? if [ "$bundle_type" == "jcef" ]; then - make test-image || exit $? + make test-image CONF=$RELEASE_NAME || do_exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... - COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \ - --exclude='test/jdk/demos' test || exit $? -fi \ No newline at end of file + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/${RELEASE_NAME}/images \ + --exclude='test/jdk/demos' test || do_exit $? +fi + +do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/mac/scripts/mkimages_fd.sh b/jb/project/tools/mac/scripts/mkimages_fd.sh deleted file mode 100755 index 4e0b2ec3c24d..000000000000 --- a/jb/project/tools/mac/scripts/mkimages_fd.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -x - -# The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) -# - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -MAJOR_JBSDK_VERSION=$(echo $JBSDK_VERSION_WITH_DOTS | awk -F "." '{print $1}') - -source jb/project/tools/common.sh - -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} - -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - -sh configure \ - --disable-warnings-as-errors \ - --with-debug-level=fastdebug \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ - --with-version-opt=b${build_number} \ - --with-import-modules=./modular-sdk \ - --with-boot-jdk=`/usr/libexec/java_home -v 14` \ - --enable-cds=yes || exit $? -make clean CONF=macosx-x86_64-server-fastdebug || exit $? -make images CONF=macosx-x86_64-server-fastdebug || exit $? - -JSDK=build/macosx-x86_64-server-fastdebug/images/jdk-bundle -JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} - -BASE_DIR=jre -JBRSDK_BUNDLE=jbrsdk - -rm -rf $BASE_DIR -mkdir $BASE_DIR || exit $? -cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $? - -echo Creating $JBSDK.tar.gz ... -cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ - -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release - -COPYFILE_DISABLE=1 \ - tar -pczf ${JBSDK}.tar.gz -C ${BASE_DIR} \ - --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ - --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - ${JBRSDK_BUNDLE} || exit $? - -JBR_BUNDLE=jbr -JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents -JRE_HOME=$JRE_CONTENTS/Home - JBR_BASE_NAME=jbr-$JBSDK_VERSION - -mkdir -p $JRE_CONTENTS - -if [ -d "$JRE_HOME" ]; then - rm -rf $JRE_HOME -fi - -JBR=${JBR_BASE_NAME}-osx-x64-fastdebug-b${build_number} - -$BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ - --module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list | sed s/" "//g) --output $JRE_HOME || exit $? -grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release -cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS -cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS -cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $? - - -echo Creating $JBR.tar.gz ... -COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $? diff --git a/jb/project/tools/patches/add_jcef_module.patch b/jb/project/tools/patches/add_jcef_module.patch new file mode 100644 index 000000000000..6a793bc64987 --- /dev/null +++ b/jb/project/tools/patches/add_jcef_module.patch @@ -0,0 +1,30 @@ +diff --git modules.list modules.list +index 7c4b3e9cb6d..5ed60349ca7 100644 +--- modules.list ++++ modules.list +@@ -53,4 +53,7 @@ jdk.security.jgss, + jdk.unsupported, + jdk.xml.dom, + jdk.zipfs, +-jdk.hotspot.agent ++jdk.hotspot.agent, ++jcef, ++gluegen.rt, ++jogl.all +diff --git src/java.desktop/share/classes/module-info.java src/java.desktop/share/classes/module-info.java +index b663b382f52..3e9acdc0c27 100644 +--- src/java.desktop/share/classes/module-info.java ++++ src/java.desktop/share/classes/module-info.java +@@ -109,7 +109,11 @@ module java.desktop { + // see make/GensrcModuleInfo.gmk + exports sun.awt to + jdk.accessibility, +- jdk.unsupported.desktop; ++ jdk.unsupported.desktop, ++ jcef, ++ jogl.all; ++ ++ exports java.awt.peer to jcef; + + exports java.awt.dnd.peer to jdk.unsupported.desktop; + exports sun.awt.dnd to jdk.unsupported.desktop; diff --git a/jb/project/tools/patches/exclude_jcef_module.patch b/jb/project/tools/patches/exclude_jcef_module.patch deleted file mode 100644 index d9e9c2afdcde..000000000000 --- a/jb/project/tools/patches/exclude_jcef_module.patch +++ /dev/null @@ -1,33 +0,0 @@ -Index: modules.list -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== ---- modules.list (revision 834c441b0f9d1a705a77f67768fa5e0411067b12) -+++ modules.list (date 1596011136827) -@@ -53,5 +53,4 @@ - jdk.unsupported, - jdk.xml.dom, - jdk.zipfs, --jdk.hotspot.agent, --jcef -+jdk.hotspot.agent -Index: src/java.desktop/share/classes/module-info.java -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== ---- src/java.desktop/share/classes/module-info.java (revision 834c441b0f9d1a705a77f67768fa5e0411067b12) -+++ src/java.desktop/share/classes/module-info.java (date 1596011136835) -@@ -109,10 +109,7 @@ - // see make/GensrcModuleInfo.gmk - exports sun.awt to - jdk.accessibility, -- jdk.unsupported.desktop, -- jcef; -- -- exports java.awt.peer to jcef; -+ jdk.unsupported.desktop; - - exports java.awt.dnd.peer to jdk.unsupported.desktop; - exports sun.awt.dnd to jdk.unsupported.desktop; diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 43c2297b5e15..0142d079c411 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -1,12 +1,13 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles with jcef -# empty - the bundles without jcef +# bundle_type - specifies bundle to be built; possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -16,12 +17,20 @@ # OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # +# Environment variables: +# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. +# By default imported modules should be located in ./modular-sdk +# JCEF_PATH - specifies the path to the directory with JCEF binaries. +# By default JCEF binaries should be located in ./jcef_win_x64 JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +WORK_DIR=$(pwd) +WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=$WORK_DIR/modular-sdk}" +JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64} source jb/project/tools/common.sh @@ -38,51 +47,67 @@ function create_jbr { echo Running jlink.... ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? + --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || do_exit $? - [ ! -z "${bundle_type}" ] && (cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin || exit $?) + [ ! -z "${bundle_type}" ] && (cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin || do_exit $?) echo Modifying release info ... cat ${JSDK}/release | tr -d '\r' | grep -v 'JAVA_VERSION' | grep -v 'MODULES' >> ${JBR_BUNDLE}/release } JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -WORK_DIR=$(pwd) +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=windows-x86_64-server-release +JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} +case "$bundle_type" in + "jcef") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + do_reset_changes=1 + ;; + "nomod" | "") + bundle_type="" + WITH_IMPORT_MODULES="" + ;; + "fd") + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + do_reset_changes=1 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=windows-x86_64-server-fastdebug + JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} + ;; +esac -#git checkout -- modules.list -#git checkout -- src/java.desktop/share/classes/module-info.java -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - -PATH="/usr/local/bin:/usr/bin:${PATH}" sh ./configure \ --disable-warnings-as-errors \ - --with-target-bits=64 \ + $WITH_DEBUG_LEVEL \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ + $WITH_IMPORT_MODULES \ --with-toolchain-version=${TOOLCHAIN_VERSION} \ - --with-import-modules=${WORK_DIR}/modular-sdk \ --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ - --enable-cds=yes || exit 1 + --enable-cds=yes || do_exit $? if [ "$bundle_type" == "jcef" ]; then - make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1else + make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? +else + make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? fi +JSDK=build/$RELEASE_NAME/images/jdk - -JSDK=build/windows-x86_64-server-release/images/jdk -if [[ "$bundle_type" == "jcef" ]]; then - JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number} -fi -BASE_DIR=build/windows-x86_64-server-release/images +BASE_DIR=build/$RELEASE_NAME/images JBRSDK_BUNDLE=jbrsdk -rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 -cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin -sed 's/JBR/JBRSDK/g' ${JSDK}/release > release -mv release ${JBRSDK_BUNDLE}/release +rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin + sed 's/JBR/JBRSDK/g' ${JSDK}/release > release + mv release ${JBRSDK_BUNDLE}/release +fi create_jbr || exit $? + +do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 14378ff41551..88929a77dea2 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 8f911aa22f60..92bc2dedc79a 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -1,11 +1,13 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure +# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) +# JDK_BUILD_NUMBER - specifies udate release of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built; possible values: +# or nomod - the bundles without any additional modules (jcef) # jcef - the bundles with jcef -# empty - the bundles without jcef +# fd - the fastdebug bundles which also include the jcef module # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz @@ -27,7 +29,7 @@ function pack_jbr { JBR_BUNDLE=jbr else JBR_BUNDLE=jbr_${bundle_type} - rm -rf ${BASE_DIR}/jbr + [ -d ${BASE_DIR}/jbr ] && rm -rf ${BASE_DIR}/jbr cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr fi JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} @@ -35,21 +37,33 @@ function pack_jbr { JBR=$JBR_BASE_NAME-windows-x64-b$build_number echo Creating $JBR.tar.gz ... - /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1 + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || do_exit $? } JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION JBR_BASE_NAME=jbr-$JBSDK_VERSION +RELEASE_NAME=windows-x86_64-server-release +JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} +case "$bundle_type" in + "nomod" | "") + bundle_type="" + ;; + "fd") + RELEASE_NAME=macosx-x86_64-server-fastdebug + JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} + ;; +esac -IMAGES_DIR=build/windows-x86_64-server-release/images +IMAGES_DIR=build/$RELEASE_NAME/images JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. -if [ "$bundle_type" == "jcef" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then JBRSDK_BUNDLE=jbrsdk echo Creating $JBSDK.tar.gz ... - /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 + [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" + /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || do_exit $? fi pack_jbr $bundle_type @@ -57,5 +71,5 @@ pack_jbr $bundle_type if [ "$bundle_type" == "jcef" ]; then JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... - /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 + /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? fi \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index c254d53cf6e9..8ce91b09347e 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -4,9 +4,6 @@ # JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 # JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure # build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to bu built; possible values: -# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created -# jfx - the bundle 1) jbr with javafx only will be created # # jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz # jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz diff --git a/modules.list b/modules.list index 75c66fab3060..e23d793ca612 100644 --- a/modules.list +++ b/modules.list @@ -54,5 +54,4 @@ jdk.security.jgss, jdk.unsupported, jdk.xml.dom, jdk.zipfs, -jdk.hotspot.agent, -jcef +jdk.hotspot.agent diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java index 442fa00c44a0..897647ee3689 100644 --- a/src/java.desktop/share/classes/module-info.java +++ b/src/java.desktop/share/classes/module-info.java @@ -116,10 +116,7 @@ // see make/GensrcModuleInfo.gmk exports sun.awt to jdk.accessibility, - jdk.unsupported.desktop, - jcef; - - exports java.awt.peer to jcef; + jdk.unsupported.desktop; exports java.awt.dnd.peer to jdk.unsupported.desktop; exports sun.awt.dnd to jdk.unsupported.desktop; From c96430a4f2aaa22fbae7ed1fa1a22b88559bc2f0 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 16 Oct 2020 05:10:58 +0700 Subject: [PATCH 032/976] JBR-2787 fix copying jcef files into jbr/jbrsdk binaries --- jb/project/tools/linux/scripts/mkimages_x64.sh | 4 ++-- jb/project/tools/windows/scripts/mkimages_x64.sh | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 956792df513e..afa8baeb6f11 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -54,7 +54,7 @@ function create_jbr { if [ ! -z "${bundle_type}" ]; then cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - cp -R ${JCEF_PATH}/* $BASE_DIR/$JBR_BUNDLE/lib || do_exit $? + rsync -av ${JCEF_PATH}/ $BASE_DIR/$JBR_BUNDLE/lib --exclude="modular-sdk" || do_exit $? fi grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release @@ -114,7 +114,7 @@ rm -rf $BASE_DIR/$JBRSDK_BUNDLE cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || do_exit $? if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then - cp -R ${JCEF_PATH}/* $BASE_DIR/$JBRSDK_BUNDLE/lib || do_exit $? + rsync -av ${JCEF_PATH}/ $BASE_DIR/$JBRSDK_BUNDLE/lib --exclude="modular-sdk" || do_exit $? echo Creating $JBSDK.tar.gz ... sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 0142d079c411..928c2d0a4ac3 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -49,7 +49,7 @@ function create_jbr { --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || do_exit $? - [ ! -z "${bundle_type}" ] && (cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin || do_exit $?) + [ ! -z "${bundle_type}" ] && (rsync -av ${JCEF_PATH}/ ${JBR_BUNDLE}/bin --exclude="modular-sdk" || do_exit $?) echo Modifying release info ... cat ${JSDK}/release | tr -d '\r' | grep -v 'JAVA_VERSION' | grep -v 'MODULES' >> ${JBR_BUNDLE}/release } @@ -97,17 +97,16 @@ else fi JSDK=build/$RELEASE_NAME/images/jdk - BASE_DIR=build/$RELEASE_NAME/images JBRSDK_BUNDLE=jbrsdk rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || do_exit $? if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then - cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin + rsync -av ${JCEF_PATH}/ ${JBRSDK_BUNDLE}/bin --exclude='modular-sdk' || do_exit $? sed 's/JBR/JBRSDK/g' ${JSDK}/release > release mv release ${JBRSDK_BUNDLE}/release fi -create_jbr || exit $? +create_jbr || do_exit $? do_exit 0 \ No newline at end of file From 1d5baed26ee703ae7fc62b0ce0f720c6502d17a0 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Sat, 17 Oct 2020 00:59:36 +0300 Subject: [PATCH 033/976] JBR-2812 bundle jcef in jmod format instead of modular-sdk Build test-image with non-jcef build target --- jb/project/tools/common.sh | 10 -- jb/project/tools/common/scripts/common.sh | 49 ++++++ .../tools/linux/scripts/mkimages_aarch64.sh | 2 +- .../tools/linux/scripts/mkimages_x64.sh | 120 +++++++-------- .../tools/linux/scripts/mkimages_x86.sh | 2 +- jb/project/tools/mac/scripts/mkimages.sh | 144 ++++++++---------- .../tools/windows/scripts/mkimages_x64.sh | 75 +++++---- .../tools/windows/scripts/mkimages_x86.sh | 2 +- jb/project/tools/windows/scripts/pack_x64.sh | 4 +- 9 files changed, 204 insertions(+), 204 deletions(-) delete mode 100644 jb/project/tools/common.sh create mode 100644 jb/project/tools/common/scripts/common.sh diff --git a/jb/project/tools/common.sh b/jb/project/tools/common.sh deleted file mode 100644 index 245b10956638..000000000000 --- a/jb/project/tools/common.sh +++ /dev/null @@ -1,10 +0,0 @@ -VENDOR_NAME="JetBrains s.r.o." -VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}" -[ -z ${bundle_type} ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" - -do_reset_changes=0 -function do_exit() { - exit_code=$1 - [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java - exit $exit_code -} diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh new file mode 100644 index 000000000000..fa1b3506a6f1 --- /dev/null +++ b/jb/project/tools/common/scripts/common.sh @@ -0,0 +1,49 @@ +VENDOR_NAME="JetBrains s.r.o." +VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}" +[ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" + +do_reset_changes=0 +function do_exit() { + exit_code=$1 + [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + exit "$exit_code" +} + +function update_jsdk_mods() { + __jsdk=$1 + __jcef_mods=$2 + __orig_jsdk_mods=$3 + __updated_jsdk_mods=$4 + + # re-create java.desktop.jmod with updated module-info.class + tmp=.java.desktop.$$.tmp + mkdir "$tmp" || exit $? + "$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.desktop.jmod || exit $? + "$__jsdk"/bin/javac \ + --patch-module java.desktop="$__orig_jsdk_mods"/java.desktop.jmod \ + --module-path "$__jcef_mods" -d "$tmp"/classes src/java.desktop/share/classes/module-info.java || exit $? + "$__jsdk"/bin/jmod \ + create --class-path "$tmp"/classes --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \ + java.desktop.jmod || exit $? + mv java.desktop.jmod "$__updated_jsdk_mods" || exit $? + rm -rf "$tmp" + + # re-create java.base.jmod with updated hashes + tmp=.java.base.$$.tmp + mkdir "$tmp" || exit $? + hash_modules=$("$JSDK"/bin/jmod describe "$__orig_jsdk_mods"/java.base.jmod | grep hashes | awk '{print $2}' | tr '\n' '|' | sed s/\|$//) || exit $? + "$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.base.jmod || exit $? + rm "$__updated_jsdk_mods"/java.base.jmod || exit $? # temp exclude from path + "$__jsdk"/bin/jmod \ + create --module-path "$__updated_jsdk_mods" --hash-modules "$hash_modules" \ + --class-path "$tmp"/classes --cmds "$tmp"/bin --config "$tmp"/conf --header-files "$tmp"/include --legal-notice "$tmp"/legal --libs "$tmp"/lib \ + java.base.jmod || exit $? + mv java.base.jmod "$__updated_jsdk_mods" || exit $? + rm -rf "$tmp" +} + +function get_mods_list() { + __mods=$1 + + return `ls "$__mods"` | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g +} diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 348038f514d7..8a3353d776b8 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -20,7 +20,7 @@ build_number=$3 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -source jb/project/tools/common.sh +source jb/project/tools/common/scripts/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index afa8baeb6f11..3de7497484a1 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -18,8 +18,6 @@ # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # # Environment variables: -# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. -# By default imported modules should be located in ./modular-sdk # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_linux_x64 @@ -28,114 +26,100 @@ JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64} -source jb/project/tools/common.sh +source jb/project/tools/common/scripts/common.sh -function create_jbr { +function create_image_bundle { + __bundle_name=$1 + __arch_name=$2 + __modules_path=$3 + __modules=$4 - if [ -z "${bundle_type}" ]; then - JBR_BUNDLE=jbr - else - JBR_BUNDLE=jbr_${bundle_type} - fi - JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - rm -rf ${BASE_DIR}/jbr - rm -rf ${BASE_DIR}/${JBR_BUNDLE} - - JBR=$JBR_BASE_NAME-linux-x64-b$build_number + [ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number} echo Running jlink.... + [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" $JSDK/bin/jlink \ - --module-path $JSDK/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE - - if [ ! -z "${bundle_type}" ]; then - cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - rsync -av ${JCEF_PATH}/ $BASE_DIR/$JBR_BUNDLE/lib --exclude="modular-sdk" || do_exit $? - fi - grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release - - echo Creating $JBR.tar.gz ... - tar -pcf $JBR.tar -C $BASE_DIR jbr || do_exit $? - [ -f "$JBR.tar.gz" ] && rm "$JBR.tar.gz" - gzip $JBR.tar || do_exit $? - rm -rf ${BASE_DIR}/${JBR_BUNDLE} + --module-path "$__modules_path" --no-man-pages --compress=2 \ + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + + # jmod does not preserve file permissions (JDK-8173610) + [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + + echo Creating "$JBR".tar.gz ... + tar -pcf "$JBR".tar -C "$IMAGES_DIR" "$__arch_name" || do_exit $? + [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" + gzip "$JBR".tar || do_exit $? + rm -rf "${IMAGES_DIR:?}"/"$__arch_name" } -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WITH_DEBUG_LEVEL="--with-debug-level=release" RELEASE_NAME=linux-x86_64-server-release -JBSDK=${JBRSDK_BASE_NAME}-linux-x64-b${build_number} + case "$bundle_type" in "jcef") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch do_reset_changes=1 ;; "nomod" | "") bundle_type="" - WITH_IMPORT_MODULES="" ;; "fd") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=linux-x86_64-server-fastdebug - JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number} ;; esac sh configure \ --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ - --with-version-opt=b${build_number} \ - $WITH_IMPORT_MODULES \ - --with-boot-jdk=${BOOT_JDK} \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ --enable-cds=yes || do_exit $? make clean CONF=$RELEASE_NAME || exit $? make images CONF=$RELEASE_NAME || do_exit $? -JSDK=build/$RELEASE_NAME/images/jdk +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods +JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -BASE_DIR=build/$RELEASE_NAME/images -JBRSDK_BUNDLE=jbrsdk - -rm -rf $BASE_DIR/$JBRSDK_BUNDLE -cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || do_exit $? - if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then - rsync -av ${JCEF_PATH}/ $BASE_DIR/$JBRSDK_BUNDLE/lib --exclude="modular-sdk" || do_exit $? - echo Creating $JBSDK.tar.gz ... - sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release - mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - - tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR $JBRSDK_BUNDLE || do_exit $? - [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" - gzip $JBSDK.tar || do_exit $? -fi - -create_jbr || do_exit $? + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $? + cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed -if [ "$bundle_type" == "jcef" ]; then - make test-image CONF=$RELEASE_NAME || do_exit $? + jbr_name_postfix="_${bundle_type}" +fi - JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number +# create runtime image bundle +modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? - echo Creating $JBSDK_TEST.tar.gz ... - tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || do_exit $? - [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" - gzip $JBRSDK_TEST.tar || do_exit $? +# create sdk image bundle +modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? + +if [ -z "$bundle_type" ]; then + JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number} + echo Creating "$JBRSDK_TEST" ... + make test-image CONF=$RELEASE_NAME || do_exit $? + tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + gzip "$JBRSDK_TEST".tar || do_exit $? fi do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 3788a2515fe5..1f7d11f8153b 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -20,7 +20,7 @@ build_number=$3 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -source jb/project/tools/common.sh +source jb/project/tools/common/scripts/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 55f026c8d79a..218faa1f837e 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -18,8 +18,6 @@ # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # # Environment variables: -# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. -# By default imported modules should be located in ./modular-sdk # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_mac @@ -27,120 +25,102 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" +JBSDK_VERSION_WITH_DOTS=$(echo "$JBSDK_VERSION" | sed 's/_/\./g') JCEF_PATH=${JCEF_PATH:=./jcef_mac} -MAJOR_JBSDK_VERSION=$(echo $JBSDK_VERSION_WITH_DOTS | awk -F "." '{print $1}') - -source jb/project/tools/common.sh - -function create_jbr { - - if [ -z "${bundle_type}" ]; then - JBR_BUNDLE=jbr - else - JBR_BUNDLE=jbr_${bundle_type} - fi - JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} - cat modules.list > modules_tmp.list - rm -rf ${BASE_DIR}/jbr - rm -rf ${BASE_DIR}/${JBR_BUNDLE} - - JRE_CONTENTS=${BASE_DIR}/${JBR_BUNDLE}/Contents - JRE_HOME=${JRE_CONTENTS}/Home - if [ -d "${JRE_CONTENTS}" ]; then - rm -rf ${JRE_CONTENTS} - fi - mkdir -p ${JRE_CONTENTS} - - JBR=${JBR_BASE_NAME}-osx-x64-b${build_number} - - echo Running jlink.... - ${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \ - --module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || do_exit $? - grep -v "^JAVA_VERSION" ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release | grep -v "^MODULES" >> ${JRE_HOME}/release - cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS} - cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS} - - rm -rf ${JRE_CONTENTS}/Frameworks || do_exit $? - [ ! -z "${bundle_type}" ] && (cp -a ${JCEF_PATH}/Frameworks ${JRE_CONTENTS} || do_exit $?) - - echo Creating ${JBR}.tar.gz ... - [ ! -z "${bundle_type}" ] && cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || do_exit $? - rm -rf ${BASE_DIR}/${JBR_BUNDLE} +MAJOR_JBSDK_VERSION=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}') +BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 14)} + +source jb/project/tools/common/scripts/common.sh + +function create_image_bundle { + __bundle_name=$1 + __modules_path=$2 + __modules=$3 + + tmp=.bundle.$$.tmp + mkdir "$tmp" || do_exit $? + + [ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-osx-x64-${fastdebug_infix}b${build_number} + + JRE_CONTENTS=$tmp/$__bundle_name/Contents + mkdir -p "$JRE_CONTENTS" || do_exit $? + + echo Running jlink... + "$JSDK"/bin/jlink \ + --module-path "$__modules_path" --no-man-pages --compress=2 \ + --add-modules "$__modules" --output "$JRE_CONTENTS/Home" || do_exit $? + + cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" + cp "$JSDK"/../Info.plist "$JRE_CONTENTS" + [ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?) + + echo Creating "$JBR".tar.gz ... + COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__bundle_name" || do_exit $? + rm -rf "$tmp" } -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WITH_DEBUG_LEVEL="--with-debug-level=release" RELEASE_NAME=macosx-x86_64-server-release -JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} + case "$bundle_type" in "jcef") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? do_reset_changes=1 ;; "nomod" | "") bundle_type="" - WITH_IMPORT_MODULES="" ;; "fd") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=macosx-x86_64-server-fastdebug - JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} ;; esac sh configure \ --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ - --with-version-opt=b${build_number} \ - $WITH_IMPORT_MODULES \ - --with-boot-jdk=`/usr/libexec/java_home -v 14` \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ --enable-cds=yes || do_exit $? make clean CONF=$RELEASE_NAME || do_exit $? make images CONF=$RELEASE_NAME || do_exit $? -JSDK=build/$RELEASE_NAME/images/jdk-bundle - -BASE_DIR=jre +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk-bundle/jdk-$MAJOR_JBSDK_VERSION.jdk/Contents/Home +JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -rm -rf $BASE_DIR -mkdir $BASE_DIR || do_exit $? -cp -a $JSDK/jdk-$MAJOR_JBSDK_VERSION.jdk $BASE_DIR/$JBRSDK_BUNDLE || do_exit $? - if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then - cp -a ${JCEF_PATH}/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ - echo Creating $JBSDK.tar.gz ... - sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release - mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release - [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" - COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \ - --exclude='._*' --exclude='.DS_Store' --exclude='*~' \ - --exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \ - $JBRSDK_BUNDLE || do_exit $? -fi + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? + cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed -create_jbr || do_exit $? - -if [ "$bundle_type" == "jcef" ]; then - make test-image CONF=$RELEASE_NAME || do_exit $? + jbr_name_postfix="_${bundle_type}" +fi - JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number +# create runtime image bundle +modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $? - echo Creating $JBRSDK_TEST.tar.gz ... - [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" - COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/${RELEASE_NAME}/images \ - --exclude='test/jdk/demos' test || do_exit $? +# create sdk image bundle +modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? + +if [ -z "$bundle_type" ]; then + JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-x64-b${build_number} + echo Creating "$JBRSDK_TEST" ... + make test-image CONF=$RELEASE_NAME || do_exit $? + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? fi do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 928c2d0a4ac3..c7ff8355468e 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -18,8 +18,6 @@ # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # # Environment variables: -# MODULAR_SDK_PATH - specifies the path to the directory where imported modules are located. -# By default imported modules should be located in ./modular-sdk # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_win_x64 @@ -29,84 +27,81 @@ build_number=$3 bundle_type=$4 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') WORK_DIR=$(pwd) -WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=$WORK_DIR/modular-sdk}" JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64} -source jb/project/tools/common.sh +source jb/project/tools/common/scripts/common.sh -function create_jbr { +function create_image_bundle { + __bundle_name=$1 + __modules_path=$2 + __modules=$3 - if [ -z "${bundle_type}" ]; then - JBR_BUNDLE=jbr - else - JBR_BUNDLE=jbr_${bundle_type} - fi - cat modules.list > modules_tmp.list - rm -rf ${JBR_BUNDLE} + [ -d $__bundle_name ] && rm -rf $__bundle_name - echo Running jlink.... + echo Running jlink ... ${JSDK}/bin/jlink \ - --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || do_exit $? - - [ ! -z "${bundle_type}" ] && (rsync -av ${JCEF_PATH}/ ${JBR_BUNDLE}/bin --exclude="modular-sdk" || do_exit $?) - echo Modifying release info ... - cat ${JSDK}/release | tr -d '\r' | grep -v 'JAVA_VERSION' | grep -v 'MODULES' >> ${JBR_BUNDLE}/release + --module-path $__modules_path --no-man-pages --compress=2 \ + --add-modules $__modules --output $__bundle_name || do_exit $? } -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WITH_DEBUG_LEVEL="--with-debug-level=release" RELEASE_NAME=windows-x86_64-server-release -JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} + case "$bundle_type" in "jcef") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? do_reset_changes=1 ;; "nomod" | "") bundle_type="" - WITH_IMPORT_MODULES="" ;; "fd") - git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=windows-x86_64-server-fastdebug - JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} ;; esac sh ./configure \ --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-build=$JDK_BUILD_NUMBER \ --with-version-opt=b${build_number} \ - $WITH_IMPORT_MODULES \ - --with-toolchain-version=${TOOLCHAIN_VERSION} \ - --with-boot-jdk=${BOOT_JDK} \ + --with-toolchain-version=$TOOLCHAIN_VERSION \ + --with-boot-jdk=$BOOT_JDK \ --disable-ccache \ --enable-cds=yes || do_exit $? -if [ "$bundle_type" == "jcef" ]; then - make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? +if [ -z "$bundle_type" ]; then + make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? else make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? fi -JSDK=build/$RELEASE_NAME/images/jdk -BASE_DIR=build/$RELEASE_NAME/images +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || do_exit $? if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then - rsync -av ${JCEF_PATH}/ ${JBRSDK_BUNDLE}/bin --exclude='modular-sdk' || do_exit $? - sed 's/JBR/JBRSDK/g' ${JSDK}/release > release - mv release ${JBRSDK_BUNDLE}/release + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? + cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged + + jbr_name_postfix="_${bundle_type}" fi -create_jbr || do_exit $? +# create runtime image bundle +modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $? + +# create sdk image bundle +modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 88929a77dea2..27ac68a46094 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -20,7 +20,7 @@ build_number=$3 JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -source jb/project/tools/common.sh +source jb/project/tools/common/scripts/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 92bc2dedc79a..8ea40e1aee63 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -18,6 +18,8 @@ # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # +source jb/project/tools/common/scripts/common.sh + JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 @@ -68,7 +70,7 @@ fi pack_jbr $bundle_type -if [ "$bundle_type" == "jcef" ]; then +if [ -z "$bundle_type" ]; then JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? From bc682ac7f38ff7af95119d346835feeedc91649f Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 27 Oct 2020 18:34:15 +0700 Subject: [PATCH 034/976] JBR-2812 remove --with-import-modules from configure for aarch64 --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 8a3353d776b8..ef69a24103d5 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -34,7 +34,6 @@ sh configure \ --with-version-pre= \ --with-version-build=${JDK_BUILD_NUMBER} \ --with-version-opt=b${build_number} \ - --with-import-modules=./modular-sdk \ --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? make clean CONF=linux-aarch64-server-release || exit $? From 7aa35617ade09c734e334f767f9cb9b596195218 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 9 Jun 2020 17:42:27 +0700 Subject: [PATCH 035/976] JBR-2864 initial commit of DCEVM patches reworked for 15 --- .../0001-Apply-basic-dcevm11-patch.patch | 8853 +++++++++++++++++ .../patches/dcevm/0002-dcevm11-fixes.patch | 1569 +++ ...xception-on-redefinition-of-class-A-.patch | 29 + .../dcevm/0004-HotswapAgent-integration.patch | 1086 ++ ...upport-for-Lambda-class-redefinition.patch | 240 + ...bytecode-found-error-if-method-with-.patch | 135 + ...method-with-Universe-throw_no_such_m.patch | 57 + .../dcevm/0008-Support-for-G1-gc.patch | 1310 +++ ...e-log-level-in-advanced-redefinition.patch | 50 + ...ssRedefinition-is-false-disabled-by-.patch | 26 + ...edRedefineClasses.-to-CMakeLists.txt.patch | 2977 ++++++ ...POT_VM_DISTRO-Dynamic-Code-Evolution.patch | 25 + .../0013-Fix-G1-nmethod-registration.patch | 71 + ...d-s-_new_version-_old_version-to-NUL.patch | 26 + .../0015-Clear-dcevm-code-separation.patch | 193 + ...sClosure-fixes-problems-with-remote-.patch | 26 + ...-Cleanup-code-related-to-removed-CMS.patch | 3934 ++++++++ ...GC-spaces-originally-in-removed-CMS-.patch | 183 + ...-fix-java15-patch-compilation-issues.patch | 942 ++ .../patches/dcevm/0020-dcevm15-G1-fixes.patch | 25 + ...021-dcevm15-Fix-flush-dependent-code.patch | 133 + ...0022-dcevm15-fix-ResolvedMethodTable.patch | 211 + ...23-dcevm15-fix-Universe-root_oops_do.patch | 88 + .../dcevm/0024-Cleanup-dcevm-comments.patch | 67 + ...ot-AllowEnhancedClassRedefinition-mo.patch | 43 + ...m15-add-ClassLoaderDataGraph_lock-on.patch | 32 + ...-has_nestmate_access_to-has-newest-h.patch | 29 + .../dcevm/0028-Remove-unused-fieldType.patch | 24 + ...rk_as_scavengable-only-alive-methods.patch | 54 + ...ClassLoaderDataGraph-rollback_redefi.patch | 28 + ...G1IterateObjectClosureTask-fixing-me.patch | 28 + .../0032-dcevm15-fix-hidded-classes.patch | 91 + ...ear-F2-in-CP-cache-after-indy-unevol.patch | 27 + ...34-dcevm15-fix-Universe-root_oops_do.patch | 49 + 34 files changed, 22661 insertions(+) create mode 100644 jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch create mode 100644 jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch create mode 100644 jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch create mode 100644 jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch create mode 100644 jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch create mode 100644 jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch create mode 100644 jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch create mode 100644 jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch create mode 100644 jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch create mode 100644 jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch create mode 100644 jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch create mode 100644 jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch create mode 100644 jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch create mode 100644 jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch create mode 100644 jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch create mode 100644 jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch create mode 100644 jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch create mode 100644 jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch create mode 100644 jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch create mode 100644 jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch create mode 100644 jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch create mode 100644 jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch create mode 100644 jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch create mode 100644 jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch create mode 100644 jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch create mode 100644 jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch create mode 100644 jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch create mode 100644 jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch create mode 100644 jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch create mode 100644 jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch create mode 100644 jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch create mode 100644 jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch create mode 100644 jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch create mode 100644 jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch diff --git a/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch b/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch new file mode 100644 index 000000000000..71a984a38f01 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch @@ -0,0 +1,8853 @@ +From 1411794eeca7b619a2761d277586a855106a3c58 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Wed, 14 Nov 2018 21:09:39 +0100 +Subject: [PATCH 01/34] Apply basic dcevm11 patch + +--- + src/hotspot/share/ci/ciObjectFactory.cpp | 25 + + src/hotspot/share/ci/ciObjectFactory.hpp | 3 + + .../share/classfile/classFileParser.cpp | 18 +- + .../share/classfile/classFileParser.hpp | 7 + + src/hotspot/share/classfile/classLoader.cpp | 1 + + .../share/classfile/classLoaderDataGraph.cpp | 12 + + .../share/classfile/classLoaderDataGraph.hpp | 5 + + .../share/classfile/classLoaderExt.cpp | 1 + + src/hotspot/share/classfile/dictionary.cpp | 44 +- + src/hotspot/share/classfile/dictionary.hpp | 10 + + src/hotspot/share/classfile/javaClasses.cpp | 63 + + src/hotspot/share/classfile/javaClasses.hpp | 53 + + .../share/classfile/javaClasses.inline.hpp | 8 + + src/hotspot/share/classfile/klassFactory.cpp | 3 + + src/hotspot/share/classfile/klassFactory.hpp | 1 + + .../share/classfile/loaderConstraints.cpp | 15 +- + .../share/classfile/loaderConstraints.hpp | 3 + + .../share/classfile/systemDictionary.cpp | 47 +- + .../share/classfile/systemDictionary.hpp | 9 +- + .../classfile/systemDictionaryShared.cpp | 2 +- + src/hotspot/share/classfile/verifier.cpp | 2 +- + src/hotspot/share/classfile/verifier.hpp | 1 + + src/hotspot/share/classfile/vmSymbols.hpp | 8 + + .../share/gc/cms/compactibleFreeListSpace.cpp | 3148 +++++++++++++++++ + .../share/gc/cms/compactibleFreeListSpace.hpp | 759 ++++ + src/hotspot/share/gc/serial/genMarkSweep.cpp | 4 + + src/hotspot/share/gc/serial/markSweep.cpp | 99 + + src/hotspot/share/gc/serial/markSweep.hpp | 7 + + src/hotspot/share/gc/shared/gcConfig.cpp | 5 +- + src/hotspot/share/gc/shared/space.cpp | 200 +- + src/hotspot/share/gc/shared/space.hpp | 18 +- + src/hotspot/share/gc/shared/space.inline.hpp | 49 +- + .../share/interpreter/linkResolver.cpp | 7 +- + .../jfrEventClassTransformer.cpp | 1 + + src/hotspot/share/memory/universe.cpp | 39 + + src/hotspot/share/memory/universe.hpp | 12 + + src/hotspot/share/oops/cpCache.cpp | 32 +- + src/hotspot/share/oops/cpCache.hpp | 16 +- + src/hotspot/share/oops/instanceKlass.cpp | 55 +- + src/hotspot/share/oops/instanceKlass.hpp | 7 + + src/hotspot/share/oops/klass.cpp | 29 +- + src/hotspot/share/oops/klass.hpp | 47 + + src/hotspot/share/oops/method.cpp | 6 + + src/hotspot/share/oops/method.hpp | 20 + + src/hotspot/share/prims/jni.cpp | 1 + + src/hotspot/share/prims/jvm.cpp | 1 + + .../prims/jvmtiEnhancedRedefineClasses.cpp | 2255 ++++++++++++ + .../prims/jvmtiEnhancedRedefineClasses.hpp | 202 ++ + src/hotspot/share/prims/jvmtiEnv.cpp | 44 +- + src/hotspot/share/prims/jvmtiExport.cpp | 2 +- + src/hotspot/share/prims/jvmtiExport.hpp | 1 + + .../share/prims/jvmtiGetLoadedClasses.cpp | 19 +- + src/hotspot/share/prims/jvmtiImpl.cpp | 5 + + src/hotspot/share/runtime/arguments.cpp | 32 + + src/hotspot/share/runtime/arguments.hpp | 1 + + src/hotspot/share/runtime/globals.hpp | 5 + + .../share/runtime/interfaceSupport.inline.hpp | 4 +- + src/hotspot/share/runtime/javaCalls.cpp | 3 +- + src/hotspot/share/runtime/mutexLocker.cpp | 4 +- + src/hotspot/share/runtime/mutexLocker.hpp | 2 + + src/hotspot/share/runtime/reflection.cpp | 6 + + 61 files changed, 7423 insertions(+), 65 deletions(-) + create mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp + create mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp + create mode 100644 src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp + create mode 100644 src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp + +diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp +index f74f5e627a0..d713570fccf 100644 +--- a/src/hotspot/share/ci/ciObjectFactory.cpp ++++ b/src/hotspot/share/ci/ciObjectFactory.cpp +@@ -722,3 +722,28 @@ void ciObjectFactory::print() { + _unloaded_instances->length(), + _unloaded_klasses->length()); + } ++ ++ ++int ciObjectFactory::compare_cimetadata(ciMetadata** a, ciMetadata** b) { ++ Metadata* am = (*a)->constant_encoding(); ++ Metadata* bm = (*b)->constant_encoding(); ++ return ((am > bm) ? 1 : ((am == bm) ? 0 : -1)); ++} ++ ++// FIXME: review... Resoring the ciObject arrays after class redefinition ++void ciObjectFactory::resort_shared_ci_metadata() { ++ if (_shared_ci_metadata == NULL) return; ++ _shared_ci_metadata->sort(ciObjectFactory::compare_cimetadata); ++ ++#ifdef ASSERT ++ if (CIObjectFactoryVerify) { ++ Metadata* last = NULL; ++ for (int j = 0; j< _shared_ci_metadata->length(); j++) { ++ Metadata* o = _shared_ci_metadata->at(j)->constant_encoding(); ++ assert(last < o, "out of order"); ++ last = o; ++ } ++ } ++#endif // ASSERT ++} ++ +diff --git a/src/hotspot/share/ci/ciObjectFactory.hpp b/src/hotspot/share/ci/ciObjectFactory.hpp +index f78ae05a905..875462c3168 100644 +--- a/src/hotspot/share/ci/ciObjectFactory.hpp ++++ b/src/hotspot/share/ci/ciObjectFactory.hpp +@@ -88,6 +88,7 @@ private: + + ciInstance* get_unloaded_instance(ciInstanceKlass* klass); + ++ static int compare_cimetadata(ciMetadata** a, ciMetadata** b); + public: + static bool is_initialized() { return _initialized; } + +@@ -144,6 +145,8 @@ public: + + void print_contents(); + void print(); ++ ++ static void resort_shared_ci_metadata(); + }; + + #endif // SHARE_CI_CIOBJECTFACTORY_HPP +diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp +index 5e81e786dc5..0192e9e006f 100644 +--- a/src/hotspot/share/classfile/classFileParser.cpp ++++ b/src/hotspot/share/classfile/classFileParser.cpp +@@ -964,6 +964,8 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, + CHECK); + } + ++ interf = (Klass *) maybe_newest(interf); ++ + if (!interf->is_interface()) { + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), + err_msg("class %s can not implement %s, because it is not an interface (%s)", +@@ -4012,7 +4014,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, + // However, make sure it is not an array type. + bool is_array = false; + if (cp->tag_at(super_class_index).is_klass()) { +- super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index)); ++ super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index))); + if (need_verify) + is_array = super_klass->is_array_klass(); + } else if (need_verify) { +@@ -4615,7 +4617,10 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { + if (!_has_empty_finalizer) { + if (_has_finalizer || + (super != NULL && super->has_finalizer())) { +- ik->set_has_finalizer(); ++ // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active ++ if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) { ++ ik->set_has_finalizer(); ++ } + } + } + +@@ -6062,6 +6067,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, + ClassLoaderData* loader_data, + const ClassLoadInfo* cl_info, + Publicity pub_level, ++ const bool pick_newest, + TRAPS) : + _stream(stream), + _class_name(NULL), +@@ -6125,7 +6131,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, + _has_finalizer(false), + _has_empty_finalizer(false), + _has_vanilla_constructor(false), +- _max_bootstrap_specifier_index(-1) { ++ _max_bootstrap_specifier_index(-1), ++ _pick_newest(pick_newest) { + + _class_name = name != NULL ? name : vmSymbols::unknown_class_name(); + _class_name->increment_refcount(); +@@ -6604,14 +6611,15 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st + CHECK); + } + Handle loader(THREAD, _loader_data->class_loader()); +- _super_klass = (const InstanceKlass*) ++ const Klass* super_klass = + SystemDictionary::resolve_super_or_fail(_class_name, + super_class_name, + loader, + _protection_domain, + true, + CHECK); +- } ++ _super_klass = (const InstanceKlass*) maybe_newest(super_klass); ++ } + + if (_super_klass != NULL) { + if (_super_klass->has_nonstatic_concrete_methods()) { +diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp +index bf5fccf340c..6660616ccad 100644 +--- a/src/hotspot/share/classfile/classFileParser.hpp ++++ b/src/hotspot/share/classfile/classFileParser.hpp +@@ -150,6 +150,9 @@ class ClassFileParser { + const intArray* _method_ordering; + GrowableArray* _all_mirandas; + ++ // Enhanced class redefinition ++ const bool _pick_newest; ++ + enum { fixed_buffer_size = 128 }; + u_char _linenumbertable_buffer[fixed_buffer_size]; + +@@ -541,6 +544,8 @@ class ClassFileParser { + TRAPS); + + void update_class_name(Symbol* new_name); ++ // Enhanced class redefinition ++ inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; } + + public: + ClassFileParser(ClassFileStream* stream, +@@ -548,6 +553,7 @@ class ClassFileParser { + ClassLoaderData* loader_data, + const ClassLoadInfo* cl_info, + Publicity pub_level, ++ const bool pick_newest, + TRAPS); + + ~ClassFileParser(); +@@ -576,6 +582,7 @@ class ClassFileParser { + ClassLoaderData* loader_data() const { return _loader_data; } + const Symbol* class_name() const { return _class_name; } + const InstanceKlass* super_klass() const { return _super_klass; } ++ Array* local_interfaces() const { return _local_interfaces; } + + ReferenceType reference_type() const { return _rt; } + AccessFlags access_flags() const { return _access_flags; } +diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp +index a53ccea0933..93ef3ea254d 100644 +--- a/src/hotspot/share/classfile/classLoader.cpp ++++ b/src/hotspot/share/classfile/classLoader.cpp +@@ -1275,6 +1275,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR + name, + loader_data, + cl_info, ++ false, // pick_newest + THREAD); + if (HAS_PENDING_EXCEPTION) { + if (DumpSharedSpaces) { +diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp +index 9b104d9ba4d..db0fbcc45dc 100644 +--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp ++++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp +@@ -439,6 +439,18 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), + } + } + ++void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) { ++ FOR_ALL_DICTIONARY(cld) { ++ cld->dictionary()->classes_do(klass_closure); ++ } ++} ++ ++void ClassLoaderDataGraph::rollback_redefinition() { ++ FOR_ALL_DICTIONARY(cld) { ++ cld->dictionary()->rollback_redefinition(); ++ } ++} ++ + void ClassLoaderDataGraph::verify_dictionary() { + FOR_ALL_DICTIONARY(cld) { + cld->dictionary()->verify(); +diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp +index 4251afab3dc..f380aa3fa34 100644 +--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp ++++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp +@@ -102,6 +102,11 @@ class ClassLoaderDataGraph : public AllStatic { + // Added for initialize_itable_for_klass to handle exceptions. + static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS); + ++ static void dictionary_classes_do(KlassClosure* klass_closure); ++ ++ // Enhanced class redefinition ++ static void rollback_redefinition(); ++ + // VM_CounterDecay iteration support + static InstanceKlass* try_get_next_class(); + static void adjust_saved_class(ClassLoaderData* cld); +diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp +index 701c155da19..9bf4f38cf21 100644 +--- a/src/hotspot/share/classfile/classLoaderExt.cpp ++++ b/src/hotspot/share/classfile/classLoaderExt.cpp +@@ -290,6 +290,7 @@ InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) + name, + loader_data, + cl_info, ++ false, + THREAD); + + if (HAS_PENDING_EXCEPTION) { +diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp +index 8b10f5abdb1..45c979a1738 100644 +--- a/src/hotspot/share/classfile/dictionary.cpp ++++ b/src/hotspot/share/classfile/dictionary.cpp +@@ -216,6 +216,19 @@ void Dictionary::classes_do(void f(InstanceKlass*)) { + } + } + ++void Dictionary::classes_do(KlassClosure* closure) { ++ for (int index = 0; index < table_size(); index++) { ++ for (DictionaryEntry* probe = bucket(index); ++ probe != NULL; ++ probe = probe->next()) { ++ InstanceKlass* k = probe->instance_klass(); ++ if (loader_data() == k->class_loader_data()) { ++ closure->do_klass(k); ++ } ++ } ++ } ++} ++ + // Added for initialize_itable_for_klass to handle exceptions + // Just the classes from defining class loaders + void Dictionary::classes_do(void f(InstanceKlass*, TRAPS), TRAPS) { +@@ -297,6 +310,33 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, + return NULL; + } + ++bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) { ++ // There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class. ++ bool found = false; ++ for (int index = 0; index < table_size(); index++) { ++ for (DictionaryEntry* entry = bucket(index); entry != NULL; entry = entry->next()) { ++ if (entry->instance_klass() == old_klass) { ++ entry->set_literal(k); ++ found = true; ++ } ++ } ++ } ++ return found; ++} ++ ++void Dictionary::rollback_redefinition() { ++ for (int index = 0; index < table_size(); index++) { ++ for (DictionaryEntry* entry = bucket(index); ++ entry != NULL; ++ entry = entry->next()) { ++ if (entry->instance_klass()->is_redefining()) { ++ entry->set_literal((InstanceKlass*) entry->instance_klass()->old_version()); ++ } ++ } ++ } ++} ++ ++ + + InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name, + Handle protection_domain) { +@@ -305,7 +345,7 @@ InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name, + int index = hash_to_index(hash); + DictionaryEntry* entry = get_entry(index, hash, name); + if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { +- return entry->instance_klass(); ++ return old_if_redefined(entry->instance_klass()); + } else { + return NULL; + } +@@ -317,7 +357,7 @@ InstanceKlass* Dictionary::find_class(int index, unsigned int hash, + assert (index == index_for(name), "incorrect index?"); + + DictionaryEntry* entry = get_entry(index, hash, name); +- return (entry != NULL) ? entry->instance_klass() : NULL; ++ return old_if_redefined((entry != NULL) ? entry->instance_klass() : NULL); + } + + +diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp +index 99b9799753f..b4f5cd5c4df 100644 +--- a/src/hotspot/share/classfile/dictionary.hpp ++++ b/src/hotspot/share/classfile/dictionary.hpp +@@ -65,6 +65,7 @@ public: + InstanceKlass* find_class(int index, unsigned int hash, Symbol* name); + + void classes_do(void f(InstanceKlass*)); ++ void classes_do(KlassClosure* closure); + void classes_do(void f(InstanceKlass*, TRAPS), TRAPS); + void all_entries_do(KlassClosure* closure); + void classes_do(MetaspaceClosure* it); +@@ -104,6 +105,15 @@ public: + } + + void free_entry(DictionaryEntry* entry); ++ ++ // Enhanced class redefinition ++ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); ++ ++ void rollback_redefinition(); ++ ++ static InstanceKlass* old_if_redefined(InstanceKlass* k) { ++ return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; ++ } + }; + + // An entry in the class loader data dictionaries, this describes a class as +diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp +index ca1f1f0d71d..9b086a241f7 100644 +--- a/src/hotspot/share/classfile/javaClasses.cpp ++++ b/src/hotspot/share/classfile/javaClasses.cpp +@@ -2540,6 +2540,8 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHand + skip_throwableInit_check = true; + } + } ++ // (DCEVM): Line numbers from newest version must be used for EMCP-swapped methods ++ method = method->newest_version(); + if (method->is_hidden()) { + if (skip_hidden) { + if (total_count == 0) { +@@ -3747,6 +3749,62 @@ void java_lang_invoke_DirectMethodHandle::serialize_offsets(SerializeClosure* f) + } + #endif + ++// Support for java_lang_invoke_DirectMethodHandle$StaticAccessor ++ ++int java_lang_invoke_DirectMethodHandle_StaticAccessor::_static_offset_offset; ++ ++long java_lang_invoke_DirectMethodHandle_StaticAccessor::static_offset(oop dmh) { ++ assert(_static_offset_offset != 0, ""); ++ return dmh->long_field(_static_offset_offset); ++} ++ ++void java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(oop dmh, long static_offset) { ++ assert(_static_offset_offset != 0, ""); ++ dmh->long_field_put(_static_offset_offset, static_offset); ++} ++ ++#define DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(macro) \ ++ macro(_static_offset_offset, k, vmSymbols::static_offset_name(), long_signature, false) ++ ++void java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets() { ++ InstanceKlass* k = SystemDictionary::DirectMethodHandle_StaticAccessor_klass(); ++ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET); ++} ++ ++#if INCLUDE_CDS ++void java_lang_invoke_DirectMethodHandle_StaticAccessor::serialize_offsets(SerializeClosure* f) { ++ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET); ++} ++#endif ++ ++// Support for java_lang_invoke_DirectMethodHandle$Accessor ++ ++int java_lang_invoke_DirectMethodHandle_Accessor::_field_offset_offset; ++ ++int java_lang_invoke_DirectMethodHandle_Accessor::field_offset(oop dmh) { ++ assert(_field_offset_offset != 0, ""); ++ return dmh->int_field(_field_offset_offset); ++} ++ ++void java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(oop dmh, int field_offset) { ++ assert(_field_offset_offset != 0, ""); ++ dmh->int_field_put(_field_offset_offset, field_offset); ++} ++ ++#define DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(macro) \ ++ macro(_field_offset_offset, k, vmSymbols::field_offset_name(), int_signature, false) ++ ++void java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets() { ++ InstanceKlass* k = SystemDictionary::DirectMethodHandle_Accessor_klass(); ++ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET); ++} ++ ++#if INCLUDE_CDS ++void java_lang_invoke_DirectMethodHandle_Accessor::serialize_offsets(SerializeClosure* f) { ++ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET); ++} ++#endif ++ + // Support for java_lang_invoke_MethodHandle + + int java_lang_invoke_MethodHandle::_type_offset; +@@ -3938,6 +3996,11 @@ void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop + resolved_method->obj_field_put(_vmholder_offset, holder); + } + ++void java_lang_invoke_ResolvedMethodName::set_vmholder_offset(oop resolved_method, Method* m) { ++ assert(is_instance(resolved_method), "wrong type"); ++ resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror()); ++} ++ + oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) { + const Method* method = m(); + +diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp +index e33391c63e0..a68c5139151 100644 +--- a/src/hotspot/share/classfile/javaClasses.hpp ++++ b/src/hotspot/share/classfile/javaClasses.hpp +@@ -56,6 +56,8 @@ class RecordComponent; + f(java_lang_invoke_MethodType) \ + f(java_lang_invoke_CallSite) \ + f(java_lang_invoke_ConstantCallSite) \ ++ f(java_lang_invoke_DirectMethodHandle_StaticAccessor) \ ++ f(java_lang_invoke_DirectMethodHandle_Accessor) \ + f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \ + f(java_security_AccessControlContext) \ + f(java_lang_reflect_AccessibleObject) \ +@@ -256,6 +258,7 @@ class java_lang_Class : AllStatic { + static void set_component_mirror(oop java_class, oop comp_mirror); + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS); ++ static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); + static void set_mirror_module_field(Klass* K, Handle mirror, Handle module, TRAPS); + public: + static void allocate_fixup_lists(); +@@ -1002,6 +1005,55 @@ class java_lang_invoke_DirectMethodHandle: AllStatic { + static int member_offset() { CHECK_INIT(_member_offset); } + }; + ++// Interface to java.lang.invoke.DirectMethodHandle$StaticAccessor objects ++ ++class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic { ++ friend class JavaClasses; ++ ++ private: ++ static int _static_offset_offset; // offset to static field ++ ++ static void compute_offsets(); ++ ++ public: ++ // Accessors ++ static long static_offset(oop dmh); ++ static void set_static_offset(oop dmh, long value); ++ ++ // Testers ++ static bool is_subclass(Klass* klass) { ++ return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_StaticAccessor_klass()); ++ } ++ static bool is_instance(oop obj); ++ ++ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; ++}; ++ ++// Interface to java.lang.invoke.DirectMethodHandle$Accessor objects ++ ++class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic { ++ friend class JavaClasses; ++ ++ private: ++ static int _field_offset_offset; // offset to field ++ ++ static void compute_offsets(); ++ ++ public: ++ // Accessors ++ static int field_offset(oop dmh); ++ static void set_field_offset(oop dmh, int value); ++ ++ // Testers ++ static bool is_subclass(Klass* klass) { ++ return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_Accessor_klass()); ++ } ++ static bool is_instance(oop obj); ++ ++ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; ++}; ++ ++ + // Interface to java.lang.invoke.LambdaForm objects + // (These are a private interface for managing adapter code generation.) + +@@ -1053,6 +1105,7 @@ class java_lang_invoke_ResolvedMethodName : AllStatic { + + static Method* vmtarget(oop resolved_method); + static void set_vmtarget(oop resolved_method, Method* method); ++ static void set_vmholder_offset(oop resolved_method, Method* method); + + static void set_vmholder(oop resolved_method, oop holder); + +diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp +index a654516a377..2c6ec3c5c23 100644 +--- a/src/hotspot/share/classfile/javaClasses.inline.hpp ++++ b/src/hotspot/share/classfile/javaClasses.inline.hpp +@@ -239,6 +239,14 @@ inline bool java_lang_invoke_DirectMethodHandle::is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); + } + ++inline bool java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(oop obj) { ++ return obj != NULL && is_subclass(obj->klass()); ++} ++ ++inline bool java_lang_invoke_DirectMethodHandle_Accessor::is_instance(oop obj) { ++ return obj != NULL && is_subclass(obj->klass()); ++} ++ + inline bool java_lang_Module::is_instance(oop obj) { + return obj != NULL && obj->klass() == SystemDictionary::Module_klass(); + } +diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp +index 8efe2b0ca0c..65e74e7c851 100644 +--- a/src/hotspot/share/classfile/klassFactory.cpp ++++ b/src/hotspot/share/classfile/klassFactory.cpp +@@ -85,6 +85,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook( + loader_data, + &cl_info, + ClassFileParser::BROADCAST, // publicity level ++ false, + CHECK_NULL); + const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); + InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook +@@ -168,6 +169,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, + Symbol* name, + ClassLoaderData* loader_data, + const ClassLoadInfo& cl_info, ++ const bool pick_newest, + TRAPS) { + assert(stream != NULL, "invariant"); + assert(loader_data != NULL, "invariant"); +@@ -201,6 +203,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, + loader_data, + &cl_info, + ClassFileParser::BROADCAST, // publicity level ++ pick_newest, + CHECK_NULL); + + const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); +diff --git a/src/hotspot/share/classfile/klassFactory.hpp b/src/hotspot/share/classfile/klassFactory.hpp +index 97d49a52294..790b1435dce 100644 +--- a/src/hotspot/share/classfile/klassFactory.hpp ++++ b/src/hotspot/share/classfile/klassFactory.hpp +@@ -73,6 +73,7 @@ class KlassFactory : AllStatic { + Symbol* name, + ClassLoaderData* loader_data, + const ClassLoadInfo& cl_info, ++ const bool pick_newest, + TRAPS); + public: + static InstanceKlass* check_shared_class_file_load_hook( +diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp +index e258f1fd1aa..fd1bd46b8bd 100644 +--- a/src/hotspot/share/classfile/loaderConstraints.cpp ++++ b/src/hotspot/share/classfile/loaderConstraints.cpp +@@ -91,6 +91,19 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( + return pp; + } + ++void LoaderConstraintTable::update_after_redefinition() { ++ for (int index = 0; index < table_size(); index++) { ++ LoaderConstraintEntry** p = bucket_addr(index); ++ while(*p) { ++ LoaderConstraintEntry* probe = *p; ++ if (probe->klass() != NULL) { ++ // We swap the class with the newest version with an assumption that the hash will be the same ++ probe->set_klass((InstanceKlass*) probe->klass()->newest_version()); ++ } ++ p = probe->next_addr(); ++ } ++ } ++} + + void LoaderConstraintTable::purge_loader_constraints() { + assert_locked_or_safepoint(SystemDictionary_lock); +@@ -446,7 +459,7 @@ void LoaderConstraintTable::verify(PlaceholderTable* placeholders) { + if (k != NULL) { + // We found the class in the dictionary, so we should + // make sure that the Klass* matches what we already have. +- guarantee(k == probe->klass(), "klass should be in dictionary"); ++ guarantee(k == probe->klass()->newest_version(), "klass should be in dictionary"); + } else { + // If we don't find the class in the dictionary, it + // has to be in the placeholders table. +diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp +index 0a6e4da2a5b..d0fa9df73e2 100644 +--- a/src/hotspot/share/classfile/loaderConstraints.hpp ++++ b/src/hotspot/share/classfile/loaderConstraints.hpp +@@ -55,6 +55,9 @@ public: + return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); + } + ++ // (DCEVM) update all klasses with newest version ++ void update_after_redefinition(); ++ + // Check class loader constraints + bool add_entry(Symbol* name, InstanceKlass* klass1, Handle loader1, + InstanceKlass* klass2, Handle loader2); +diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp +index 3a460f95b59..e6b25e90f18 100644 +--- a/src/hotspot/share/classfile/systemDictionary.cpp ++++ b/src/hotspot/share/classfile/systemDictionary.cpp +@@ -265,6 +265,7 @@ Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader + // can return a null klass + klass = handle_resolution_exception(class_name, throw_error, klass, THREAD); + } ++ assert(klass == NULL || klass->new_version() == NULL || klass->newest_version()->is_redefining(), "must be"); + return klass; + } + +@@ -966,6 +967,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, + ClassLoaderData* loader_data = k->class_loader_data(); + MutexLocker mu(THREAD, SystemDictionary_lock); + InstanceKlass* kk = find_class(name, loader_data); ++ // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) + assert(kk == k, "should be present in dictionary"); + } + #endif +@@ -1091,6 +1093,7 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, + class_name, + loader_data, + cl_info, ++ false, // pick_newest + CHECK_NULL); + + if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) { +@@ -1145,10 +1148,13 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, ++ InstanceKlass* old_klass, + TRAPS) { + + HandleMark hm(THREAD); + ++ bool is_redefining = (old_klass != NULL); ++ + // Classloaders that support parallelism, e.g. bootstrap classloader, + // do not acquire lock here + bool DoObjectLock = true; +@@ -1172,6 +1178,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + InstanceKlass* k = NULL; + + #if INCLUDE_CDS ++ // FIXME: what to do during redefinition? + if (!DumpSharedSpaces) { + k = SystemDictionaryShared::lookup_from_stream(class_name, + class_loader, +@@ -1186,7 +1193,12 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + return NULL; + } + ClassLoadInfo cl_info(protection_domain); +- k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL); ++ k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, is_redefining, CHECK_NULL); ++ } ++ ++ if (is_redefining && k != NULL) { ++ k->set_redefining(true); ++ k->set_old_version(old_klass); + } + + assert(k != NULL, "no klass created"); +@@ -1196,7 +1208,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + // Add class just loaded + // If a class loader supports parallel classloading handle parallel define requests + // find_or_define_instance_class may return a different InstanceKlass +- if (is_parallelCapable(class_loader)) { ++ if (is_parallelCapable(class_loader) && !is_redefining) { + InstanceKlass* defined_k = find_or_define_instance_class(h_name, class_loader, k, THREAD); + if (!HAS_PENDING_EXCEPTION && defined_k != k) { + // If a parallel capable class loader already defined this class, register 'k' for cleanup. +@@ -1205,7 +1217,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + k = defined_k; + } + } else { +- define_instance_class(k, THREAD); ++ define_instance_class(k, old_klass, THREAD); + } + + // If defining the class throws an exception register 'k' for cleanup. +@@ -1220,7 +1232,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + MutexLocker mu(THREAD, SystemDictionary_lock); + + Klass* check = find_class(h_name, k->class_loader_data()); +- assert(check == k, "should be present in the dictionary"); ++ assert((check == k && !k->is_redefining()) || (k->is_redefining() && check == k->old_version()), "should be present in the dictionary"); + } ); + + return k; +@@ -1701,11 +1713,12 @@ static void post_class_define_event(InstanceKlass* k, const ClassLoaderData* def + } + } + +-void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { ++void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* old_klass, TRAPS) { + + HandleMark hm(THREAD); + ClassLoaderData* loader_data = k->class_loader_data(); + Handle class_loader_h(THREAD, loader_data->class_loader()); ++ bool is_redefining = (old_klass != NULL); + + // for bootstrap and other parallel classloaders don't acquire lock, + // use placeholder token +@@ -1730,7 +1743,11 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { + Symbol* name_h = k->name(); + Dictionary* dictionary = loader_data->dictionary(); + unsigned int d_hash = dictionary->compute_hash(name_h); +- check_constraints(d_hash, k, class_loader_h, true, CHECK); ++ if (is_redefining) { ++ bool ok = dictionary->update_klass(d_hash, name_h, loader_data, k, old_klass); ++ assert (ok, "must have found old class and updated!"); ++ } ++ check_constraints(d_hash, k, class_loader_h, !is_redefining, CHECK); + + // Register class just loaded with class loader (placed in ArrayList) + // Note we do this before updating the dictionary, as this can +@@ -1764,7 +1781,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { + k->eager_initialize(THREAD); + + // notify jvmti +- if (JvmtiExport::should_post_class_load()) { ++ if (!is_redefining && JvmtiExport::should_post_class_load()) { + assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); + JvmtiExport::post_class_load((JavaThread *) THREAD, k); + +@@ -1842,7 +1859,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam + } + } + +- define_instance_class(k, THREAD); ++ define_instance_class(k, NULL, THREAD); + + Handle linkage_exception = Handle(); // null handle + +@@ -1972,6 +1989,18 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { + } + } + ++// Enhanced class redefinition ++void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { ++ assert(k != NULL, "just checking"); ++ ++ // remove receiver from sibling list ++ k->remove_from_sibling_list(); ++} ++ ++void SystemDictionary::update_constraints_after_redefinition() { ++ constraints()->update_after_redefinition(); ++} ++ + // ---------------------------------------------------------------------------- + // GC support + +@@ -2251,7 +2280,7 @@ void SystemDictionary::check_constraints(unsigned int d_hash, + // also hold array classes. + + assert(check->is_instance_klass(), "noninstance in systemdictionary"); +- if ((defining == true) || (k != check)) { ++ if ((defining == true) || ((k != check) && k->old_version() != check)) { + throwException = true; + ss.print("loader %s", loader_data->loader_name_and_id()); + ss.print(" attempted duplicate %s definition for %s. (%s)", +diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp +index 7fd274b8d77..4547449dbec 100644 +--- a/src/hotspot/share/classfile/systemDictionary.hpp ++++ b/src/hotspot/share/classfile/systemDictionary.hpp +@@ -209,6 +209,8 @@ class EventClassLoad; + \ + /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ + do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \ ++ do_klass(DirectMethodHandle_StaticAccessor_klass, java_lang_invoke_DirectMethodHandle_StaticAccessor ) \ ++ do_klass(DirectMethodHandle_Accessor_klass, java_lang_invoke_DirectMethodHandle_Accessor ) \ + do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle ) \ + do_klass(VarHandle_klass, java_lang_invoke_VarHandle ) \ + do_klass(MemberName_klass, java_lang_invoke_MemberName ) \ +@@ -334,6 +336,7 @@ public: + Handle class_loader, + Handle protection_domain, + ClassFileStream* st, ++ InstanceKlass* old_klass, + TRAPS); + + // Lookup an already loaded class. If not found NULL is returned. +@@ -451,6 +454,10 @@ public: + static bool is_well_known_klass(Symbol* class_name); + #endif + ++ // Enhanced class redefinition ++ static void remove_from_hierarchy(InstanceKlass* k); ++ static void update_constraints_after_redefinition(); ++ + protected: + // Returns the class loader data to be used when looking up/updating the + // system dictionary. +@@ -622,7 +629,7 @@ protected: + // after waiting, but before reentering SystemDictionary_lock + // to preserve lock order semantics. + static void double_lock_wait(Handle lockObject, TRAPS); +- static void define_instance_class(InstanceKlass* k, TRAPS); ++ static void define_instance_class(InstanceKlass* k, InstanceKlass* old_klass, TRAPS); + static InstanceKlass* find_or_define_instance_class(Symbol* class_name, + Handle class_loader, + InstanceKlass* k, TRAPS); +diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp +index 96c53e059a9..91dd2f2701a 100644 +--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp ++++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp +@@ -1079,7 +1079,7 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class( + + k = load_shared_class_for_builtin_loader(name, class_loader, THREAD); + if (k != NULL) { +- define_instance_class(k, CHECK_NULL); ++ define_instance_class(k, NULL, CHECK_NULL); + } + } + } +diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp +index 9711662698b..4f9c750d549 100644 +--- a/src/hotspot/share/classfile/verifier.cpp ++++ b/src/hotspot/share/classfile/verifier.cpp +@@ -259,7 +259,7 @@ bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_ve + Symbol* name = klass->name(); + Klass* refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); + +- bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); ++ bool is_reflect = refl_magic_klass != NULL && (klass->is_subtype_of(refl_magic_klass) || klass->is_subtype_of(refl_magic_klass->newest_version())); + + return (should_verify_for(klass->class_loader(), should_verify_class) && + // return if the class is a bootstrapping class +diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp +index e629b4f5623..eedb57e5c9d 100644 +--- a/src/hotspot/share/classfile/verifier.hpp ++++ b/src/hotspot/share/classfile/verifier.hpp +@@ -374,6 +374,7 @@ class ClassVerifier : public StackObj { + + VerificationType object_type() const; + ++ InstanceKlass* _klass_to_verify; + InstanceKlass* _klass; // the class being verified + methodHandle _method; // current method being verified + VerificationType _this_type; // the verification type of the current class +diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp +index 28cb9bae2e2..99c5ac98995 100644 +--- a/src/hotspot/share/classfile/vmSymbols.hpp ++++ b/src/hotspot/share/classfile/vmSymbols.hpp +@@ -292,6 +292,8 @@ + template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ + template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \ + template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ ++ template(java_lang_invoke_DirectMethodHandle_StaticAccessor, "java/lang/invoke/DirectMethodHandle$StaticAccessor") \ ++ template(java_lang_invoke_DirectMethodHandle_Accessor, "java/lang/invoke/DirectMethodHandle$Accessor") \ + template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \ + template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \ + template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ +@@ -459,6 +461,12 @@ + template(big_endian_name, "BIG_ENDIAN") \ + template(use_unaligned_access_name, "UNALIGNED_ACCESS") \ + template(data_cache_line_flush_size_name, "DATA_CACHE_LINE_FLUSH_SIZE") \ ++ template(static_offset_name, "staticOffset") \ ++ template(static_base_name, "staticBase") \ ++ template(field_offset_name, "fieldOffset") \ ++ template(field_type_name, "fieldType") \ ++ \ ++ /* name symbols needed by intrinsics */ \ + \ + /* name symbols needed by intrinsics */ \ + VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ +diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp +new file mode 100644 +index 00000000000..a93f764f1b9 +--- /dev/null ++++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp +@@ -0,0 +1,3148 @@ ++/* ++ * Copyright (c) 2001, 2018, 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/cms/cmsHeap.hpp" ++#include "gc/cms/cmsLockVerifier.hpp" ++#include "gc/cms/compactibleFreeListSpace.hpp" ++#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" ++#include "gc/cms/concurrentMarkSweepThread.hpp" ++#include "gc/shared/blockOffsetTable.inline.hpp" ++#include "gc/shared/collectedHeap.inline.hpp" ++#include "gc/shared/genOopClosures.inline.hpp" ++#include "gc/shared/space.inline.hpp" ++#include "gc/shared/spaceDecorator.hpp" ++#include "logging/log.hpp" ++#include "logging/logStream.hpp" ++#include "memory/allocation.inline.hpp" ++#include "memory/binaryTreeDictionary.inline.hpp" ++#include "memory/iterator.inline.hpp" ++#include "memory/resourceArea.hpp" ++#include "memory/universe.hpp" ++#include "oops/access.inline.hpp" ++#include "oops/compressedOops.inline.hpp" ++#include "oops/oop.inline.hpp" ++#include "runtime/globals.hpp" ++#include "runtime/handles.inline.hpp" ++#include "runtime/init.hpp" ++#include "runtime/java.hpp" ++#include "runtime/orderAccess.hpp" ++#include "runtime/vmThread.hpp" ++#include "utilities/align.hpp" ++#include "utilities/copy.hpp" ++ ++// Specialize for AdaptiveFreeList which tries to avoid ++// splitting a chunk of a size that is under populated in favor of ++// an over populated size. The general get_better_list() just returns ++// the current list. ++template <> ++TreeList >* ++TreeList >::get_better_list( ++ BinaryTreeDictionary >* dictionary) { ++ // A candidate chunk has been found. If it is already under ++ // populated, get a chunk associated with the hint for this ++ // chunk. ++ ++ TreeList >* curTL = this; ++ if (curTL->surplus() <= 0) { ++ /* Use the hint to find a size with a surplus, and reset the hint. */ ++ TreeList >* hintTL = this; ++ while (hintTL->hint() != 0) { ++ assert(hintTL->hint() > hintTL->size(), ++ "hint points in the wrong direction"); ++ hintTL = dictionary->find_list(hintTL->hint()); ++ assert(curTL != hintTL, "Infinite loop"); ++ if (hintTL == NULL || ++ hintTL == curTL /* Should not happen but protect against it */ ) { ++ // No useful hint. Set the hint to NULL and go on. ++ curTL->set_hint(0); ++ break; ++ } ++ assert(hintTL->size() > curTL->size(), "hint is inconsistent"); ++ if (hintTL->surplus() > 0) { ++ // The hint led to a list that has a surplus. Use it. ++ // Set the hint for the candidate to an overpopulated ++ // size. ++ curTL->set_hint(hintTL->size()); ++ // Change the candidate. ++ curTL = hintTL; ++ break; ++ } ++ } ++ } ++ return curTL; ++} ++ ++void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) { ++ TreeList >* nd = find_list(size); ++ if (nd) { ++ if (split) { ++ if (birth) { ++ nd->increment_split_births(); ++ nd->increment_surplus(); ++ } else { ++ nd->increment_split_deaths(); ++ nd->decrement_surplus(); ++ } ++ } else { ++ if (birth) { ++ nd->increment_coal_births(); ++ nd->increment_surplus(); ++ } else { ++ nd->increment_coal_deaths(); ++ nd->decrement_surplus(); ++ } ++ } ++ } ++ // A list for this size may not be found (nd == 0) if ++ // This is a death where the appropriate list is now ++ // empty and has been removed from the list. ++ // This is a birth associated with a LinAB. The chunk ++ // for the LinAB is not in the dictionary. ++} ++ ++bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { ++ if (FLSAlwaysCoalesceLarge) return true; ++ ++ TreeList >* list_of_size = find_list(size); ++ // None of requested size implies overpopulated. ++ return list_of_size == NULL || list_of_size->coal_desired() <= 0 || ++ list_of_size->count() > list_of_size->coal_desired(); ++} ++ ++// For each list in the tree, calculate the desired, desired ++// coalesce, count before sweep, and surplus before sweep. ++class BeginSweepClosure : public AscendTreeCensusClosure > { ++ double _percentage; ++ float _inter_sweep_current; ++ float _inter_sweep_estimate; ++ float _intra_sweep_estimate; ++ ++ public: ++ BeginSweepClosure(double p, float inter_sweep_current, ++ float inter_sweep_estimate, ++ float intra_sweep_estimate) : ++ _percentage(p), ++ _inter_sweep_current(inter_sweep_current), ++ _inter_sweep_estimate(inter_sweep_estimate), ++ _intra_sweep_estimate(intra_sweep_estimate) { } ++ ++ void do_list(AdaptiveFreeList* fl) { ++ double coalSurplusPercent = _percentage; ++ fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); ++ fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent)); ++ fl->set_before_sweep(fl->count()); ++ fl->set_bfr_surp(fl->surplus()); ++ } ++}; ++ ++void AFLBinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent, ++ float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { ++ BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, ++ inter_sweep_estimate, ++ intra_sweep_estimate); ++ bsc.do_tree(root()); ++} ++ ++// Calculate surpluses for the lists in the tree. ++class setTreeSurplusClosure : public AscendTreeCensusClosure > { ++ double percentage; ++ public: ++ setTreeSurplusClosure(double v) { percentage = v; } ++ ++ void do_list(AdaptiveFreeList* fl) { ++ double splitSurplusPercent = percentage; ++ fl->set_surplus(fl->count() - ++ (ssize_t)((double)fl->desired() * splitSurplusPercent)); ++ } ++}; ++ ++void AFLBinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) { ++ setTreeSurplusClosure sts(splitSurplusPercent); ++ sts.do_tree(root()); ++} ++ ++// Set hints for the lists in the tree. ++class setTreeHintsClosure : public DescendTreeCensusClosure > { ++ size_t hint; ++ public: ++ setTreeHintsClosure(size_t v) { hint = v; } ++ ++ void do_list(AdaptiveFreeList* fl) { ++ fl->set_hint(hint); ++ assert(fl->hint() == 0 || fl->hint() > fl->size(), ++ "Current hint is inconsistent"); ++ if (fl->surplus() > 0) { ++ hint = fl->size(); ++ } ++ } ++}; ++ ++void AFLBinaryTreeDictionary::set_tree_hints(void) { ++ setTreeHintsClosure sth(0); ++ sth.do_tree(root()); ++} ++ ++// Save count before previous sweep and splits and coalesces. ++class clearTreeCensusClosure : public AscendTreeCensusClosure > { ++ void do_list(AdaptiveFreeList* fl) { ++ fl->set_prev_sweep(fl->count()); ++ fl->set_coal_births(0); ++ fl->set_coal_deaths(0); ++ fl->set_split_births(0); ++ fl->set_split_deaths(0); ++ } ++}; ++ ++void AFLBinaryTreeDictionary::clear_tree_census(void) { ++ clearTreeCensusClosure ctc; ++ ctc.do_tree(root()); ++} ++ ++// Do reporting and post sweep clean up. ++void AFLBinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) { ++ // Does walking the tree 3 times hurt? ++ set_tree_surplus(splitSurplusPercent); ++ set_tree_hints(); ++ LogTarget(Trace, gc, freelist, stats) log; ++ if (log.is_enabled()) { ++ LogStream out(log); ++ report_statistics(&out); ++ } ++ clear_tree_census(); ++} ++ ++// Print census information - counts, births, deaths, etc. ++// for each list in the tree. Also print some summary ++// information. ++class PrintTreeCensusClosure : public AscendTreeCensusClosure > { ++ int _print_line; ++ size_t _total_free; ++ AdaptiveFreeList _total; ++ ++ public: ++ PrintTreeCensusClosure() { ++ _print_line = 0; ++ _total_free = 0; ++ } ++ AdaptiveFreeList* total() { return &_total; } ++ size_t total_free() { return _total_free; } ++ ++ void do_list(AdaptiveFreeList* fl) { ++ LogStreamHandle(Debug, gc, freelist, census) out; ++ ++ if (++_print_line >= 40) { ++ AdaptiveFreeList::print_labels_on(&out, "size"); ++ _print_line = 0; ++ } ++ fl->print_on(&out); ++ _total_free += fl->count() * fl->size() ; ++ total()->set_count( total()->count() + fl->count() ); ++ total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() ); ++ total()->set_surplus( total()->split_deaths() + fl->surplus() ); ++ total()->set_desired( total()->desired() + fl->desired() ); ++ total()->set_prev_sweep( total()->prev_sweep() + fl->prev_sweep() ); ++ total()->set_before_sweep(total()->before_sweep() + fl->before_sweep()); ++ total()->set_coal_births( total()->coal_births() + fl->coal_births() ); ++ total()->set_coal_deaths( total()->coal_deaths() + fl->coal_deaths() ); ++ total()->set_split_births(total()->split_births() + fl->split_births()); ++ total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); ++ } ++}; ++ ++void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const { ++ ++ st->print_cr("BinaryTree"); ++ AdaptiveFreeList::print_labels_on(st, "size"); ++ PrintTreeCensusClosure ptc; ++ ptc.do_tree(root()); ++ ++ AdaptiveFreeList* total = ptc.total(); ++ AdaptiveFreeList::print_labels_on(st, " "); ++ total->print_on(st, "TOTAL\t"); ++ st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f deficit: %8.5f", ++ ptc.total_free(), ++ (double)(total->split_births() + total->coal_births() ++ - total->split_deaths() - total->coal_deaths()) ++ /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0), ++ (double)(total->desired() - total->count()) ++ /(total->desired() != 0 ? (double)total->desired() : 1.0)); ++} ++ ++///////////////////////////////////////////////////////////////////////// ++//// CompactibleFreeListSpace ++///////////////////////////////////////////////////////////////////////// ++ ++// highest ranked free list lock rank ++int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3; ++ ++// Defaults are 0 so things will break badly if incorrectly initialized. ++size_t CompactibleFreeListSpace::IndexSetStart = 0; ++size_t CompactibleFreeListSpace::IndexSetStride = 0; ++size_t CompactibleFreeListSpace::_min_chunk_size_in_bytes = 0; ++ ++size_t MinChunkSize = 0; ++ ++void CompactibleFreeListSpace::set_cms_values() { ++ // Set CMS global values ++ assert(MinChunkSize == 0, "already set"); ++ ++ // MinChunkSize should be a multiple of MinObjAlignment and be large enough ++ // for chunks to contain a FreeChunk. ++ _min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes); ++ MinChunkSize = _min_chunk_size_in_bytes / BytesPerWord; ++ ++ assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); ++ IndexSetStart = MinChunkSize; ++ IndexSetStride = MinObjAlignment; ++} ++ ++// Constructor ++CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) : ++ _bt(bs, mr), ++ // free list locks are in the range of values taken by _lockRank ++ // This range currently is [_leaf+2, _leaf+3] ++ // Note: this requires that CFLspace c'tors ++ // are called serially in the order in which the locks are ++ // are acquired in the program text. This is true today. ++ _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true, ++ Monitor::_safepoint_check_sometimes), ++ _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1 ++ "CompactibleFreeListSpace._dict_par_lock", true, ++ Monitor::_safepoint_check_never), ++ _rescan_task_size(CardTable::card_size_in_words * BitsPerWord * ++ CMSRescanMultiple), ++ _marking_task_size(CardTable::card_size_in_words * BitsPerWord * ++ CMSConcMarkMultiple), ++ _collector(NULL), ++ _preconsumptionDirtyCardClosure(NULL) ++{ ++ assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, ++ "FreeChunk is larger than expected"); ++ _bt.set_space(this); ++ initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); ++ ++ _dictionary = new AFLBinaryTreeDictionary(mr); ++ ++ assert(_dictionary != NULL, "CMS dictionary initialization"); ++ // The indexed free lists are initially all empty and are lazily ++ // filled in on demand. Initialize the array elements to NULL. ++ initializeIndexedFreeListArray(); ++ ++ _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, ++ SmallForLinearAlloc); ++ ++ // CMSIndexedFreeListReplenish should be at least 1 ++ CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish); ++ _promoInfo.setSpace(this); ++ if (UseCMSBestFit) { ++ _fitStrategy = FreeBlockBestFitFirst; ++ } else { ++ _fitStrategy = FreeBlockStrategyNone; ++ } ++ check_free_list_consistency(); ++ ++ // Initialize locks for parallel case. ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 ++ "a freelist par lock", true, Mutex::_safepoint_check_sometimes); ++ DEBUG_ONLY( ++ _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); ++ ) ++ } ++ _dictionary->set_par_lock(&_parDictionaryAllocLock); ++ ++ _used_stable = 0; ++} ++ ++HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size, ++ CompactPoint* cp, HeapWord* compact_top) { ++ ShouldNotReachHere(); ++ return NULL; ++} ++ ++// Like CompactibleSpace forward() but always calls cross_threshold() to ++// update the block offset table. Removed initialize_threshold call because ++// CFLS does not use a block offset array for contiguous spaces. ++HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size, ++ CompactPoint* cp, HeapWord* compact_top) { ++ // q is alive ++ // First check if we should switch compaction space ++ assert(this == cp->space, "'this' should be current compaction space."); ++ size_t compaction_max_size = pointer_delta(end(), compact_top); ++ assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), ++ "virtual adjustObjectSize_v() method is not correct"); ++ size_t adjusted_size = adjustObjectSize(size); ++ assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, ++ "no small fragments allowed"); ++ assert(minimum_free_block_size() == MinChunkSize, ++ "for de-virtualized reference below"); ++ // Can't leave a nonzero size, residual fragment smaller than MinChunkSize ++ if (adjusted_size + MinChunkSize > compaction_max_size && ++ adjusted_size != compaction_max_size) { ++ do { ++ // switch to next compaction space ++ cp->space->set_compaction_top(compact_top); ++ cp->space = cp->space->next_compaction_space(); ++ if (cp->space == NULL) { ++ cp->gen = CMSHeap::heap()->young_gen(); ++ assert(cp->gen != NULL, "compaction must succeed"); ++ cp->space = cp->gen->first_compaction_space(); ++ assert(cp->space != NULL, "generation must have a first compaction space"); ++ } ++ compact_top = cp->space->bottom(); ++ cp->space->set_compaction_top(compact_top); ++ // The correct adjusted_size may not be the same as that for this method ++ // (i.e., cp->space may no longer be "this" so adjust the size again. ++ // Use the virtual method which is not used above to save the virtual ++ // dispatch. ++ adjusted_size = cp->space->adjust_object_size_v(size); ++ compaction_max_size = pointer_delta(cp->space->end(), compact_top); ++ assert(cp->space->minimum_free_block_size() == 0, "just checking"); ++ } while (adjusted_size > compaction_max_size); ++ } ++ ++ // store the forwarding pointer into the mark word ++ if ((HeapWord*)q != compact_top) { ++ q->forward_to(oop(compact_top)); ++ assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); ++ } else { ++ // if the object isn't moving we can just set the mark to the default ++ // mark and handle it specially later on. ++ q->init_mark_raw(); ++ assert(q->forwardee() == NULL, "should be forwarded to NULL"); ++ } ++ ++ compact_top += adjusted_size; ++ ++ // we need to update the offset table so that the beginnings of objects can be ++ // found during scavenge. Note that we are updating the offset table based on ++ // where the object will be once the compaction phase finishes. ++ ++ // Always call cross_threshold(). A contiguous space can only call it when ++ // the compaction_top exceeds the current threshold but not for an ++ // non-contiguous space. ++ cp->threshold = ++ cp->space->cross_threshold(compact_top - adjusted_size, compact_top); ++ return compact_top; ++} ++ ++// A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt ++// and use of single_block instead of alloc_block. The name here is not really ++// appropriate - maybe a more general name could be invented for both the ++// contiguous and noncontiguous spaces. ++ ++HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) { ++ _bt.single_block(start, the_end); ++ return end(); ++} ++ ++// Initialize them to NULL. ++void CompactibleFreeListSpace::initializeIndexedFreeListArray() { ++ for (size_t i = 0; i < IndexSetSize; i++) { ++ // Note that on platforms where objects are double word aligned, ++ // the odd array elements are not used. It is convenient, however, ++ // to map directly from the object size to the array element. ++ _indexedFreeList[i].reset(IndexSetSize); ++ _indexedFreeList[i].set_size(i); ++ assert(_indexedFreeList[i].count() == 0, "reset check failed"); ++ assert(_indexedFreeList[i].head() == NULL, "reset check failed"); ++ assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); ++ assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); ++ } ++} ++ ++size_t CompactibleFreeListSpace::obj_size(const HeapWord* addr) const { ++ return adjustObjectSize(oop(addr)->size()); ++} ++ ++void CompactibleFreeListSpace::resetIndexedFreeListArray() { ++ for (size_t i = 1; i < IndexSetSize; i++) { ++ assert(_indexedFreeList[i].size() == (size_t) i, ++ "Indexed free list sizes are incorrect"); ++ _indexedFreeList[i].reset(IndexSetSize); ++ assert(_indexedFreeList[i].count() == 0, "reset check failed"); ++ assert(_indexedFreeList[i].head() == NULL, "reset check failed"); ++ assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); ++ assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); ++ } ++} ++ ++void CompactibleFreeListSpace::reset(MemRegion mr) { ++ resetIndexedFreeListArray(); ++ dictionary()->reset(); ++ if (BlockOffsetArrayUseUnallocatedBlock) { ++ assert(end() == mr.end(), "We are compacting to the bottom of CMS gen"); ++ // Everything's allocated until proven otherwise. ++ _bt.set_unallocated_block(end()); ++ } ++ if (!mr.is_empty()) { ++ assert(mr.word_size() >= MinChunkSize, "Chunk size is too small"); ++ _bt.single_block(mr.start(), mr.word_size()); ++ FreeChunk* fc = (FreeChunk*) mr.start(); ++ fc->set_size(mr.word_size()); ++ if (mr.word_size() >= IndexSetSize ) { ++ returnChunkToDictionary(fc); ++ } else { ++ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); ++ _indexedFreeList[mr.word_size()].return_chunk_at_head(fc); ++ } ++ coalBirth(mr.word_size()); ++ } ++ _promoInfo.reset(); ++ _smallLinearAllocBlock._ptr = NULL; ++ _smallLinearAllocBlock._word_size = 0; ++} ++ ++void CompactibleFreeListSpace::reset_after_compaction() { ++ // Reset the space to the new reality - one free chunk. ++ MemRegion mr(compaction_top(), end()); ++ reset(mr); ++ // Now refill the linear allocation block(s) if possible. ++ refillLinearAllocBlocksIfNeeded(); ++} ++ ++// Walks the entire dictionary, returning a coterminal ++// chunk, if it exists. Use with caution since it involves ++// a potentially complete walk of a potentially large tree. ++FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() { ++ ++ assert_lock_strong(&_freelistLock); ++ ++ return dictionary()->find_chunk_ends_at(end()); ++} ++ ++ ++#ifndef PRODUCT ++void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() { ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ _indexedFreeList[i].allocation_stats()->set_returned_bytes(0); ++ } ++} ++ ++size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() { ++ size_t sum = 0; ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ sum += _indexedFreeList[i].allocation_stats()->returned_bytes(); ++ } ++ return sum; ++} ++ ++size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const { ++ size_t count = 0; ++ for (size_t i = IndexSetStart; i < IndexSetSize; i++) { ++ debug_only( ++ ssize_t total_list_count = 0; ++ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; ++ fc = fc->next()) { ++ total_list_count++; ++ } ++ assert(total_list_count == _indexedFreeList[i].count(), ++ "Count in list is incorrect"); ++ ) ++ count += _indexedFreeList[i].count(); ++ } ++ return count; ++} ++ ++size_t CompactibleFreeListSpace::totalCount() { ++ size_t num = totalCountInIndexedFreeLists(); ++ num += dictionary()->total_count(); ++ if (_smallLinearAllocBlock._word_size != 0) { ++ num++; ++ } ++ return num; ++} ++#endif ++ ++bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const { ++ FreeChunk* fc = (FreeChunk*) p; ++ return fc->is_free(); ++} ++ ++size_t CompactibleFreeListSpace::used() const { ++ return capacity() - free(); ++} ++ ++size_t CompactibleFreeListSpace::used_stable() const { ++ return _used_stable; ++} ++ ++void CompactibleFreeListSpace::recalculate_used_stable() { ++ _used_stable = used(); ++} ++ ++size_t CompactibleFreeListSpace::free() const { ++ // "MT-safe, but not MT-precise"(TM), if you will: i.e. ++ // if you do this while the structures are in flux you ++ // may get an approximate answer only; for instance ++ // because there is concurrent allocation either ++ // directly by mutators or for promotion during a GC. ++ // It's "MT-safe", however, in the sense that you are guaranteed ++ // not to crash and burn, for instance, because of walking ++ // pointers that could disappear as you were walking them. ++ // The approximation is because the various components ++ // that are read below are not read atomically (and ++ // further the computation of totalSizeInIndexedFreeLists() ++ // is itself a non-atomic computation. The normal use of ++ // this is during a resize operation at the end of GC ++ // and at that time you are guaranteed to get the ++ // correct actual value. However, for instance, this is ++ // also read completely asynchronously by the "perf-sampler" ++ // that supports jvmstat, and you are apt to see the values ++ // flicker in such cases. ++ assert(_dictionary != NULL, "No _dictionary?"); ++ return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) + ++ totalSizeInIndexedFreeLists() + ++ _smallLinearAllocBlock._word_size) * HeapWordSize; ++} ++ ++size_t CompactibleFreeListSpace::max_alloc_in_words() const { ++ assert(_dictionary != NULL, "No _dictionary?"); ++ assert_locked(); ++ size_t res = _dictionary->max_chunk_size(); ++ res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, ++ (size_t) SmallForLinearAlloc - 1)); ++ // XXX the following could potentially be pretty slow; ++ // should one, pessimistically for the rare cases when res ++ // calculated above is less than IndexSetSize, ++ // just return res calculated above? My reasoning was that ++ // those cases will be so rare that the extra time spent doesn't ++ // really matter.... ++ // Note: do not change the loop test i >= res + IndexSetStride ++ // to i > res below, because i is unsigned and res may be zero. ++ for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride; ++ i -= IndexSetStride) { ++ if (_indexedFreeList[i].head() != NULL) { ++ assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); ++ return i; ++ } ++ } ++ return res; ++} ++ ++void LinearAllocBlock::print_on(outputStream* st) const { ++ st->print_cr(" LinearAllocBlock: ptr = " PTR_FORMAT ", word_size = " SIZE_FORMAT ++ ", refillsize = " SIZE_FORMAT ", allocation_size_limit = " SIZE_FORMAT, ++ p2i(_ptr), _word_size, _refillSize, _allocation_size_limit); ++} ++ ++void CompactibleFreeListSpace::print_on(outputStream* st) const { ++ st->print_cr("COMPACTIBLE FREELIST SPACE"); ++ st->print_cr(" Space:"); ++ Space::print_on(st); ++ ++ st->print_cr("promoInfo:"); ++ _promoInfo.print_on(st); ++ ++ st->print_cr("_smallLinearAllocBlock"); ++ _smallLinearAllocBlock.print_on(st); ++ ++ // dump_memory_block(_smallLinearAllocBlock->_ptr, 128); ++ ++ st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy)); ++} ++ ++void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) ++const { ++ reportIndexedFreeListStatistics(st); ++ st->print_cr("Layout of Indexed Freelists"); ++ st->print_cr("---------------------------"); ++ AdaptiveFreeList::print_labels_on(st, "size"); ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ _indexedFreeList[i].print_on(st); ++ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; fc = fc->next()) { ++ st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", ++ p2i(fc), p2i((HeapWord*)fc + i), ++ fc->cantCoalesce() ? "\t CC" : ""); ++ } ++ } ++} ++ ++void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st) ++const { ++ _promoInfo.print_on(st); ++} ++ ++void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st) ++const { ++ _dictionary->report_statistics(st); ++ st->print_cr("Layout of Freelists in Tree"); ++ st->print_cr("---------------------------"); ++ _dictionary->print_free_lists(st); ++} ++ ++class BlkPrintingClosure: public BlkClosure { ++ const CMSCollector* _collector; ++ const CompactibleFreeListSpace* _sp; ++ const CMSBitMap* _live_bit_map; ++ const bool _post_remark; ++ outputStream* _st; ++public: ++ BlkPrintingClosure(const CMSCollector* collector, ++ const CompactibleFreeListSpace* sp, ++ const CMSBitMap* live_bit_map, ++ outputStream* st): ++ _collector(collector), ++ _sp(sp), ++ _live_bit_map(live_bit_map), ++ _post_remark(collector->abstract_state() > CMSCollector::FinalMarking), ++ _st(st) { } ++ size_t do_blk(HeapWord* addr); ++}; ++ ++size_t BlkPrintingClosure::do_blk(HeapWord* addr) { ++ size_t sz = _sp->block_size_no_stall(addr, _collector); ++ assert(sz != 0, "Should always be able to compute a size"); ++ if (_sp->block_is_obj(addr)) { ++ const bool dead = _post_remark && !_live_bit_map->isMarked(addr); ++ _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s", ++ p2i(addr), ++ dead ? "dead" : "live", ++ sz, ++ (!dead && CMSPrintObjectsInDump) ? ":" : "."); ++ if (CMSPrintObjectsInDump && !dead) { ++ oop(addr)->print_on(_st); ++ _st->print_cr("--------------------------------------"); ++ } ++ } else { // free block ++ _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s", ++ p2i(addr), sz, CMSPrintChunksInDump ? ":" : "."); ++ if (CMSPrintChunksInDump) { ++ ((FreeChunk*)addr)->print_on(_st); ++ _st->print_cr("--------------------------------------"); ++ } ++ } ++ return sz; ++} ++ ++void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st) { ++ st->print_cr("========================="); ++ st->print_cr("Block layout in CMS Heap:"); ++ st->print_cr("========================="); ++ BlkPrintingClosure bpcl(c, this, c->markBitMap(), st); ++ blk_iterate(&bpcl); ++ ++ st->print_cr("======================================="); ++ st->print_cr("Order & Layout of Promotion Info Blocks"); ++ st->print_cr("======================================="); ++ print_promo_info_blocks(st); ++ ++ st->print_cr("==========================="); ++ st->print_cr("Order of Indexed Free Lists"); ++ st->print_cr("========================="); ++ print_indexed_free_lists(st); ++ ++ st->print_cr("================================="); ++ st->print_cr("Order of Free Lists in Dictionary"); ++ st->print_cr("================================="); ++ print_dictionary_free_lists(st); ++} ++ ++ ++void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const { ++ assert_lock_strong(&_freelistLock); ++ Log(gc, freelist, stats) log; ++ if (!log.is_debug()) { ++ return; ++ } ++ log.debug("%s", title); ++ ++ LogStream out(log.debug()); ++ _dictionary->report_statistics(&out); ++ ++ if (log.is_trace()) { ++ LogStream trace_out(log.trace()); ++ reportIndexedFreeListStatistics(&trace_out); ++ size_t total_size = totalSizeInIndexedFreeLists() + ++ _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); ++ log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); ++ } ++} ++ ++void CompactibleFreeListSpace::reportIndexedFreeListStatistics(outputStream* st) const { ++ assert_lock_strong(&_freelistLock); ++ st->print_cr("Statistics for IndexedFreeLists:"); ++ st->print_cr("--------------------------------"); ++ size_t total_size = totalSizeInIndexedFreeLists(); ++ size_t free_blocks = numFreeBlocksInIndexedFreeLists(); ++ st->print_cr("Total Free Space: " SIZE_FORMAT, total_size); ++ st->print_cr("Max Chunk Size: " SIZE_FORMAT, maxChunkSizeInIndexedFreeLists()); ++ st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks); ++ if (free_blocks != 0) { ++ st->print_cr("Av. Block Size: " SIZE_FORMAT, total_size/free_blocks); ++ } ++} ++ ++size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { ++ size_t res = 0; ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ debug_only( ++ ssize_t recount = 0; ++ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; ++ fc = fc->next()) { ++ recount += 1; ++ } ++ assert(recount == _indexedFreeList[i].count(), ++ "Incorrect count in list"); ++ ) ++ res += _indexedFreeList[i].count(); ++ } ++ return res; ++} ++ ++size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const { ++ for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { ++ if (_indexedFreeList[i].head() != NULL) { ++ assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); ++ return (size_t)i; ++ } ++ } ++ return 0; ++} ++ ++void CompactibleFreeListSpace::set_end(HeapWord* value) { ++ HeapWord* prevEnd = end(); ++ assert(prevEnd != value, "unnecessary set_end call"); ++ assert(prevEnd == NULL || !BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), ++ "New end is below unallocated block"); ++ _end = value; ++ if (prevEnd != NULL) { ++ // Resize the underlying block offset table. ++ _bt.resize(pointer_delta(value, bottom())); ++ if (value <= prevEnd) { ++ assert(!BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), ++ "New end is below unallocated block"); ++ } else { ++ // Now, take this new chunk and add it to the free blocks. ++ // Note that the BOT has not yet been updated for this block. ++ size_t newFcSize = pointer_delta(value, prevEnd); ++ // Add the block to the free lists, if possible coalescing it ++ // with the last free block, and update the BOT and census data. ++ addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); ++ } ++ } ++} ++ ++class FreeListSpaceDCTOC : public FilteringDCTOC { ++ CompactibleFreeListSpace* _cfls; ++ CMSCollector* _collector; ++ bool _parallel; ++protected: ++ // Override. ++#define walk_mem_region_with_cl_DECL(ClosureType) \ ++ virtual void walk_mem_region_with_cl(MemRegion mr, \ ++ HeapWord* bottom, HeapWord* top, \ ++ ClosureType* cl); \ ++ void walk_mem_region_with_cl_par(MemRegion mr, \ ++ HeapWord* bottom, HeapWord* top, \ ++ ClosureType* cl); \ ++ void walk_mem_region_with_cl_nopar(MemRegion mr, \ ++ HeapWord* bottom, HeapWord* top, \ ++ ClosureType* cl) ++ walk_mem_region_with_cl_DECL(OopIterateClosure); ++ walk_mem_region_with_cl_DECL(FilteringClosure); ++ ++public: ++ FreeListSpaceDCTOC(CompactibleFreeListSpace* sp, ++ CMSCollector* collector, ++ OopIterateClosure* cl, ++ CardTable::PrecisionStyle precision, ++ HeapWord* boundary, ++ bool parallel) : ++ FilteringDCTOC(sp, cl, precision, boundary), ++ _cfls(sp), _collector(collector), _parallel(parallel) {} ++}; ++ ++// We de-virtualize the block-related calls below, since we know that our ++// space is a CompactibleFreeListSpace. ++ ++#define FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \ ++void FreeListSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \ ++ HeapWord* bottom, \ ++ HeapWord* top, \ ++ ClosureType* cl) { \ ++ if (_parallel) { \ ++ walk_mem_region_with_cl_par(mr, bottom, top, cl); \ ++ } else { \ ++ walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \ ++ } \ ++} \ ++void FreeListSpaceDCTOC::walk_mem_region_with_cl_par(MemRegion mr, \ ++ HeapWord* bottom, \ ++ HeapWord* top, \ ++ ClosureType* cl) { \ ++ /* Skip parts that are before "mr", in case "block_start" sent us \ ++ back too far. */ \ ++ HeapWord* mr_start = mr.start(); \ ++ size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ ++ HeapWord* next = bottom + bot_size; \ ++ while (next < mr_start) { \ ++ bottom = next; \ ++ bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ ++ next = bottom + bot_size; \ ++ } \ ++ \ ++ while (bottom < top) { \ ++ if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) && \ ++ !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ ++ oop(bottom)) && \ ++ !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ ++ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ ++ bottom += _cfls->adjustObjectSize(word_sz); \ ++ } else { \ ++ bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \ ++ } \ ++ } \ ++} \ ++void FreeListSpaceDCTOC::walk_mem_region_with_cl_nopar(MemRegion mr, \ ++ HeapWord* bottom, \ ++ HeapWord* top, \ ++ ClosureType* cl) { \ ++ /* Skip parts that are before "mr", in case "block_start" sent us \ ++ back too far. */ \ ++ HeapWord* mr_start = mr.start(); \ ++ size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ ++ HeapWord* next = bottom + bot_size; \ ++ while (next < mr_start) { \ ++ bottom = next; \ ++ bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ ++ next = bottom + bot_size; \ ++ } \ ++ \ ++ while (bottom < top) { \ ++ if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) && \ ++ !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ ++ oop(bottom)) && \ ++ !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ ++ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ ++ bottom += _cfls->adjustObjectSize(word_sz); \ ++ } else { \ ++ bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ ++ } \ ++ } \ ++} ++ ++// (There are only two of these, rather than N, because the split is due ++// only to the introduction of the FilteringClosure, a local part of the ++// impl of this abstraction.) ++FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure) ++FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) ++ ++DirtyCardToOopClosure* ++CompactibleFreeListSpace::new_dcto_cl(OopIterateClosure* cl, ++ CardTable::PrecisionStyle precision, ++ HeapWord* boundary, ++ bool parallel) { ++ return new FreeListSpaceDCTOC(this, _collector, cl, precision, boundary, parallel); ++} ++ ++ ++// Note on locking for the space iteration functions: ++// since the collector's iteration activities are concurrent with ++// allocation activities by mutators, absent a suitable mutual exclusion ++// mechanism the iterators may go awry. For instance a block being iterated ++// may suddenly be allocated or divided up and part of it allocated and ++// so on. ++ ++// Apply the given closure to each block in the space. ++void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) { ++ assert_lock_strong(freelistLock()); ++ HeapWord *cur, *limit; ++ for (cur = bottom(), limit = end(); cur < limit; ++ cur += cl->do_blk_careful(cur)); ++} ++ ++// Apply the given closure to each block in the space. ++void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) { ++ assert_lock_strong(freelistLock()); ++ HeapWord *cur, *limit; ++ for (cur = bottom(), limit = end(); cur < limit; ++ cur += cl->do_blk(cur)); ++} ++ ++// Apply the given closure to each oop in the space. ++void CompactibleFreeListSpace::oop_iterate(OopIterateClosure* cl) { ++ assert_lock_strong(freelistLock()); ++ HeapWord *cur, *limit; ++ size_t curSize; ++ for (cur = bottom(), limit = end(); cur < limit; ++ cur += curSize) { ++ curSize = block_size(cur); ++ if (block_is_obj(cur)) { ++ oop(cur)->oop_iterate(cl); ++ } ++ } ++} ++ ++// NOTE: In the following methods, in order to safely be able to ++// apply the closure to an object, we need to be sure that the ++// object has been initialized. We are guaranteed that an object ++// is initialized if we are holding the Heap_lock with the ++// world stopped. ++void CompactibleFreeListSpace::verify_objects_initialized() const { ++ if (is_init_completed()) { ++ assert_locked_or_safepoint(Heap_lock); ++ if (Universe::is_fully_initialized()) { ++ guarantee(SafepointSynchronize::is_at_safepoint(), ++ "Required for objects to be initialized"); ++ } ++ } // else make a concession at vm start-up ++} ++ ++// Apply the given closure to each object in the space ++void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { ++ assert_lock_strong(freelistLock()); ++ NOT_PRODUCT(verify_objects_initialized()); ++ HeapWord *cur, *limit; ++ size_t curSize; ++ for (cur = bottom(), limit = end(); cur < limit; ++ cur += curSize) { ++ curSize = block_size(cur); ++ if (block_is_obj(cur)) { ++ blk->do_object(oop(cur)); ++ } ++ } ++} ++ ++// Apply the given closure to each live object in the space ++// The usage of CompactibleFreeListSpace ++// by the ConcurrentMarkSweepGeneration for concurrent GC's allows ++// objects in the space with references to objects that are no longer ++// valid. For example, an object may reference another object ++// that has already been sweep up (collected). This method uses ++// obj_is_alive() to determine whether it is safe to apply the closure to ++// an object. See obj_is_alive() for details on how liveness of an ++// object is decided. ++ ++void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { ++ assert_lock_strong(freelistLock()); ++ NOT_PRODUCT(verify_objects_initialized()); ++ HeapWord *cur, *limit; ++ size_t curSize; ++ for (cur = bottom(), limit = end(); cur < limit; ++ cur += curSize) { ++ curSize = block_size(cur); ++ if (block_is_obj(cur) && obj_is_alive(cur)) { ++ blk->do_object(oop(cur)); ++ } ++ } ++} ++ ++void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, ++ UpwardsObjectClosure* cl) { ++ assert_locked(freelistLock()); ++ NOT_PRODUCT(verify_objects_initialized()); ++ assert(!mr.is_empty(), "Should be non-empty"); ++ // We use MemRegion(bottom(), end()) rather than used_region() below ++ // because the two are not necessarily equal for some kinds of ++ // spaces, in particular, certain kinds of free list spaces. ++ // We could use the more complicated but more precise: ++ // MemRegion(used_region().start(), align_up(used_region().end(), CardSize)) ++ // but the slight imprecision seems acceptable in the assertion check. ++ assert(MemRegion(bottom(), end()).contains(mr), ++ "Should be within used space"); ++ HeapWord* prev = cl->previous(); // max address from last time ++ if (prev >= mr.end()) { // nothing to do ++ return; ++ } ++ // This assert will not work when we go from cms space to perm ++ // space, and use same closure. Easy fix deferred for later. XXX YSR ++ // assert(prev == NULL || contains(prev), "Should be within space"); ++ ++ bool last_was_obj_array = false; ++ HeapWord *blk_start_addr, *region_start_addr; ++ if (prev > mr.start()) { ++ region_start_addr = prev; ++ blk_start_addr = prev; ++ // The previous invocation may have pushed "prev" beyond the ++ // last allocated block yet there may be still be blocks ++ // in this region due to a particular coalescing policy. ++ // Relax the assertion so that the case where the unallocated ++ // block is maintained and "prev" is beyond the unallocated ++ // block does not cause the assertion to fire. ++ assert((BlockOffsetArrayUseUnallocatedBlock && ++ (!is_in(prev))) || ++ (blk_start_addr == block_start(region_start_addr)), "invariant"); ++ } else { ++ region_start_addr = mr.start(); ++ blk_start_addr = block_start(region_start_addr); ++ } ++ HeapWord* region_end_addr = mr.end(); ++ MemRegion derived_mr(region_start_addr, region_end_addr); ++ while (blk_start_addr < region_end_addr) { ++ const size_t size = block_size(blk_start_addr); ++ if (block_is_obj(blk_start_addr)) { ++ last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr); ++ } else { ++ last_was_obj_array = false; ++ } ++ blk_start_addr += size; ++ } ++ if (!last_was_obj_array) { ++ assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()), ++ "Should be within (closed) used space"); ++ assert(blk_start_addr > prev, "Invariant"); ++ cl->set_previous(blk_start_addr); // min address for next time ++ } ++} ++ ++// Callers of this iterator beware: The closure application should ++// be robust in the face of uninitialized objects and should (always) ++// return a correct size so that the next addr + size below gives us a ++// valid block boundary. [See for instance, ++// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful() ++// in ConcurrentMarkSweepGeneration.cpp.] ++HeapWord* ++CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr, ++ ObjectClosureCareful* cl) { ++ assert_lock_strong(freelistLock()); ++ // Can't use used_region() below because it may not necessarily ++ // be the same as [bottom(),end()); although we could ++ // use [used_region().start(),align_up(used_region().end(),CardSize)), ++ // that appears too cumbersome, so we just do the simpler check ++ // in the assertion below. ++ assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr), ++ "mr should be non-empty and within used space"); ++ HeapWord *addr, *end; ++ size_t size; ++ for (addr = block_start_careful(mr.start()), end = mr.end(); ++ addr < end; addr += size) { ++ FreeChunk* fc = (FreeChunk*)addr; ++ if (fc->is_free()) { ++ // Since we hold the free list lock, which protects direct ++ // allocation in this generation by mutators, a free object ++ // will remain free throughout this iteration code. ++ size = fc->size(); ++ } else { ++ // Note that the object need not necessarily be initialized, ++ // because (for instance) the free list lock does NOT protect ++ // object initialization. The closure application below must ++ // therefore be correct in the face of uninitialized objects. ++ size = cl->do_object_careful_m(oop(addr), mr); ++ if (size == 0) { ++ // An unparsable object found. Signal early termination. ++ return addr; ++ } ++ } ++ } ++ return NULL; ++} ++ ++ ++HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const { ++ NOT_PRODUCT(verify_objects_initialized()); ++ return _bt.block_start(p); ++} ++ ++HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const { ++ return _bt.block_start_careful(p); ++} ++ ++size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { ++ NOT_PRODUCT(verify_objects_initialized()); ++ // This must be volatile, or else there is a danger that the compiler ++ // will compile the code below into a sometimes-infinite loop, by keeping ++ // the value read the first time in a register. ++ while (true) { ++ // We must do this until we get a consistent view of the object. ++ if (FreeChunk::indicatesFreeChunk(p)) { ++ volatile FreeChunk* fc = (volatile FreeChunk*)p; ++ size_t res = fc->size(); ++ ++ // Bugfix for systems with weak memory model (PPC64/IA64). The ++ // block's free bit was set and we have read the size of the ++ // block. Acquire and check the free bit again. If the block is ++ // still free, the read size is correct. ++ OrderAccess::acquire(); ++ ++ // If the object is still a free chunk, return the size, else it ++ // has been allocated so try again. ++ if (FreeChunk::indicatesFreeChunk(p)) { ++ assert(res != 0, "Block size should not be 0"); ++ return res; ++ } ++ } else { ++ // Ensure klass read before size. ++ Klass* k = oop(p)->klass_or_null_acquire(); ++ if (k != NULL) { ++ assert(k->is_klass(), "Should really be klass oop."); ++ oop o = (oop)p; ++ assert(oopDesc::is_oop(o, true /* ignore mark word */), "Should be an oop."); ++ ++ size_t res = o->size_given_klass(k); ++ res = adjustObjectSize(res); ++ assert(res != 0, "Block size should not be 0"); ++ return res; ++ } ++ } ++ } ++} ++ ++// TODO: Now that is_parsable is gone, we should combine these two functions. ++// A variant of the above that uses the Printezis bits for ++// unparsable but allocated objects. This avoids any possible ++// stalls waiting for mutators to initialize objects, and is ++// thus potentially faster than the variant above. However, ++// this variant may return a zero size for a block that is ++// under mutation and for which a consistent size cannot be ++// inferred without stalling; see CMSCollector::block_size_if_printezis_bits(). ++size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p, ++ const CMSCollector* c) ++const { ++ assert(MemRegion(bottom(), end()).contains(p), "p not in space"); ++ // This must be volatile, or else there is a danger that the compiler ++ // will compile the code below into a sometimes-infinite loop, by keeping ++ // the value read the first time in a register. ++ DEBUG_ONLY(uint loops = 0;) ++ while (true) { ++ // We must do this until we get a consistent view of the object. ++ if (FreeChunk::indicatesFreeChunk(p)) { ++ volatile FreeChunk* fc = (volatile FreeChunk*)p; ++ size_t res = fc->size(); ++ ++ // Bugfix for systems with weak memory model (PPC64/IA64). The ++ // free bit of the block was set and we have read the size of ++ // the block. Acquire and check the free bit again. If the ++ // block is still free, the read size is correct. ++ OrderAccess::acquire(); ++ ++ if (FreeChunk::indicatesFreeChunk(p)) { ++ assert(res != 0, "Block size should not be 0"); ++ assert(loops == 0, "Should be 0"); ++ return res; ++ } ++ } else { ++ // Ensure klass read before size. ++ Klass* k = oop(p)->klass_or_null_acquire(); ++ if (k != NULL) { ++ assert(k->is_klass(), "Should really be klass oop."); ++ oop o = (oop)p; ++ assert(oopDesc::is_oop(o), "Should be an oop"); ++ ++ size_t res = o->size_given_klass(k); ++ res = adjustObjectSize(res); ++ assert(res != 0, "Block size should not be 0"); ++ return res; ++ } else { ++ // May return 0 if P-bits not present. ++ return c->block_size_if_printezis_bits(p); ++ } ++ } ++ assert(loops == 0, "Can loop at most once"); ++ DEBUG_ONLY(loops++;) ++ } ++} ++ ++size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const { ++ NOT_PRODUCT(verify_objects_initialized()); ++ assert(MemRegion(bottom(), end()).contains(p), "p not in space"); ++ FreeChunk* fc = (FreeChunk*)p; ++ if (fc->is_free()) { ++ return fc->size(); ++ } else { ++ // Ignore mark word because this may be a recently promoted ++ // object whose mark word is used to chain together grey ++ // objects (the last one would have a null value). ++ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); ++ return adjustObjectSize(oop(p)->size()); ++ } ++} ++ ++// This implementation assumes that the property of "being an object" is ++// stable. But being a free chunk may not be (because of parallel ++// promotion.) ++bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const { ++ FreeChunk* fc = (FreeChunk*)p; ++ assert(is_in_reserved(p), "Should be in space"); ++ if (FreeChunk::indicatesFreeChunk(p)) return false; ++ Klass* k = oop(p)->klass_or_null_acquire(); ++ if (k != NULL) { ++ // Ignore mark word because it may have been used to ++ // chain together promoted objects (the last one ++ // would have a null value). ++ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); ++ return true; ++ } else { ++ return false; // Was not an object at the start of collection. ++ } ++} ++ ++// Check if the object is alive. This fact is checked either by consulting ++// the main marking bitmap in the sweeping phase or, if it's a permanent ++// generation and we're not in the sweeping phase, by checking the ++// perm_gen_verify_bit_map where we store the "deadness" information if ++// we did not sweep the perm gen in the most recent previous GC cycle. ++bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const { ++ assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(), ++ "Else races are possible"); ++ assert(block_is_obj(p), "The address should point to an object"); ++ ++ // If we're sweeping, we use object liveness information from the main bit map ++ // for both perm gen and old gen. ++ // We don't need to lock the bitmap (live_map or dead_map below), because ++ // EITHER we are in the middle of the sweeping phase, and the ++ // main marking bit map (live_map below) is locked, ++ // OR we're in other phases and perm_gen_verify_bit_map (dead_map below) ++ // is stable, because it's mutated only in the sweeping phase. ++ // NOTE: This method is also used by jmap where, if class unloading is ++ // off, the results can return "false" for legitimate perm objects, ++ // when we are not in the midst of a sweeping phase, which can result ++ // in jmap not reporting certain perm gen objects. This will be moot ++ // if/when the perm gen goes away in the future. ++ if (_collector->abstract_state() == CMSCollector::Sweeping) { ++ CMSBitMap* live_map = _collector->markBitMap(); ++ return live_map->par_isMarked((HeapWord*) p); ++ } ++ return true; ++} ++ ++bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const { ++ FreeChunk* fc = (FreeChunk*)p; ++ assert(is_in_reserved(p), "Should be in space"); ++ assert(_bt.block_start(p) == p, "Should be a block boundary"); ++ if (!fc->is_free()) { ++ // Ignore mark word because it may have been used to ++ // chain together promoted objects (the last one ++ // would have a null value). ++ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); ++ return true; ++ } ++ return false; ++} ++ ++// "MT-safe but not guaranteed MT-precise" (TM); you may get an ++// approximate answer if you don't hold the freelistlock when you call this. ++size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const { ++ size_t size = 0; ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ debug_only( ++ // We may be calling here without the lock in which case we ++ // won't do this modest sanity check. ++ if (freelistLock()->owned_by_self()) { ++ size_t total_list_size = 0; ++ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; ++ fc = fc->next()) { ++ total_list_size += i; ++ } ++ assert(total_list_size == i * _indexedFreeList[i].count(), ++ "Count in list is incorrect"); ++ } ++ ) ++ size += i * _indexedFreeList[i].count(); ++ } ++ return size; ++} ++ ++HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) { ++ MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); ++ return allocate(size); ++} ++ ++HeapWord* ++CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) { ++ return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size); ++} ++ ++HeapWord* CompactibleFreeListSpace::allocate(size_t size) { ++ assert_lock_strong(freelistLock()); ++ HeapWord* res = NULL; ++ assert(size == adjustObjectSize(size), ++ "use adjustObjectSize() before calling into allocate()"); ++ ++ res = allocate_adaptive_freelists(size); ++ ++ if (res != NULL) { ++ // check that res does lie in this space! ++ assert(is_in_reserved(res), "Not in this space!"); ++ assert(is_aligned((void*)res), "alignment check"); ++ ++ FreeChunk* fc = (FreeChunk*)res; ++ fc->markNotFree(); ++ assert(!fc->is_free(), "shouldn't be marked free"); ++ assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized"); ++ // Verify that the block offset table shows this to ++ // be a single block, but not one which is unallocated. ++ _bt.verify_single_block(res, size); ++ _bt.verify_not_unallocated(res, size); ++ // mangle a just allocated object with a distinct pattern. ++ debug_only(fc->mangleAllocated(size)); ++ } ++ ++ // During GC we do not need to recalculate the stable used value for ++ // every allocation in old gen. It is done once at the end of GC instead ++ // for performance reasons. ++ if (!CMSHeap::heap()->is_gc_active()) { ++ recalculate_used_stable(); ++ } ++ ++ return res; ++} ++ ++HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) { ++ assert_lock_strong(freelistLock()); ++ HeapWord* res = NULL; ++ assert(size == adjustObjectSize(size), ++ "use adjustObjectSize() before calling into allocate()"); ++ ++ // Strategy ++ // if small ++ // exact size from small object indexed list if small ++ // small or large linear allocation block (linAB) as appropriate ++ // take from lists of greater sized chunks ++ // else ++ // dictionary ++ // small or large linear allocation block if it has the space ++ // Try allocating exact size from indexTable first ++ if (size < IndexSetSize) { ++ res = (HeapWord*) getChunkFromIndexedFreeList(size); ++ if(res != NULL) { ++ assert(res != (HeapWord*)_indexedFreeList[size].head(), ++ "Not removed from free list"); ++ // no block offset table adjustment is necessary on blocks in ++ // the indexed lists. ++ ++ // Try allocating from the small LinAB ++ } else if (size < _smallLinearAllocBlock._allocation_size_limit && ++ (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) { ++ // if successful, the above also adjusts block offset table ++ // Note that this call will refill the LinAB to ++ // satisfy the request. This is different that ++ // evm. ++ // Don't record chunk off a LinAB? smallSplitBirth(size); ++ } else { ++ // Raid the exact free lists larger than size, even if they are not ++ // overpopulated. ++ res = (HeapWord*) getChunkFromGreater(size); ++ } ++ } else { ++ // Big objects get allocated directly from the dictionary. ++ res = (HeapWord*) getChunkFromDictionaryExact(size); ++ if (res == NULL) { ++ // Try hard not to fail since an allocation failure will likely ++ // trigger a synchronous GC. Try to get the space from the ++ // allocation blocks. ++ res = getChunkFromSmallLinearAllocBlockRemainder(size); ++ } ++ } ++ ++ return res; ++} ++ ++// A worst-case estimate of the space required (in HeapWords) to expand the heap ++// when promoting obj. ++size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const { ++ // Depending on the object size, expansion may require refilling either a ++ // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize ++ // is added because the dictionary may over-allocate to avoid fragmentation. ++ size_t space = obj_size; ++ space += _promoInfo.refillSize() + 2 * MinChunkSize; ++ return space; ++} ++ ++FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) { ++ FreeChunk* ret; ++ ++ assert(numWords >= MinChunkSize, "Size is less than minimum"); ++ assert(linearAllocationWouldFail() || bestFitFirst(), ++ "Should not be here"); ++ ++ size_t i; ++ size_t currSize = numWords + MinChunkSize; ++ assert(is_object_aligned(currSize), "currSize should be aligned"); ++ for (i = currSize; i < IndexSetSize; i += IndexSetStride) { ++ AdaptiveFreeList* fl = &_indexedFreeList[i]; ++ if (fl->head()) { ++ ret = getFromListGreater(fl, numWords); ++ assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); ++ return ret; ++ } ++ } ++ ++ currSize = MAX2((size_t)SmallForDictionary, ++ (size_t)(numWords + MinChunkSize)); ++ ++ /* Try to get a chunk that satisfies request, while avoiding ++ fragmentation that can't be handled. */ ++ { ++ ret = dictionary()->get_chunk(currSize); ++ if (ret != NULL) { ++ assert(ret->size() - numWords >= MinChunkSize, ++ "Chunk is too small"); ++ _bt.allocated((HeapWord*)ret, ret->size()); ++ /* Carve returned chunk. */ ++ (void) splitChunkAndReturnRemainder(ret, numWords); ++ /* Label this as no longer a free chunk. */ ++ assert(ret->is_free(), "This chunk should be free"); ++ ret->link_prev(NULL); ++ } ++ assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); ++ return ret; ++ } ++ ShouldNotReachHere(); ++} ++ ++bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { ++ assert(fc->size() < IndexSetSize, "Size of chunk is too large"); ++ return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc); ++} ++ ++bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { ++ assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || ++ (_smallLinearAllocBlock._word_size == fc->size()), ++ "Linear allocation block shows incorrect size"); ++ return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && ++ (_smallLinearAllocBlock._word_size == fc->size())); ++} ++ ++// Check if the purported free chunk is present either as a linear ++// allocation block, the size-indexed table of (smaller) free blocks, ++// or the larger free blocks kept in the binary tree dictionary. ++bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const { ++ if (verify_chunk_is_linear_alloc_block(fc)) { ++ return true; ++ } else if (fc->size() < IndexSetSize) { ++ return verifyChunkInIndexedFreeLists(fc); ++ } else { ++ return dictionary()->verify_chunk_in_free_list(fc); ++ } ++} ++ ++#ifndef PRODUCT ++void CompactibleFreeListSpace::assert_locked() const { ++ CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock()); ++} ++ ++void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const { ++ CMSLockVerifier::assert_locked(lock); ++} ++#endif ++ ++FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { ++ // In the parallel case, the main thread holds the free list lock ++ // on behalf the parallel threads. ++ FreeChunk* fc; ++ { ++ // If GC is parallel, this might be called by several threads. ++ // This should be rare enough that the locking overhead won't affect ++ // the sequential code. ++ MutexLockerEx x(parDictionaryAllocLock(), ++ Mutex::_no_safepoint_check_flag); ++ fc = getChunkFromDictionary(size); ++ } ++ if (fc != NULL) { ++ fc->dontCoalesce(); ++ assert(fc->is_free(), "Should be free, but not coalescable"); ++ // Verify that the block offset table shows this to ++ // be a single block, but not one which is unallocated. ++ _bt.verify_single_block((HeapWord*)fc, fc->size()); ++ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); ++ } ++ return fc; ++} ++ ++oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) { ++ assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); ++ assert_locked(); ++ ++ // if we are tracking promotions, then first ensure space for ++ // promotion (including spooling space for saving header if necessary). ++ // then allocate and copy, then track promoted info if needed. ++ // When tracking (see PromotionInfo::track()), the mark word may ++ // be displaced and in this case restoration of the mark word ++ // occurs in the (oop_since_save_marks_)iterate phase. ++ if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) { ++ return NULL; ++ } ++ // Call the allocate(size_t, bool) form directly to avoid the ++ // additional call through the allocate(size_t) form. Having ++ // the compile inline the call is problematic because allocate(size_t) ++ // is a virtual method. ++ HeapWord* res = allocate(adjustObjectSize(obj_size)); ++ if (res != NULL) { ++ Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size); ++ // if we should be tracking promotions, do so. ++ if (_promoInfo.tracking()) { ++ _promoInfo.track((PromotedObject*)res); ++ } ++ } ++ return oop(res); ++} ++ ++HeapWord* ++CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) { ++ assert_locked(); ++ assert(size >= MinChunkSize, "minimum chunk size"); ++ assert(size < _smallLinearAllocBlock._allocation_size_limit, ++ "maximum from smallLinearAllocBlock"); ++ return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size); ++} ++ ++HeapWord* ++CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk, ++ size_t size) { ++ assert_locked(); ++ assert(size >= MinChunkSize, "too small"); ++ HeapWord* res = NULL; ++ // Try to do linear allocation from blk, making sure that ++ if (blk->_word_size == 0) { ++ // We have probably been unable to fill this either in the prologue or ++ // when it was exhausted at the last linear allocation. Bail out until ++ // next time. ++ assert(blk->_ptr == NULL, "consistency check"); ++ return NULL; ++ } ++ assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check"); ++ res = getChunkFromLinearAllocBlockRemainder(blk, size); ++ if (res != NULL) return res; ++ ++ // about to exhaust this linear allocation block ++ if (blk->_word_size == size) { // exactly satisfied ++ res = blk->_ptr; ++ _bt.allocated(res, blk->_word_size); ++ } else if (size + MinChunkSize <= blk->_refillSize) { ++ size_t sz = blk->_word_size; ++ // Update _unallocated_block if the size is such that chunk would be ++ // returned to the indexed free list. All other chunks in the indexed ++ // free lists are allocated from the dictionary so that _unallocated_block ++ // has already been adjusted for them. Do it here so that the cost ++ // for all chunks added back to the indexed free lists. ++ if (sz < SmallForDictionary) { ++ _bt.allocated(blk->_ptr, sz); ++ } ++ // Return the chunk that isn't big enough, and then refill below. ++ addChunkToFreeLists(blk->_ptr, sz); ++ split_birth(sz); ++ // Don't keep statistics on adding back chunk from a LinAB. ++ } else { ++ // A refilled block would not satisfy the request. ++ return NULL; ++ } ++ ++ blk->_ptr = NULL; blk->_word_size = 0; ++ refillLinearAllocBlock(blk); ++ assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, ++ "block was replenished"); ++ if (res != NULL) { ++ split_birth(size); ++ repairLinearAllocBlock(blk); ++ } else if (blk->_ptr != NULL) { ++ res = blk->_ptr; ++ size_t blk_size = blk->_word_size; ++ blk->_word_size -= size; ++ blk->_ptr += size; ++ split_birth(size); ++ repairLinearAllocBlock(blk); ++ // Update BOT last so that other (parallel) GC threads see a consistent ++ // view of the BOT and free blocks. ++ // Above must occur before BOT is updated below. ++ OrderAccess::storestore(); ++ _bt.split_block(res, blk_size, size); // adjust block offset table ++ } ++ return res; ++} ++ ++HeapWord* CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder( ++ LinearAllocBlock* blk, ++ size_t size) { ++ assert_locked(); ++ assert(size >= MinChunkSize, "too small"); ++ ++ HeapWord* res = NULL; ++ // This is the common case. Keep it simple. ++ if (blk->_word_size >= size + MinChunkSize) { ++ assert(blk->_ptr != NULL, "consistency check"); ++ res = blk->_ptr; ++ // Note that the BOT is up-to-date for the linAB before allocation. It ++ // indicates the start of the linAB. The split_block() updates the ++ // BOT for the linAB after the allocation (indicates the start of the ++ // next chunk to be allocated). ++ size_t blk_size = blk->_word_size; ++ blk->_word_size -= size; ++ blk->_ptr += size; ++ split_birth(size); ++ repairLinearAllocBlock(blk); ++ // Update BOT last so that other (parallel) GC threads see a consistent ++ // view of the BOT and free blocks. ++ // Above must occur before BOT is updated below. ++ OrderAccess::storestore(); ++ _bt.split_block(res, blk_size, size); // adjust block offset table ++ _bt.allocated(res, size); ++ } ++ return res; ++} ++ ++FreeChunk* ++CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) { ++ assert_locked(); ++ assert(size < SmallForDictionary, "just checking"); ++ FreeChunk* res; ++ res = _indexedFreeList[size].get_chunk_at_head(); ++ if (res == NULL) { ++ res = getChunkFromIndexedFreeListHelper(size); ++ } ++ _bt.verify_not_unallocated((HeapWord*) res, size); ++ assert(res == NULL || res->size() == size, "Incorrect block size"); ++ return res; ++} ++ ++FreeChunk* ++CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, ++ bool replenish) { ++ assert_locked(); ++ FreeChunk* fc = NULL; ++ if (size < SmallForDictionary) { ++ assert(_indexedFreeList[size].head() == NULL || ++ _indexedFreeList[size].surplus() <= 0, ++ "List for this size should be empty or under populated"); ++ // Try best fit in exact lists before replenishing the list ++ if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) { ++ // Replenish list. ++ // ++ // Things tried that failed. ++ // Tried allocating out of the two LinAB's first before ++ // replenishing lists. ++ // Tried small linAB of size 256 (size in indexed list) ++ // and replenishing indexed lists from the small linAB. ++ // ++ FreeChunk* newFc = NULL; ++ const size_t replenish_size = CMSIndexedFreeListReplenish * size; ++ if (replenish_size < SmallForDictionary) { ++ // Do not replenish from an underpopulated size. ++ if (_indexedFreeList[replenish_size].surplus() > 0 && ++ _indexedFreeList[replenish_size].head() != NULL) { ++ newFc = _indexedFreeList[replenish_size].get_chunk_at_head(); ++ } else if (bestFitFirst()) { ++ newFc = bestFitSmall(replenish_size); ++ } ++ } ++ if (newFc == NULL && replenish_size > size) { ++ assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant"); ++ newFc = getChunkFromIndexedFreeListHelper(replenish_size, false); ++ } ++ // Note: The stats update re split-death of block obtained above ++ // will be recorded below precisely when we know we are going to ++ // be actually splitting it into more than one pieces below. ++ if (newFc != NULL) { ++ if (replenish || CMSReplenishIntermediate) { ++ // Replenish this list and return one block to caller. ++ size_t i; ++ FreeChunk *curFc, *nextFc; ++ size_t num_blk = newFc->size() / size; ++ assert(num_blk >= 1, "Smaller than requested?"); ++ assert(newFc->size() % size == 0, "Should be integral multiple of request"); ++ if (num_blk > 1) { ++ // we are sure we will be splitting the block just obtained ++ // into multiple pieces; record the split-death of the original ++ splitDeath(replenish_size); ++ } ++ // carve up and link blocks 0, ..., num_blk - 2 ++ // The last chunk is not added to the lists but is returned as the ++ // free chunk. ++ for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), ++ i = 0; ++ i < (num_blk - 1); ++ curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), ++ i++) { ++ curFc->set_size(size); ++ // Don't record this as a return in order to try and ++ // determine the "returns" from a GC. ++ _bt.verify_not_unallocated((HeapWord*) fc, size); ++ _indexedFreeList[size].return_chunk_at_tail(curFc, false); ++ _bt.mark_block((HeapWord*)curFc, size); ++ split_birth(size); ++ // Don't record the initial population of the indexed list ++ // as a split birth. ++ } ++ ++ // check that the arithmetic was OK above ++ assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, ++ "inconsistency in carving newFc"); ++ curFc->set_size(size); ++ _bt.mark_block((HeapWord*)curFc, size); ++ split_birth(size); ++ fc = curFc; ++ } else { ++ // Return entire block to caller ++ fc = newFc; ++ } ++ } ++ } ++ } else { ++ // Get a free chunk from the free chunk dictionary to be returned to ++ // replenish the indexed free list. ++ fc = getChunkFromDictionaryExact(size); ++ } ++ // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk"); ++ return fc; ++} ++ ++FreeChunk* ++CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { ++ assert_locked(); ++ FreeChunk* fc = _dictionary->get_chunk(size); ++ if (fc == NULL) { ++ return NULL; ++ } ++ _bt.allocated((HeapWord*)fc, fc->size()); ++ if (fc->size() >= size + MinChunkSize) { ++ fc = splitChunkAndReturnRemainder(fc, size); ++ } ++ assert(fc->size() >= size, "chunk too small"); ++ assert(fc->size() < size + MinChunkSize, "chunk too big"); ++ _bt.verify_single_block((HeapWord*)fc, fc->size()); ++ return fc; ++} ++ ++FreeChunk* ++CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { ++ assert_locked(); ++ FreeChunk* fc = _dictionary->get_chunk(size); ++ if (fc == NULL) { ++ return fc; ++ } ++ _bt.allocated((HeapWord*)fc, fc->size()); ++ if (fc->size() == size) { ++ _bt.verify_single_block((HeapWord*)fc, size); ++ return fc; ++ } ++ assert(fc->size() > size, "get_chunk() guarantee"); ++ if (fc->size() < size + MinChunkSize) { ++ // Return the chunk to the dictionary and go get a bigger one. ++ returnChunkToDictionary(fc); ++ fc = _dictionary->get_chunk(size + MinChunkSize); ++ if (fc == NULL) { ++ return NULL; ++ } ++ _bt.allocated((HeapWord*)fc, fc->size()); ++ } ++ assert(fc->size() >= size + MinChunkSize, "tautology"); ++ fc = splitChunkAndReturnRemainder(fc, size); ++ assert(fc->size() == size, "chunk is wrong size"); ++ _bt.verify_single_block((HeapWord*)fc, size); ++ return fc; ++} ++ ++void ++CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { ++ assert_locked(); ++ ++ size_t size = chunk->size(); ++ _bt.verify_single_block((HeapWord*)chunk, size); ++ // adjust _unallocated_block downward, as necessary ++ _bt.freed((HeapWord*)chunk, size); ++ _dictionary->return_chunk(chunk); ++#ifndef PRODUCT ++ if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { ++ TreeChunk >* tc = TreeChunk >::as_TreeChunk(chunk); ++ TreeList >* tl = tc->list(); ++ tl->verify_stats(); ++ } ++#endif // PRODUCT ++} ++ ++void ++CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { ++ assert_locked(); ++ size_t size = fc->size(); ++ _bt.verify_single_block((HeapWord*) fc, size); ++ _bt.verify_not_unallocated((HeapWord*) fc, size); ++ _indexedFreeList[size].return_chunk_at_tail(fc); ++#ifndef PRODUCT ++ if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { ++ _indexedFreeList[size].verify_stats(); ++ } ++#endif // PRODUCT ++} ++ ++// Add chunk to end of last block -- if it's the largest ++// block -- and update BOT and census data. We would ++// of course have preferred to coalesce it with the ++// last block, but it's currently less expensive to find the ++// largest block than it is to find the last. ++void ++CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats( ++ HeapWord* chunk, size_t size) { ++ // check that the chunk does lie in this space! ++ assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); ++ // One of the parallel gc task threads may be here ++ // whilst others are allocating. ++ Mutex* lock = &_parDictionaryAllocLock; ++ FreeChunk* ec; ++ { ++ MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); ++ ec = dictionary()->find_largest_dict(); // get largest block ++ if (ec != NULL && ec->end() == (uintptr_t*) chunk) { ++ // It's a coterminal block - we can coalesce. ++ size_t old_size = ec->size(); ++ coalDeath(old_size); ++ removeChunkFromDictionary(ec); ++ size += old_size; ++ } else { ++ ec = (FreeChunk*)chunk; ++ } ++ } ++ ec->set_size(size); ++ debug_only(ec->mangleFreed(size)); ++ if (size < SmallForDictionary) { ++ lock = _indexedFreeListParLocks[size]; ++ } ++ MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); ++ addChunkAndRepairOffsetTable((HeapWord*)ec, size, true); ++ // record the birth under the lock since the recording involves ++ // manipulation of the list on which the chunk lives and ++ // if the chunk is allocated and is the last on the list, ++ // the list can go away. ++ coalBirth(size); ++} ++ ++void ++CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk, ++ size_t size) { ++ // check that the chunk does lie in this space! ++ assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); ++ assert_locked(); ++ _bt.verify_single_block(chunk, size); ++ ++ FreeChunk* fc = (FreeChunk*) chunk; ++ fc->set_size(size); ++ debug_only(fc->mangleFreed(size)); ++ if (size < SmallForDictionary) { ++ returnChunkToFreeList(fc); ++ } else { ++ returnChunkToDictionary(fc); ++ } ++} ++ ++void ++CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk, ++ size_t size, bool coalesced) { ++ assert_locked(); ++ assert(chunk != NULL, "null chunk"); ++ if (coalesced) { ++ // repair BOT ++ _bt.single_block(chunk, size); ++ } ++ addChunkToFreeLists(chunk, size); ++} ++ ++// We _must_ find the purported chunk on our free lists; ++// we assert if we don't. ++void ++CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) { ++ size_t size = fc->size(); ++ assert_locked(); ++ debug_only(verifyFreeLists()); ++ if (size < SmallForDictionary) { ++ removeChunkFromIndexedFreeList(fc); ++ } else { ++ removeChunkFromDictionary(fc); ++ } ++ _bt.verify_single_block((HeapWord*)fc, size); ++ debug_only(verifyFreeLists()); ++} ++ ++void ++CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) { ++ size_t size = fc->size(); ++ assert_locked(); ++ assert(fc != NULL, "null chunk"); ++ _bt.verify_single_block((HeapWord*)fc, size); ++ _dictionary->remove_chunk(fc); ++ // adjust _unallocated_block upward, as necessary ++ _bt.allocated((HeapWord*)fc, size); ++} ++ ++void ++CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) { ++ assert_locked(); ++ size_t size = fc->size(); ++ _bt.verify_single_block((HeapWord*)fc, size); ++ NOT_PRODUCT( ++ if (FLSVerifyIndexTable) { ++ verifyIndexedFreeList(size); ++ } ++ ) ++ _indexedFreeList[size].remove_chunk(fc); ++ NOT_PRODUCT( ++ if (FLSVerifyIndexTable) { ++ verifyIndexedFreeList(size); ++ } ++ ) ++} ++ ++FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) { ++ /* A hint is the next larger size that has a surplus. ++ Start search at a size large enough to guarantee that ++ the excess is >= MIN_CHUNK. */ ++ size_t start = align_object_size(numWords + MinChunkSize); ++ if (start < IndexSetSize) { ++ AdaptiveFreeList* it = _indexedFreeList; ++ size_t hint = _indexedFreeList[start].hint(); ++ while (hint < IndexSetSize) { ++ assert(is_object_aligned(hint), "hint should be aligned"); ++ AdaptiveFreeList *fl = &_indexedFreeList[hint]; ++ if (fl->surplus() > 0 && fl->head() != NULL) { ++ // Found a list with surplus, reset original hint ++ // and split out a free chunk which is returned. ++ _indexedFreeList[start].set_hint(hint); ++ FreeChunk* res = getFromListGreater(fl, numWords); ++ assert(res == NULL || res->is_free(), ++ "Should be returning a free chunk"); ++ return res; ++ } ++ hint = fl->hint(); /* keep looking */ ++ } ++ /* None found. */ ++ it[start].set_hint(IndexSetSize); ++ } ++ return NULL; ++} ++ ++/* Requires fl->size >= numWords + MinChunkSize */ ++FreeChunk* CompactibleFreeListSpace::getFromListGreater(AdaptiveFreeList* fl, ++ size_t numWords) { ++ FreeChunk *curr = fl->head(); ++ size_t oldNumWords = curr->size(); ++ assert(numWords >= MinChunkSize, "Word size is too small"); ++ assert(curr != NULL, "List is empty"); ++ assert(oldNumWords >= numWords + MinChunkSize, ++ "Size of chunks in the list is too small"); ++ ++ fl->remove_chunk(curr); ++ // recorded indirectly by splitChunkAndReturnRemainder - ++ // smallSplit(oldNumWords, numWords); ++ FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); ++ // Does anything have to be done for the remainder in terms of ++ // fixing the card table? ++ assert(new_chunk == NULL || new_chunk->is_free(), ++ "Should be returning a free chunk"); ++ return new_chunk; ++} ++ ++FreeChunk* ++CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk, ++ size_t new_size) { ++ assert_locked(); ++ size_t size = chunk->size(); ++ assert(size > new_size, "Split from a smaller block?"); ++ assert(is_aligned(chunk), "alignment problem"); ++ assert(size == adjustObjectSize(size), "alignment problem"); ++ size_t rem_sz = size - new_size; ++ assert(rem_sz == adjustObjectSize(rem_sz), "alignment problem"); ++ assert(rem_sz >= MinChunkSize, "Free chunk smaller than minimum"); ++ FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); ++ assert(is_aligned(ffc), "alignment problem"); ++ ffc->set_size(rem_sz); ++ ffc->link_next(NULL); ++ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. ++ // Above must occur before BOT is updated below. ++ // adjust block offset table ++ OrderAccess::storestore(); ++ assert(chunk->is_free() && ffc->is_free(), "Error"); ++ _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); ++ if (rem_sz < SmallForDictionary) { ++ // The freeList lock is held, but multiple GC task threads might be executing in parallel. ++ bool is_par = Thread::current()->is_GC_task_thread(); ++ if (is_par) _indexedFreeListParLocks[rem_sz]->lock(); ++ returnChunkToFreeList(ffc); ++ split(size, rem_sz); ++ if (is_par) _indexedFreeListParLocks[rem_sz]->unlock(); ++ } else { ++ returnChunkToDictionary(ffc); ++ split(size, rem_sz); ++ } ++ chunk->set_size(new_size); ++ return chunk; ++} ++ ++void ++CompactibleFreeListSpace::sweep_completed() { ++ // Now that space is probably plentiful, refill linear ++ // allocation blocks as needed. ++ refillLinearAllocBlocksIfNeeded(); ++} ++ ++void ++CompactibleFreeListSpace::gc_prologue() { ++ assert_locked(); ++ reportFreeListStatistics("Before GC:"); ++ refillLinearAllocBlocksIfNeeded(); ++} ++ ++void ++CompactibleFreeListSpace::gc_epilogue() { ++ assert_locked(); ++ assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); ++ _promoInfo.stopTrackingPromotions(); ++ repairLinearAllocationBlocks(); ++ reportFreeListStatistics("After GC:"); ++} ++ ++// Iteration support, mostly delegated from a CMS generation ++ ++void CompactibleFreeListSpace::save_marks() { ++ assert(Thread::current()->is_VM_thread(), ++ "Global variable should only be set when single-threaded"); ++ // Mark the "end" of the used space at the time of this call; ++ // note, however, that promoted objects from this point ++ // on are tracked in the _promoInfo below. ++ set_saved_mark_word(unallocated_block()); ++#ifdef ASSERT ++ // Check the sanity of save_marks() etc. ++ MemRegion ur = used_region(); ++ MemRegion urasm = used_region_at_save_marks(); ++ assert(ur.contains(urasm), ++ " Error at save_marks(): [" PTR_FORMAT "," PTR_FORMAT ")" ++ " should contain [" PTR_FORMAT "," PTR_FORMAT ")", ++ p2i(ur.start()), p2i(ur.end()), p2i(urasm.start()), p2i(urasm.end())); ++#endif ++ // inform allocator that promotions should be tracked. ++ assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); ++ _promoInfo.startTrackingPromotions(); ++} ++ ++bool CompactibleFreeListSpace::no_allocs_since_save_marks() { ++ assert(_promoInfo.tracking(), "No preceding save_marks?"); ++ return _promoInfo.noPromotions(); ++} ++ ++bool CompactibleFreeListSpace::linearAllocationWouldFail() const { ++ return _smallLinearAllocBlock._word_size == 0; ++} ++ ++void CompactibleFreeListSpace::repairLinearAllocationBlocks() { ++ // Fix up linear allocation blocks to look like free blocks ++ repairLinearAllocBlock(&_smallLinearAllocBlock); ++} ++ ++void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) { ++ assert_locked(); ++ if (blk->_ptr != NULL) { ++ assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize, ++ "Minimum block size requirement"); ++ FreeChunk* fc = (FreeChunk*)(blk->_ptr); ++ fc->set_size(blk->_word_size); ++ fc->link_prev(NULL); // mark as free ++ fc->dontCoalesce(); ++ assert(fc->is_free(), "just marked it free"); ++ assert(fc->cantCoalesce(), "just marked it uncoalescable"); ++ } ++} ++ ++void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() { ++ assert_locked(); ++ if (_smallLinearAllocBlock._ptr == NULL) { ++ assert(_smallLinearAllocBlock._word_size == 0, ++ "Size of linAB should be zero if the ptr is NULL"); ++ // Reset the linAB refill and allocation size limit. ++ _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc); ++ } ++ refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock); ++} ++ ++void ++CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) { ++ assert_locked(); ++ assert((blk->_ptr == NULL && blk->_word_size == 0) || ++ (blk->_ptr != NULL && blk->_word_size >= MinChunkSize), ++ "blk invariant"); ++ if (blk->_ptr == NULL) { ++ refillLinearAllocBlock(blk); ++ } ++} ++ ++void ++CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) { ++ assert_locked(); ++ assert(blk->_word_size == 0 && blk->_ptr == NULL, ++ "linear allocation block should be empty"); ++ FreeChunk* fc; ++ if (blk->_refillSize < SmallForDictionary && ++ (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) { ++ // A linAB's strategy might be to use small sizes to reduce ++ // fragmentation but still get the benefits of allocation from a ++ // linAB. ++ } else { ++ fc = getChunkFromDictionary(blk->_refillSize); ++ } ++ if (fc != NULL) { ++ blk->_ptr = (HeapWord*)fc; ++ blk->_word_size = fc->size(); ++ fc->dontCoalesce(); // to prevent sweeper from sweeping us up ++ } ++} ++ ++// Support for compaction ++void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { ++ scan_and_forward(this, cp, false); ++ // of the free lists doesn't work after. ++ // Prepare_for_compaction() uses the space between live objects ++ // so that later phase can skip dead space quickly. So verification ++ // of the free lists doesn't work after. ++} ++ ++void CompactibleFreeListSpace::adjust_pointers() { ++ // In other versions of adjust_pointers(), a bail out ++ // based on the amount of live data in the generation ++ // (i.e., if 0, bail out) may be used. ++ // Cannot test used() == 0 here because the free lists have already ++ // been mangled by the compaction. ++ ++ scan_and_adjust_pointers(this); ++ // See note about verification in prepare_for_compaction(). ++} ++ ++void CompactibleFreeListSpace::compact() { ++ scan_and_compact(this, false); ++} ++ ++// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2] ++// where fbs is free block sizes ++double CompactibleFreeListSpace::flsFrag() const { ++ size_t itabFree = totalSizeInIndexedFreeLists(); ++ double frag = 0.0; ++ size_t i; ++ ++ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ double sz = i; ++ frag += _indexedFreeList[i].count() * (sz * sz); ++ } ++ ++ double totFree = itabFree + ++ _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); ++ if (totFree > 0) { ++ frag = ((frag + _dictionary->sum_of_squared_block_sizes()) / ++ (totFree * totFree)); ++ frag = (double)1.0 - frag; ++ } else { ++ assert(frag == 0.0, "Follows from totFree == 0"); ++ } ++ return frag; ++} ++ ++void CompactibleFreeListSpace::beginSweepFLCensus( ++ float inter_sweep_current, ++ float inter_sweep_estimate, ++ float intra_sweep_estimate) { ++ assert_locked(); ++ size_t i; ++ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ AdaptiveFreeList* fl = &_indexedFreeList[i]; ++ log_trace(gc, freelist)("size[" SIZE_FORMAT "] : ", i); ++ fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); ++ fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); ++ fl->set_before_sweep(fl->count()); ++ fl->set_bfr_surp(fl->surplus()); ++ } ++ _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent, ++ inter_sweep_current, ++ inter_sweep_estimate, ++ intra_sweep_estimate); ++} ++ ++void CompactibleFreeListSpace::setFLSurplus() { ++ assert_locked(); ++ size_t i; ++ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ AdaptiveFreeList *fl = &_indexedFreeList[i]; ++ fl->set_surplus(fl->count() - ++ (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); ++ } ++} ++ ++void CompactibleFreeListSpace::setFLHints() { ++ assert_locked(); ++ size_t i; ++ size_t h = IndexSetSize; ++ for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { ++ AdaptiveFreeList *fl = &_indexedFreeList[i]; ++ fl->set_hint(h); ++ if (fl->surplus() > 0) { ++ h = i; ++ } ++ } ++} ++ ++void CompactibleFreeListSpace::clearFLCensus() { ++ assert_locked(); ++ size_t i; ++ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ AdaptiveFreeList *fl = &_indexedFreeList[i]; ++ fl->set_prev_sweep(fl->count()); ++ fl->set_coal_births(0); ++ fl->set_coal_deaths(0); ++ fl->set_split_births(0); ++ fl->set_split_deaths(0); ++ } ++} ++ ++void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { ++ log_debug(gc, freelist)("CMS: Large block " PTR_FORMAT, p2i(dictionary()->find_largest_dict())); ++ setFLSurplus(); ++ setFLHints(); ++ printFLCensus(sweep_count); ++ clearFLCensus(); ++ assert_locked(); ++ _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); ++} ++ ++bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { ++ if (size < SmallForDictionary) { ++ AdaptiveFreeList *fl = &_indexedFreeList[size]; ++ return (fl->coal_desired() < 0) || ++ ((int)fl->count() > fl->coal_desired()); ++ } else { ++ return dictionary()->coal_dict_over_populated(size); ++ } ++} ++ ++void CompactibleFreeListSpace::smallCoalBirth(size_t size) { ++ assert(size < SmallForDictionary, "Size too large for indexed list"); ++ AdaptiveFreeList *fl = &_indexedFreeList[size]; ++ fl->increment_coal_births(); ++ fl->increment_surplus(); ++} ++ ++void CompactibleFreeListSpace::smallCoalDeath(size_t size) { ++ assert(size < SmallForDictionary, "Size too large for indexed list"); ++ AdaptiveFreeList *fl = &_indexedFreeList[size]; ++ fl->increment_coal_deaths(); ++ fl->decrement_surplus(); ++} ++ ++void CompactibleFreeListSpace::coalBirth(size_t size) { ++ if (size < SmallForDictionary) { ++ smallCoalBirth(size); ++ } else { ++ dictionary()->dict_census_update(size, ++ false /* split */, ++ true /* birth */); ++ } ++} ++ ++void CompactibleFreeListSpace::coalDeath(size_t size) { ++ if(size < SmallForDictionary) { ++ smallCoalDeath(size); ++ } else { ++ dictionary()->dict_census_update(size, ++ false /* split */, ++ false /* birth */); ++ } ++} ++ ++void CompactibleFreeListSpace::smallSplitBirth(size_t size) { ++ assert(size < SmallForDictionary, "Size too large for indexed list"); ++ AdaptiveFreeList *fl = &_indexedFreeList[size]; ++ fl->increment_split_births(); ++ fl->increment_surplus(); ++} ++ ++void CompactibleFreeListSpace::smallSplitDeath(size_t size) { ++ assert(size < SmallForDictionary, "Size too large for indexed list"); ++ AdaptiveFreeList *fl = &_indexedFreeList[size]; ++ fl->increment_split_deaths(); ++ fl->decrement_surplus(); ++} ++ ++void CompactibleFreeListSpace::split_birth(size_t size) { ++ if (size < SmallForDictionary) { ++ smallSplitBirth(size); ++ } else { ++ dictionary()->dict_census_update(size, ++ true /* split */, ++ true /* birth */); ++ } ++} ++ ++void CompactibleFreeListSpace::splitDeath(size_t size) { ++ if (size < SmallForDictionary) { ++ smallSplitDeath(size); ++ } else { ++ dictionary()->dict_census_update(size, ++ true /* split */, ++ false /* birth */); ++ } ++} ++ ++void CompactibleFreeListSpace::split(size_t from, size_t to1) { ++ size_t to2 = from - to1; ++ splitDeath(from); ++ split_birth(to1); ++ split_birth(to2); ++} ++ ++void CompactibleFreeListSpace::print() const { ++ print_on(tty); ++} ++ ++void CompactibleFreeListSpace::prepare_for_verify() { ++ assert_locked(); ++ repairLinearAllocationBlocks(); ++ // Verify that the SpoolBlocks look like free blocks of ++ // appropriate sizes... To be done ... ++} ++ ++class VerifyAllBlksClosure: public BlkClosure { ++ private: ++ const CompactibleFreeListSpace* _sp; ++ const MemRegion _span; ++ HeapWord* _last_addr; ++ size_t _last_size; ++ bool _last_was_obj; ++ bool _last_was_live; ++ ++ public: ++ VerifyAllBlksClosure(const CompactibleFreeListSpace* sp, ++ MemRegion span) : _sp(sp), _span(span), ++ _last_addr(NULL), _last_size(0), ++ _last_was_obj(false), _last_was_live(false) { } ++ ++ virtual size_t do_blk(HeapWord* addr) { ++ size_t res; ++ bool was_obj = false; ++ bool was_live = false; ++ if (_sp->block_is_obj(addr)) { ++ was_obj = true; ++ oop p = oop(addr); ++ guarantee(oopDesc::is_oop(p), "Should be an oop"); ++ res = _sp->adjustObjectSize(p->size()); ++ if (_sp->obj_is_alive(addr)) { ++ was_live = true; ++ p->verify(); ++ } ++ } else { ++ FreeChunk* fc = (FreeChunk*)addr; ++ res = fc->size(); ++ if (FLSVerifyLists && !fc->cantCoalesce()) { ++ guarantee(_sp->verify_chunk_in_free_list(fc), ++ "Chunk should be on a free list"); ++ } ++ } ++ if (res == 0) { ++ Log(gc, verify) log; ++ log.error("Livelock: no rank reduction!"); ++ log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n" ++ " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n", ++ p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false", ++ p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false"); ++ LogStream ls(log.error()); ++ _sp->print_on(&ls); ++ guarantee(false, "Verification failed."); ++ } ++ _last_addr = addr; ++ _last_size = res; ++ _last_was_obj = was_obj; ++ _last_was_live = was_live; ++ return res; ++ } ++}; ++ ++class VerifyAllOopsClosure: public BasicOopIterateClosure { ++ private: ++ const CMSCollector* _collector; ++ const CompactibleFreeListSpace* _sp; ++ const MemRegion _span; ++ const bool _past_remark; ++ const CMSBitMap* _bit_map; ++ ++ protected: ++ void do_oop(void* p, oop obj) { ++ if (_span.contains(obj)) { // the interior oop points into CMS heap ++ if (!_span.contains(p)) { // reference from outside CMS heap ++ // Should be a valid object; the first disjunct below allows ++ // us to sidestep an assertion in block_is_obj() that insists ++ // that p be in _sp. Note that several generations (and spaces) ++ // are spanned by _span (CMS heap) above. ++ guarantee(!_sp->is_in_reserved(obj) || ++ _sp->block_is_obj((HeapWord*)obj), ++ "Should be an object"); ++ guarantee(oopDesc::is_oop(obj), "Should be an oop"); ++ obj->verify(); ++ if (_past_remark) { ++ // Remark has been completed, the object should be marked ++ _bit_map->isMarked((HeapWord*)obj); ++ } ++ } else { // reference within CMS heap ++ if (_past_remark) { ++ // Remark has been completed -- so the referent should have ++ // been marked, if referring object is. ++ if (_bit_map->isMarked(_collector->block_start(p))) { ++ guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?"); ++ } ++ } ++ } ++ } else if (_sp->is_in_reserved(p)) { ++ // the reference is from FLS, and points out of FLS ++ guarantee(oopDesc::is_oop(obj), "Should be an oop"); ++ obj->verify(); ++ } ++ } ++ ++ template void do_oop_work(T* p) { ++ T heap_oop = RawAccess<>::oop_load(p); ++ if (!CompressedOops::is_null(heap_oop)) { ++ oop obj = CompressedOops::decode_not_null(heap_oop); ++ do_oop(p, obj); ++ } ++ } ++ ++ public: ++ VerifyAllOopsClosure(const CMSCollector* collector, ++ const CompactibleFreeListSpace* sp, MemRegion span, ++ bool past_remark, CMSBitMap* bit_map) : ++ _collector(collector), _sp(sp), _span(span), ++ _past_remark(past_remark), _bit_map(bit_map) { } ++ ++ virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); } ++ virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); } ++}; ++ ++void CompactibleFreeListSpace::verify() const { ++ assert_lock_strong(&_freelistLock); ++ verify_objects_initialized(); ++ MemRegion span = _collector->_span; ++ bool past_remark = (_collector->abstract_state() == ++ CMSCollector::Sweeping); ++ ++ ResourceMark rm; ++ HandleMark hm; ++ ++ // Check integrity of CFL data structures ++ _promoInfo.verify(); ++ _dictionary->verify(); ++ if (FLSVerifyIndexTable) { ++ verifyIndexedFreeLists(); ++ } ++ // Check integrity of all objects and free blocks in space ++ { ++ VerifyAllBlksClosure cl(this, span); ++ ((CompactibleFreeListSpace*)this)->blk_iterate(&cl); // cast off const ++ } ++ // Check that all references in the heap to FLS ++ // are to valid objects in FLS or that references in ++ // FLS are to valid objects elsewhere in the heap ++ if (FLSVerifyAllHeapReferences) ++ { ++ VerifyAllOopsClosure cl(_collector, this, span, past_remark, ++ _collector->markBitMap()); ++ ++ // Iterate over all oops in the heap. ++ CMSHeap::heap()->oop_iterate(&cl); ++ } ++ ++ if (VerifyObjectStartArray) { ++ // Verify the block offset table ++ _bt.verify(); ++ } ++} ++ ++#ifndef PRODUCT ++void CompactibleFreeListSpace::verifyFreeLists() const { ++ if (FLSVerifyLists) { ++ _dictionary->verify(); ++ verifyIndexedFreeLists(); ++ } else { ++ if (FLSVerifyDictionary) { ++ _dictionary->verify(); ++ } ++ if (FLSVerifyIndexTable) { ++ verifyIndexedFreeLists(); ++ } ++ } ++} ++#endif ++ ++void CompactibleFreeListSpace::verifyIndexedFreeLists() const { ++ size_t i = 0; ++ for (; i < IndexSetStart; i++) { ++ guarantee(_indexedFreeList[i].head() == NULL, "should be NULL"); ++ } ++ for (; i < IndexSetSize; i++) { ++ verifyIndexedFreeList(i); ++ } ++} ++ ++void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { ++ FreeChunk* fc = _indexedFreeList[size].head(); ++ FreeChunk* tail = _indexedFreeList[size].tail(); ++ size_t num = _indexedFreeList[size].count(); ++ size_t n = 0; ++ guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, ++ "Slot should have been empty"); ++ for (; fc != NULL; fc = fc->next(), n++) { ++ guarantee(fc->size() == size, "Size inconsistency"); ++ guarantee(fc->is_free(), "!free?"); ++ guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); ++ guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); ++ } ++ guarantee(n == num, "Incorrect count"); ++} ++ ++#ifndef PRODUCT ++void CompactibleFreeListSpace::check_free_list_consistency() const { ++ assert((TreeChunk >::min_size() <= IndexSetSize), ++ "Some sizes can't be allocated without recourse to" ++ " linear allocation buffers"); ++ assert((TreeChunk >::min_size()*HeapWordSize == sizeof(TreeChunk >)), ++ "else MIN_TREE_CHUNK_SIZE is wrong"); ++ assert(IndexSetStart != 0, "IndexSetStart not initialized"); ++ assert(IndexSetStride != 0, "IndexSetStride not initialized"); ++} ++#endif ++ ++void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { ++ assert_lock_strong(&_freelistLock); ++ LogTarget(Debug, gc, freelist, census) log; ++ if (!log.is_enabled()) { ++ return; ++ } ++ AdaptiveFreeList total; ++ log.print("end sweep# " SIZE_FORMAT, sweep_count); ++ ResourceMark rm; ++ LogStream ls(log); ++ outputStream* out = &ls; ++ AdaptiveFreeList::print_labels_on(out, "size"); ++ size_t total_free = 0; ++ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { ++ const AdaptiveFreeList *fl = &_indexedFreeList[i]; ++ total_free += fl->count() * fl->size(); ++ if (i % (40*IndexSetStride) == 0) { ++ AdaptiveFreeList::print_labels_on(out, "size"); ++ } ++ fl->print_on(out); ++ total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); ++ total.set_surplus( total.surplus() + fl->surplus() ); ++ total.set_desired( total.desired() + fl->desired() ); ++ total.set_prev_sweep( total.prev_sweep() + fl->prev_sweep() ); ++ total.set_before_sweep(total.before_sweep() + fl->before_sweep()); ++ total.set_count( total.count() + fl->count() ); ++ total.set_coal_births( total.coal_births() + fl->coal_births() ); ++ total.set_coal_deaths( total.coal_deaths() + fl->coal_deaths() ); ++ total.set_split_births(total.split_births() + fl->split_births()); ++ total.set_split_deaths(total.split_deaths() + fl->split_deaths()); ++ } ++ total.print_on(out, "TOTAL"); ++ log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free); ++ log.print("growth: %8.5f deficit: %8.5f", ++ (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ ++ (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), ++ (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); ++ _dictionary->print_dict_census(out); ++} ++ ++/////////////////////////////////////////////////////////////////////////// ++// CompactibleFreeListSpaceLAB ++/////////////////////////////////////////////////////////////////////////// ++ ++#define VECTOR_257(x) \ ++ /* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \ ++ { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ ++ x } ++ ++// Initialize with default setting for CMS, _not_ ++// generic OldPLABSize, whose static default is different; if overridden at the ++// command-line, this will get reinitialized via a call to ++// modify_initialization() below. ++AdaptiveWeightedAverage CompactibleFreeListSpaceLAB::_blocks_to_claim[] = ++ VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CompactibleFreeListSpaceLAB::_default_dynamic_old_plab_size)); ++size_t CompactibleFreeListSpaceLAB::_global_num_blocks[] = VECTOR_257(0); ++uint CompactibleFreeListSpaceLAB::_global_num_workers[] = VECTOR_257(0); ++ ++CompactibleFreeListSpaceLAB::CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls) : ++ _cfls(cfls) ++{ ++ assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above"); ++ for (size_t i = CompactibleFreeListSpace::IndexSetStart; ++ i < CompactibleFreeListSpace::IndexSetSize; ++ i += CompactibleFreeListSpace::IndexSetStride) { ++ _indexedFreeList[i].set_size(i); ++ _num_blocks[i] = 0; ++ } ++} ++ ++static bool _CFLS_LAB_modified = false; ++ ++void CompactibleFreeListSpaceLAB::modify_initialization(size_t n, unsigned wt) { ++ assert(!_CFLS_LAB_modified, "Call only once"); ++ _CFLS_LAB_modified = true; ++ for (size_t i = CompactibleFreeListSpace::IndexSetStart; ++ i < CompactibleFreeListSpace::IndexSetSize; ++ i += CompactibleFreeListSpace::IndexSetStride) { ++ _blocks_to_claim[i].modify(n, wt, true /* force */); ++ } ++} ++ ++HeapWord* CompactibleFreeListSpaceLAB::alloc(size_t word_sz) { ++ FreeChunk* res; ++ assert(word_sz == _cfls->adjustObjectSize(word_sz), "Error"); ++ if (word_sz >= CompactibleFreeListSpace::IndexSetSize) { ++ // This locking manages sync with other large object allocations. ++ MutexLockerEx x(_cfls->parDictionaryAllocLock(), ++ Mutex::_no_safepoint_check_flag); ++ res = _cfls->getChunkFromDictionaryExact(word_sz); ++ if (res == NULL) return NULL; ++ } else { ++ AdaptiveFreeList* fl = &_indexedFreeList[word_sz]; ++ if (fl->count() == 0) { ++ // Attempt to refill this local free list. ++ get_from_global_pool(word_sz, fl); ++ // If it didn't work, give up. ++ if (fl->count() == 0) return NULL; ++ } ++ res = fl->get_chunk_at_head(); ++ assert(res != NULL, "Why was count non-zero?"); ++ } ++ res->markNotFree(); ++ assert(!res->is_free(), "shouldn't be marked free"); ++ assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); ++ // mangle a just allocated object with a distinct pattern. ++ debug_only(res->mangleAllocated(word_sz)); ++ return (HeapWord*)res; ++} ++ ++// Get a chunk of blocks of the right size and update related ++// book-keeping stats ++void CompactibleFreeListSpaceLAB::get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl) { ++ // Get the #blocks we want to claim ++ size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); ++ assert(n_blks > 0, "Error"); ++ assert(ResizeOldPLAB || n_blks == OldPLABSize, "Error"); ++ // In some cases, when the application has a phase change, ++ // there may be a sudden and sharp shift in the object survival ++ // profile, and updating the counts at the end of a scavenge ++ // may not be quick enough, giving rise to large scavenge pauses ++ // during these phase changes. It is beneficial to detect such ++ // changes on-the-fly during a scavenge and avoid such a phase-change ++ // pothole. The following code is a heuristic attempt to do that. ++ // It is protected by a product flag until we have gained ++ // enough experience with this heuristic and fine-tuned its behavior. ++ // WARNING: This might increase fragmentation if we overreact to ++ // small spikes, so some kind of historical smoothing based on ++ // previous experience with the greater reactivity might be useful. ++ // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by ++ // default. ++ if (ResizeOldPLAB && CMSOldPLABResizeQuicker) { ++ // ++ // On a 32-bit VM, the denominator can become zero because of integer overflow, ++ // which is why there is a cast to double. ++ // ++ size_t multiple = (size_t) (_num_blocks[word_sz]/(((double)CMSOldPLABToleranceFactor)*CMSOldPLABNumRefills*n_blks)); ++ n_blks += CMSOldPLABReactivityFactor*multiple*n_blks; ++ n_blks = MIN2(n_blks, CMSOldPLABMax); ++ } ++ assert(n_blks > 0, "Error"); ++ _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl); ++ // Update stats table entry for this block size ++ _num_blocks[word_sz] += fl->count(); ++} ++ ++void CompactibleFreeListSpaceLAB::compute_desired_plab_size() { ++ for (size_t i = CompactibleFreeListSpace::IndexSetStart; ++ i < CompactibleFreeListSpace::IndexSetSize; ++ i += CompactibleFreeListSpace::IndexSetStride) { ++ assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0), ++ "Counter inconsistency"); ++ if (_global_num_workers[i] > 0) { ++ // Need to smooth wrt historical average ++ if (ResizeOldPLAB) { ++ _blocks_to_claim[i].sample( ++ MAX2(CMSOldPLABMin, ++ MIN2(CMSOldPLABMax, ++ _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills))); ++ } ++ // Reset counters for next round ++ _global_num_workers[i] = 0; ++ _global_num_blocks[i] = 0; ++ log_trace(gc, plab)("[" SIZE_FORMAT "]: " SIZE_FORMAT, i, (size_t)_blocks_to_claim[i].average()); ++ } ++ } ++} ++ ++// If this is changed in the future to allow parallel ++// access, one would need to take the FL locks and, ++// depending on how it is used, stagger access from ++// parallel threads to reduce contention. ++void CompactibleFreeListSpaceLAB::retire(int tid) { ++ // We run this single threaded with the world stopped; ++ // so no need for locks and such. ++ NOT_PRODUCT(Thread* t = Thread::current();) ++ assert(Thread::current()->is_VM_thread(), "Error"); ++ for (size_t i = CompactibleFreeListSpace::IndexSetStart; ++ i < CompactibleFreeListSpace::IndexSetSize; ++ i += CompactibleFreeListSpace::IndexSetStride) { ++ assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), ++ "Can't retire more than what we obtained"); ++ if (_num_blocks[i] > 0) { ++ size_t num_retire = _indexedFreeList[i].count(); ++ assert(_num_blocks[i] > num_retire, "Should have used at least one"); ++ { ++ // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], ++ // Mutex::_no_safepoint_check_flag); ++ ++ // Update globals stats for num_blocks used ++ _global_num_blocks[i] += (_num_blocks[i] - num_retire); ++ _global_num_workers[i]++; ++ assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); ++ if (num_retire > 0) { ++ _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); ++ // Reset this list. ++ _indexedFreeList[i] = AdaptiveFreeList(); ++ _indexedFreeList[i].set_size(i); ++ } ++ } ++ log_trace(gc, plab)("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT, ++ tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); ++ // Reset stats for next round ++ _num_blocks[i] = 0; ++ } ++ } ++} ++ ++// Used by par_get_chunk_of_blocks() for the chunks from the ++// indexed_free_lists. Looks for a chunk with size that is a multiple ++// of "word_sz" and if found, splits it into "word_sz" chunks and add ++// to the free list "fl". "n" is the maximum number of chunks to ++// be added to "fl". ++bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl) { ++ ++ // We'll try all multiples of word_sz in the indexed set, starting with ++ // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, ++ // then try getting a big chunk and splitting it. ++ { ++ bool found; ++ int k; ++ size_t cur_sz; ++ for (k = 1, cur_sz = k * word_sz, found = false; ++ (cur_sz < CompactibleFreeListSpace::IndexSetSize) && ++ (CMSSplitIndexedFreeListBlocks || k <= 1); ++ k++, cur_sz = k * word_sz) { ++ AdaptiveFreeList fl_for_cur_sz; // Empty. ++ fl_for_cur_sz.set_size(cur_sz); ++ { ++ MutexLockerEx x(_indexedFreeListParLocks[cur_sz], ++ Mutex::_no_safepoint_check_flag); ++ AdaptiveFreeList* gfl = &_indexedFreeList[cur_sz]; ++ if (gfl->count() != 0) { ++ // nn is the number of chunks of size cur_sz that ++ // we'd need to split k-ways each, in order to create ++ // "n" chunks of size word_sz each. ++ const size_t nn = MAX2(n/k, (size_t)1); ++ gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); ++ found = true; ++ if (k > 1) { ++ // Update split death stats for the cur_sz-size blocks list: ++ // we increment the split death count by the number of blocks ++ // we just took from the cur_sz-size blocks list and which ++ // we will be splitting below. ++ ssize_t deaths = gfl->split_deaths() + ++ fl_for_cur_sz.count(); ++ gfl->set_split_deaths(deaths); ++ } ++ } ++ } ++ // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. ++ if (found) { ++ if (k == 1) { ++ fl->prepend(&fl_for_cur_sz); ++ } else { ++ // Divide each block on fl_for_cur_sz up k ways. ++ FreeChunk* fc; ++ while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) { ++ // Must do this in reverse order, so that anybody attempting to ++ // access the main chunk sees it as a single free block until we ++ // change it. ++ size_t fc_size = fc->size(); ++ assert(fc->is_free(), "Error"); ++ for (int i = k-1; i >= 0; i--) { ++ FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); ++ assert((i != 0) || ++ ((fc == ffc) && ffc->is_free() && ++ (ffc->size() == k*word_sz) && (fc_size == word_sz)), ++ "Counting error"); ++ ffc->set_size(word_sz); ++ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. ++ ffc->link_next(NULL); ++ // Above must occur before BOT is updated below. ++ OrderAccess::storestore(); ++ // splitting from the right, fc_size == i * word_sz ++ _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); ++ fc_size -= word_sz; ++ assert(fc_size == i*word_sz, "Error"); ++ _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); ++ _bt.verify_single_block((HeapWord*)fc, fc_size); ++ _bt.verify_single_block((HeapWord*)ffc, word_sz); ++ // Push this on "fl". ++ fl->return_chunk_at_head(ffc); ++ } ++ // TRAP ++ assert(fl->tail()->next() == NULL, "List invariant."); ++ } ++ } ++ // Update birth stats for this block size. ++ size_t num = fl->count(); ++ MutexLockerEx x(_indexedFreeListParLocks[word_sz], ++ Mutex::_no_safepoint_check_flag); ++ ssize_t births = _indexedFreeList[word_sz].split_births() + num; ++ _indexedFreeList[word_sz].set_split_births(births); ++ return true; ++ } ++ } ++ return found; ++ } ++} ++ ++FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { ++ ++ FreeChunk* fc = NULL; ++ FreeChunk* rem_fc = NULL; ++ size_t rem; ++ { ++ MutexLockerEx x(parDictionaryAllocLock(), ++ Mutex::_no_safepoint_check_flag); ++ while (n > 0) { ++ fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size())); ++ if (fc != NULL) { ++ break; ++ } else { ++ n--; ++ } ++ } ++ if (fc == NULL) return NULL; ++ // Otherwise, split up that block. ++ assert((ssize_t)n >= 1, "Control point invariant"); ++ assert(fc->is_free(), "Error: should be a free block"); ++ _bt.verify_single_block((HeapWord*)fc, fc->size()); ++ const size_t nn = fc->size() / word_sz; ++ n = MIN2(nn, n); ++ assert((ssize_t)n >= 1, "Control point invariant"); ++ rem = fc->size() - n * word_sz; ++ // If there is a remainder, and it's too small, allocate one fewer. ++ if (rem > 0 && rem < MinChunkSize) { ++ n--; rem += word_sz; ++ } ++ // Note that at this point we may have n == 0. ++ assert((ssize_t)n >= 0, "Control point invariant"); ++ ++ // If n is 0, the chunk fc that was found is not large ++ // enough to leave a viable remainder. We are unable to ++ // allocate even one block. Return fc to the ++ // dictionary and return, leaving "fl" empty. ++ if (n == 0) { ++ returnChunkToDictionary(fc); ++ return NULL; ++ } ++ ++ _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk ++ dictionary()->dict_census_update(fc->size(), ++ true /*split*/, ++ false /*birth*/); ++ ++ // First return the remainder, if any. ++ // Note that we hold the lock until we decide if we're going to give ++ // back the remainder to the dictionary, since a concurrent allocation ++ // may otherwise see the heap as empty. (We're willing to take that ++ // hit if the block is a small block.) ++ if (rem > 0) { ++ size_t prefix_size = n * word_sz; ++ rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); ++ rem_fc->set_size(rem); ++ rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. ++ rem_fc->link_next(NULL); ++ // Above must occur before BOT is updated below. ++ assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); ++ OrderAccess::storestore(); ++ _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); ++ assert(fc->is_free(), "Error"); ++ fc->set_size(prefix_size); ++ if (rem >= IndexSetSize) { ++ returnChunkToDictionary(rem_fc); ++ dictionary()->dict_census_update(rem, true /*split*/, true /*birth*/); ++ rem_fc = NULL; ++ } ++ // Otherwise, return it to the small list below. ++ } ++ } ++ if (rem_fc != NULL) { ++ MutexLockerEx x(_indexedFreeListParLocks[rem], ++ Mutex::_no_safepoint_check_flag); ++ _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); ++ _indexedFreeList[rem].return_chunk_at_head(rem_fc); ++ smallSplitBirth(rem); ++ } ++ assert(n * word_sz == fc->size(), ++ "Chunk size " SIZE_FORMAT " is not exactly splittable by " ++ SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, ++ fc->size(), n, word_sz); ++ return fc; ++} ++ ++void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList* fl) { ++ ++ FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); ++ ++ if (fc == NULL) { ++ return; ++ } ++ ++ size_t n = fc->size() / word_sz; ++ ++ assert((ssize_t)n > 0, "Consistency"); ++ // Now do the splitting up. ++ // Must do this in reverse order, so that anybody attempting to ++ // access the main chunk sees it as a single free block until we ++ // change it. ++ size_t fc_size = n * word_sz; ++ // All but first chunk in this loop ++ for (ssize_t i = n-1; i > 0; i--) { ++ FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); ++ ffc->set_size(word_sz); ++ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. ++ ffc->link_next(NULL); ++ // Above must occur before BOT is updated below. ++ OrderAccess::storestore(); ++ // splitting from the right, fc_size == (n - i + 1) * wordsize ++ _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); ++ fc_size -= word_sz; ++ _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); ++ _bt.verify_single_block((HeapWord*)ffc, ffc->size()); ++ _bt.verify_single_block((HeapWord*)fc, fc_size); ++ // Push this on "fl". ++ fl->return_chunk_at_head(ffc); ++ } ++ // First chunk ++ assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block"); ++ // The blocks above should show their new sizes before the first block below ++ fc->set_size(word_sz); ++ fc->link_prev(NULL); // idempotent wrt free-ness, see assert above ++ fc->link_next(NULL); ++ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); ++ _bt.verify_single_block((HeapWord*)fc, fc->size()); ++ fl->return_chunk_at_head(fc); ++ ++ assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); ++ { ++ // Update the stats for this block size. ++ MutexLockerEx x(_indexedFreeListParLocks[word_sz], ++ Mutex::_no_safepoint_check_flag); ++ const ssize_t births = _indexedFreeList[word_sz].split_births() + n; ++ _indexedFreeList[word_sz].set_split_births(births); ++ // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; ++ // _indexedFreeList[word_sz].set_surplus(new_surplus); ++ } ++ ++ // TRAP ++ assert(fl->tail()->next() == NULL, "List invariant."); ++} ++ ++void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { ++ assert(fl->count() == 0, "Precondition."); ++ assert(word_sz < CompactibleFreeListSpace::IndexSetSize, ++ "Precondition"); ++ ++ if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { ++ // Got it ++ return; ++ } ++ ++ // Otherwise, we'll split a block from the dictionary. ++ par_get_chunk_of_blocks_dictionary(word_sz, n, fl); ++} ++ ++const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { ++ const size_t ergo_max = _old_gen->reserved().word_size() / (CardTable::card_size_in_words * BitsPerWord); ++ return ergo_max; ++} ++ ++// Set up the space's par_seq_tasks structure for work claiming ++// for parallel rescan. See CMSParRemarkTask where this is currently used. ++// XXX Need to suitably abstract and generalize this and the next ++// method into one. ++void ++CompactibleFreeListSpace:: ++initialize_sequential_subtasks_for_rescan(int n_threads) { ++ // The "size" of each task is fixed according to rescan_task_size. ++ assert(n_threads > 0, "Unexpected n_threads argument"); ++ const size_t task_size = rescan_task_size(); ++ size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size; ++ assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect"); ++ assert(n_tasks == 0 || ++ ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) && ++ (used_region().start() + n_tasks*task_size >= used_region().end())), ++ "n_tasks calculation incorrect"); ++ SequentialSubTasksDone* pst = conc_par_seq_tasks(); ++ assert(!pst->valid(), "Clobbering existing data?"); ++ // Sets the condition for completion of the subtask (how many threads ++ // need to finish in order to be done). ++ pst->set_n_threads(n_threads); ++ pst->set_n_tasks((int)n_tasks); ++} ++ ++// Set up the space's par_seq_tasks structure for work claiming ++// for parallel concurrent marking. See CMSConcMarkTask where this is currently used. ++void ++CompactibleFreeListSpace:: ++initialize_sequential_subtasks_for_marking(int n_threads, ++ HeapWord* low) { ++ // The "size" of each task is fixed according to rescan_task_size. ++ assert(n_threads > 0, "Unexpected n_threads argument"); ++ const size_t task_size = marking_task_size(); ++ assert(task_size > CardTable::card_size_in_words && ++ (task_size % CardTable::card_size_in_words == 0), ++ "Otherwise arithmetic below would be incorrect"); ++ MemRegion span = _old_gen->reserved(); ++ if (low != NULL) { ++ if (span.contains(low)) { ++ // Align low down to a card boundary so that ++ // we can use block_offset_careful() on span boundaries. ++ HeapWord* aligned_low = align_down(low, CardTable::card_size); ++ // Clip span prefix at aligned_low ++ span = span.intersection(MemRegion(aligned_low, span.end())); ++ } else if (low > span.end()) { ++ span = MemRegion(low, low); // Null region ++ } // else use entire span ++ } ++ assert(span.is_empty() || ++ ((uintptr_t)span.start() % CardTable::card_size == 0), ++ "span should start at a card boundary"); ++ size_t n_tasks = (span.word_size() + task_size - 1)/task_size; ++ assert((n_tasks == 0) == span.is_empty(), "Inconsistency"); ++ assert(n_tasks == 0 || ++ ((span.start() + (n_tasks - 1)*task_size < span.end()) && ++ (span.start() + n_tasks*task_size >= span.end())), ++ "n_tasks calculation incorrect"); ++ SequentialSubTasksDone* pst = conc_par_seq_tasks(); ++ assert(!pst->valid(), "Clobbering existing data?"); ++ // Sets the condition for completion of the subtask (how many threads ++ // need to finish in order to be done). ++ pst->set_n_threads(n_threads); ++ pst->set_n_tasks((int)n_tasks); ++} +diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp +new file mode 100644 +index 00000000000..9fd2ea58320 +--- /dev/null ++++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp +@@ -0,0 +1,759 @@ ++/* ++ * Copyright (c) 2001, 2018, 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_CMS_COMPACTIBLEFREELISTSPACE_HPP ++#define SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP ++ ++#include "gc/cms/adaptiveFreeList.hpp" ++#include "gc/cms/promotionInfo.hpp" ++#include "gc/shared/blockOffsetTable.hpp" ++#include "gc/shared/cardTable.hpp" ++#include "gc/shared/space.hpp" ++#include "logging/log.hpp" ++#include "memory/binaryTreeDictionary.hpp" ++#include "memory/freeList.hpp" ++ ++// Classes in support of keeping track of promotions into a non-Contiguous ++// space, in this case a CompactibleFreeListSpace. ++ ++// Forward declarations ++class CMSCollector; ++class CompactibleFreeListSpace; ++class ConcurrentMarkSweepGeneration; ++class BlkClosure; ++class BlkClosureCareful; ++class FreeChunk; ++class UpwardsObjectClosure; ++class ObjectClosureCareful; ++class Klass; ++ ++class AFLBinaryTreeDictionary : public BinaryTreeDictionary > { ++ public: ++ AFLBinaryTreeDictionary(MemRegion mr) ++ : BinaryTreeDictionary >(mr) {} ++ ++ // Find the list with size "size" in the binary tree and update ++ // the statistics in the list according to "split" (chunk was ++ // split or coalesce) and "birth" (chunk was added or removed). ++ void dict_census_update(size_t size, bool split, bool birth); ++ // Return true if the dictionary is overpopulated (more chunks of ++ // this size than desired) for size "size". ++ bool coal_dict_over_populated(size_t size); ++ // Methods called at the beginning of a sweep to prepare the ++ // statistics for the sweep. ++ void begin_sweep_dict_census(double coalSurplusPercent, ++ float inter_sweep_current, ++ float inter_sweep_estimate, ++ float intra_sweep_estimate); ++ // Methods called after the end of a sweep to modify the ++ // statistics for the sweep. ++ void end_sweep_dict_census(double splitSurplusPercent); ++ // Accessors for statistics ++ void set_tree_surplus(double splitSurplusPercent); ++ void set_tree_hints(void); ++ // Reset statistics for all the lists in the tree. ++ void clear_tree_census(void); ++ // Print the statistics for all the lists in the tree. Also may ++ // print out summaries. ++ void print_dict_census(outputStream* st) const; ++}; ++ ++class LinearAllocBlock { ++ public: ++ LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), ++ _allocation_size_limit(0) {} ++ void set(HeapWord* ptr, size_t word_size, size_t refill_size, ++ size_t allocation_size_limit) { ++ _ptr = ptr; ++ _word_size = word_size; ++ _refillSize = refill_size; ++ _allocation_size_limit = allocation_size_limit; ++ } ++ HeapWord* _ptr; ++ size_t _word_size; ++ size_t _refillSize; ++ size_t _allocation_size_limit; // Largest size that will be allocated ++ ++ void print_on(outputStream* st) const; ++}; ++ ++// Concrete subclass of CompactibleSpace that implements ++// a free list space, such as used in the concurrent mark sweep ++// generation. ++ ++class CompactibleFreeListSpace: public CompactibleSpace { ++ friend class VMStructs; ++ friend class ConcurrentMarkSweepGeneration; ++ friend class CMSCollector; ++ // Local alloc buffer for promotion into this space. ++ friend class CompactibleFreeListSpaceLAB; ++ // Allow scan_and_* functions to call (private) overrides of the auxiliary functions on this class ++ template ++ friend void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space); ++ template ++ friend void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run); ++ template ++ friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); ++ template ++ friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); ++ ++ // "Size" of chunks of work (executed during parallel remark phases ++ // of CMS collection); this probably belongs in CMSCollector, although ++ // it's cached here because it's used in ++ // initialize_sequential_subtasks_for_rescan() which modifies ++ // par_seq_tasks which also lives in Space. XXX ++ const size_t _rescan_task_size; ++ const size_t _marking_task_size; ++ ++ // Yet another sequential tasks done structure. This supports ++ // CMS GC, where we have threads dynamically ++ // claiming sub-tasks from a larger parallel task. ++ SequentialSubTasksDone _conc_par_seq_tasks; ++ ++ BlockOffsetArrayNonContigSpace _bt; ++ ++ CMSCollector* _collector; ++ ConcurrentMarkSweepGeneration* _old_gen; ++ ++ // Data structures for free blocks (used during allocation/sweeping) ++ ++ // Allocation is done linearly from two different blocks depending on ++ // whether the request is small or large, in an effort to reduce ++ // fragmentation. We assume that any locking for allocation is done ++ // by the containing generation. Thus, none of the methods in this ++ // space are re-entrant. ++ enum SomeConstants { ++ SmallForLinearAlloc = 16, // size < this then use _sLAB ++ SmallForDictionary = 257, // size < this then use _indexedFreeList ++ IndexSetSize = SmallForDictionary // keep this odd-sized ++ }; ++ static size_t IndexSetStart; ++ static size_t IndexSetStride; ++ static size_t _min_chunk_size_in_bytes; ++ ++ private: ++ enum FitStrategyOptions { ++ FreeBlockStrategyNone = 0, ++ FreeBlockBestFitFirst ++ }; ++ ++ PromotionInfo _promoInfo; ++ ++ // Helps to impose a global total order on freelistLock ranks; ++ // assumes that CFLSpace's are allocated in global total order ++ static int _lockRank; ++ ++ // A lock protecting the free lists and free blocks; ++ // mutable because of ubiquity of locking even for otherwise const methods ++ mutable Mutex _freelistLock; ++ ++ // Locking verifier convenience function ++ void assert_locked() const PRODUCT_RETURN; ++ void assert_locked(const Mutex* lock) const PRODUCT_RETURN; ++ ++ // Linear allocation blocks ++ LinearAllocBlock _smallLinearAllocBlock; ++ ++ AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks ++ ++ // Indexed array for small size blocks ++ AdaptiveFreeList _indexedFreeList[IndexSetSize]; ++ ++ // Allocation strategy ++ bool _fitStrategy; // Use best fit strategy ++ ++ // This is an address close to the largest free chunk in the heap. ++ // It is currently assumed to be at the end of the heap. Free ++ // chunks with addresses greater than nearLargestChunk are coalesced ++ // in an effort to maintain a large chunk at the end of the heap. ++ HeapWord* _nearLargestChunk; ++ ++ // Used to keep track of limit of sweep for the space ++ HeapWord* _sweep_limit; ++ ++ // Stable value of used(). ++ size_t _used_stable; ++ ++ // Used to make the young collector update the mod union table ++ MemRegionClosure* _preconsumptionDirtyCardClosure; ++ ++ // Support for compacting cms ++ HeapWord* cross_threshold(HeapWord* start, HeapWord* end); ++ HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); ++ HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); ++ ++ // Initialization helpers. ++ void initializeIndexedFreeListArray(); ++ ++ // Extra stuff to manage promotion parallelism. ++ ++ // A lock protecting the dictionary during par promotion allocation. ++ mutable Mutex _parDictionaryAllocLock; ++ Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } ++ ++ // Locks protecting the exact lists during par promotion allocation. ++ Mutex* _indexedFreeListParLocks[IndexSetSize]; ++ ++ // Attempt to obtain up to "n" blocks of the size "word_sz" (which is ++ // required to be smaller than "IndexSetSize".) If successful, ++ // adds them to "fl", which is required to be an empty free list. ++ // If the count of "fl" is negative, it's absolute value indicates a ++ // number of free chunks that had been previously "borrowed" from global ++ // list of size "word_sz", and must now be decremented. ++ void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl); ++ ++ // Used by par_get_chunk_of_blocks() for the chunks from the ++ // indexed_free_lists. ++ bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl); ++ ++ // Used by par_get_chunk_of_blocks_dictionary() to get a chunk ++ // evenly splittable into "n" "word_sz" chunks. Returns that ++ // evenly splittable chunk. May split a larger chunk to get the ++ // evenly splittable chunk. ++ FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); ++ ++ // Used by par_get_chunk_of_blocks() for the chunks from the ++ // dictionary. ++ void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList* fl); ++ ++ // Allocation helper functions ++ // Allocate using a strategy that takes from the indexed free lists ++ // first. This allocation strategy assumes a companion sweeping ++ // strategy that attempts to keep the needed number of chunks in each ++ // indexed free lists. ++ HeapWord* allocate_adaptive_freelists(size_t size); ++ ++ // Gets a chunk from the linear allocation block (LinAB). If there ++ // is not enough space in the LinAB, refills it. ++ HeapWord* getChunkFromLinearAllocBlock(LinearAllocBlock* blk, size_t size); ++ HeapWord* getChunkFromSmallLinearAllocBlock(size_t size); ++ // Get a chunk from the space remaining in the linear allocation block. Do ++ // not attempt to refill if the space is not available, return NULL. Do the ++ // repairs on the linear allocation block as appropriate. ++ HeapWord* getChunkFromLinearAllocBlockRemainder(LinearAllocBlock* blk, size_t size); ++ inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); ++ ++ // Helper function for getChunkFromIndexedFreeList. ++ // Replenish the indexed free list for this "size". Do not take from an ++ // underpopulated size. ++ FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); ++ ++ // Get a chunk from the indexed free list. If the indexed free list ++ // does not have a free chunk, try to replenish the indexed free list ++ // then get the free chunk from the replenished indexed free list. ++ inline FreeChunk* getChunkFromIndexedFreeList(size_t size); ++ ++ // The returned chunk may be larger than requested (or null). ++ FreeChunk* getChunkFromDictionary(size_t size); ++ // The returned chunk is the exact size requested (or null). ++ FreeChunk* getChunkFromDictionaryExact(size_t size); ++ ++ // Find a chunk in the indexed free list that is the best ++ // fit for size "numWords". ++ FreeChunk* bestFitSmall(size_t numWords); ++ // For free list "fl" of chunks of size > numWords, ++ // remove a chunk, split off a chunk of size numWords ++ // and return it. The split off remainder is returned to ++ // the free lists. The old name for getFromListGreater ++ // was lookInListGreater. ++ FreeChunk* getFromListGreater(AdaptiveFreeList* fl, size_t numWords); ++ // Get a chunk in the indexed free list or dictionary, ++ // by considering a larger chunk and splitting it. ++ FreeChunk* getChunkFromGreater(size_t numWords); ++ // Verify that the given chunk is in the indexed free lists. ++ bool verifyChunkInIndexedFreeLists(FreeChunk* fc) const; ++ // Remove the specified chunk from the indexed free lists. ++ void removeChunkFromIndexedFreeList(FreeChunk* fc); ++ // Remove the specified chunk from the dictionary. ++ void removeChunkFromDictionary(FreeChunk* fc); ++ // Split a free chunk into a smaller free chunk of size "new_size". ++ // Return the smaller free chunk and return the remainder to the ++ // free lists. ++ FreeChunk* splitChunkAndReturnRemainder(FreeChunk* chunk, size_t new_size); ++ // Add a chunk to the free lists. ++ void addChunkToFreeLists(HeapWord* chunk, size_t size); ++ // Add a chunk to the free lists, preferring to suffix it ++ // to the last free chunk at end of space if possible, and ++ // updating the block census stats as well as block offset table. ++ // Take any locks as appropriate if we are multithreaded. ++ void addChunkToFreeListsAtEndRecordingStats(HeapWord* chunk, size_t size); ++ // Add a free chunk to the indexed free lists. ++ void returnChunkToFreeList(FreeChunk* chunk); ++ // Add a free chunk to the dictionary. ++ void returnChunkToDictionary(FreeChunk* chunk); ++ ++ // Functions for maintaining the linear allocation buffers (LinAB). ++ // Repairing a linear allocation block refers to operations ++ // performed on the remainder of a LinAB after an allocation ++ // has been made from it. ++ void repairLinearAllocationBlocks(); ++ void repairLinearAllocBlock(LinearAllocBlock* blk); ++ void refillLinearAllocBlock(LinearAllocBlock* blk); ++ void refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk); ++ void refillLinearAllocBlocksIfNeeded(); ++ ++ void verify_objects_initialized() const; ++ ++ // Statistics reporting helper functions ++ void reportFreeListStatistics(const char* title) const; ++ void reportIndexedFreeListStatistics(outputStream* st) const; ++ size_t maxChunkSizeInIndexedFreeLists() const; ++ size_t numFreeBlocksInIndexedFreeLists() const; ++ // Accessor ++ HeapWord* unallocated_block() const { ++ if (BlockOffsetArrayUseUnallocatedBlock) { ++ HeapWord* ub = _bt.unallocated_block(); ++ assert(ub >= bottom() && ++ ub <= end(), "space invariant"); ++ return ub; ++ } else { ++ return end(); ++ } ++ } ++ void freed(HeapWord* start, size_t size) { ++ _bt.freed(start, size); ++ } ++ ++ // Auxiliary functions for scan_and_{forward,adjust_pointers,compact} support. ++ // See comments for CompactibleSpace for more information. ++ inline HeapWord* scan_limit() const { ++ return end(); ++ } ++ ++ inline bool scanned_block_is_obj(const HeapWord* addr) const { ++ return CompactibleFreeListSpace::block_is_obj(addr); // Avoid virtual call ++ } ++ ++ inline size_t scanned_block_size(const HeapWord* addr) const { ++ return CompactibleFreeListSpace::block_size(addr); // Avoid virtual call ++ } ++ ++ inline size_t adjust_obj_size(size_t size) const { ++ return adjustObjectSize(size); ++ } ++ ++ inline size_t obj_size(const HeapWord* addr) const; ++ ++ protected: ++ // Reset the indexed free list to its initial empty condition. ++ void resetIndexedFreeListArray(); ++ // Reset to an initial state with a single free block described ++ // by the MemRegion parameter. ++ void reset(MemRegion mr); ++ // Return the total number of words in the indexed free lists. ++ size_t totalSizeInIndexedFreeLists() const; ++ ++ public: ++ // Constructor ++ CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); ++ // Accessors ++ bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } ++ AFLBinaryTreeDictionary* dictionary() const { return _dictionary; } ++ HeapWord* nearLargestChunk() const { return _nearLargestChunk; } ++ void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; } ++ ++ // Set CMS global values. ++ static void set_cms_values(); ++ ++ // Return the free chunk at the end of the space. If no such ++ // chunk exists, return NULL. ++ FreeChunk* find_chunk_at_end(); ++ ++ void set_collector(CMSCollector* collector) { _collector = collector; } ++ ++ // Support for parallelization of rescan and marking. ++ const size_t rescan_task_size() const { return _rescan_task_size; } ++ const size_t marking_task_size() const { return _marking_task_size; } ++ // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. ++ const size_t max_flag_size_for_task_size() const; ++ SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } ++ void initialize_sequential_subtasks_for_rescan(int n_threads); ++ void initialize_sequential_subtasks_for_marking(int n_threads, ++ HeapWord* low = NULL); ++ ++ virtual MemRegionClosure* preconsumptionDirtyCardClosure() const { ++ return _preconsumptionDirtyCardClosure; ++ } ++ ++ void setPreconsumptionDirtyCardClosure(MemRegionClosure* cl) { ++ _preconsumptionDirtyCardClosure = cl; ++ } ++ ++ // Space enquiries ++ size_t used() const; ++ size_t free() const; ++ size_t max_alloc_in_words() const; ++ // XXX: should have a less conservative used_region() than that of ++ // Space; we could consider keeping track of highest allocated ++ // address and correcting that at each sweep, as the sweeper ++ // goes through the entire allocated part of the generation. We ++ // could also use that information to keep the sweeper from ++ // sweeping more than is necessary. The allocator and sweeper will ++ // of course need to synchronize on this, since the sweeper will ++ // try to bump down the address and the allocator will try to bump it up. ++ // For now, however, we'll just use the default used_region() ++ // which overestimates the region by returning the entire ++ // committed region (this is safe, but inefficient). ++ ++ // Returns monotonically increasing stable used space bytes for CMS. ++ // This is required for jstat and other memory monitoring tools ++ // that might otherwise see inconsistent used space values during a garbage ++ // collection, promotion or allocation into compactibleFreeListSpace. ++ // The value returned by this function might be smaller than the ++ // actual value. ++ size_t used_stable() const; ++ // Recalculate and cache the current stable used() value. Only to be called ++ // in places where we can be sure that the result is stable. ++ void recalculate_used_stable(); ++ ++ // Returns a subregion of the space containing all the objects in ++ // the space. ++ MemRegion used_region() const { ++ return MemRegion(bottom(), ++ BlockOffsetArrayUseUnallocatedBlock ? ++ unallocated_block() : end()); ++ } ++ ++ virtual bool is_free_block(const HeapWord* p) const; ++ ++ // Resizing support ++ void set_end(HeapWord* value); // override ++ ++ // Never mangle CompactibleFreeListSpace ++ void mangle_unused_area() {} ++ void mangle_unused_area_complete() {} ++ ++ // Mutual exclusion support ++ Mutex* freelistLock() const { return &_freelistLock; } ++ ++ // Iteration support ++ void oop_iterate(OopIterateClosure* cl); ++ ++ void object_iterate(ObjectClosure* blk); ++ // Apply the closure to each object in the space whose references ++ // point to objects in the heap. The usage of CompactibleFreeListSpace ++ // by the ConcurrentMarkSweepGeneration for concurrent GC's allows ++ // objects in the space with references to objects that are no longer ++ // valid. For example, an object may reference another object ++ // that has already been sweep up (collected). This method uses ++ // obj_is_alive() to determine whether it is safe to iterate of ++ // an object. ++ void safe_object_iterate(ObjectClosure* blk); ++ ++ // Iterate over all objects that intersect with mr, calling "cl->do_object" ++ // on each. There is an exception to this: if this closure has already ++ // been invoked on an object, it may skip such objects in some cases. This is ++ // Most likely to happen in an "upwards" (ascending address) iteration of ++ // MemRegions. ++ void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); ++ ++ // Requires that "mr" be entirely within the space. ++ // Apply "cl->do_object" to all objects that intersect with "mr". ++ // If the iteration encounters an unparseable portion of the region, ++ // terminate the iteration and return the address of the start of the ++ // subregion that isn't done. Return of "NULL" indicates that the ++ // iteration completed. ++ HeapWord* object_iterate_careful_m(MemRegion mr, ++ ObjectClosureCareful* cl); ++ ++ // Override: provides a DCTO_CL specific to this kind of space. ++ DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, ++ CardTable::PrecisionStyle precision, ++ HeapWord* boundary, ++ bool parallel); ++ ++ void blk_iterate(BlkClosure* cl); ++ void blk_iterate_careful(BlkClosureCareful* cl); ++ HeapWord* block_start_const(const void* p) const; ++ HeapWord* block_start_careful(const void* p) const; ++ size_t block_size(const HeapWord* p) const; ++ size_t block_size_no_stall(HeapWord* p, const CMSCollector* c) const; ++ bool block_is_obj(const HeapWord* p) const; ++ bool obj_is_alive(const HeapWord* p) const; ++ size_t block_size_nopar(const HeapWord* p) const; ++ bool block_is_obj_nopar(const HeapWord* p) const; ++ ++ // Iteration support for promotion ++ void save_marks(); ++ bool no_allocs_since_save_marks(); ++ ++ // Iteration support for sweeping ++ void save_sweep_limit() { ++ _sweep_limit = BlockOffsetArrayUseUnallocatedBlock ? ++ unallocated_block() : end(); ++ log_develop_trace(gc, sweep)(">>>>> Saving sweep limit " PTR_FORMAT ++ " for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<", ++ p2i(_sweep_limit), p2i(bottom()), p2i(end())); ++ } ++ NOT_PRODUCT( ++ void clear_sweep_limit() { _sweep_limit = NULL; } ++ ) ++ HeapWord* sweep_limit() { return _sweep_limit; } ++ ++ // Apply "blk->do_oop" to the addresses of all reference fields in objects ++ // promoted into this generation since the most recent save_marks() call. ++ // Fields in objects allocated by applications of the closure ++ // *are* included in the iteration. Thus, when the iteration completes ++ // there should be no further such objects remaining. ++ template ++ void oop_since_save_marks_iterate(OopClosureType* blk); ++ ++ // Allocation support ++ HeapWord* allocate(size_t size); ++ HeapWord* par_allocate(size_t size); ++ ++ oop promote(oop obj, size_t obj_size); ++ void gc_prologue(); ++ void gc_epilogue(); ++ ++ // This call is used by a containing CMS generation / collector ++ // to inform the CFLS space that a sweep has been completed ++ // and that the space can do any related house-keeping functions. ++ void sweep_completed(); ++ ++ // For an object in this space, the mark-word's two ++ // LSB's having the value [11] indicates that it has been ++ // promoted since the most recent call to save_marks() on ++ // this generation and has not subsequently been iterated ++ // over (using oop_since_save_marks_iterate() above). ++ // This property holds only for single-threaded collections, ++ // and is typically used for Cheney scans; for MT scavenges, ++ // the property holds for all objects promoted during that ++ // scavenge for the duration of the scavenge and is used ++ // by card-scanning to avoid scanning objects (being) promoted ++ // during that scavenge. ++ bool obj_allocated_since_save_marks(const oop obj) const { ++ assert(is_in_reserved(obj), "Wrong space?"); ++ return ((PromotedObject*)obj)->hasPromotedMark(); ++ } ++ ++ // A worst-case estimate of the space required (in HeapWords) to expand the ++ // heap when promoting an obj of size obj_size. ++ size_t expansionSpaceRequired(size_t obj_size) const; ++ ++ FreeChunk* allocateScratch(size_t size); ++ ++ // Returns true if either the small or large linear allocation buffer is empty. ++ bool linearAllocationWouldFail() const; ++ ++ // Adjust the chunk for the minimum size. This version is called in ++ // most cases in CompactibleFreeListSpace methods. ++ inline static size_t adjustObjectSize(size_t size) { ++ return align_object_size(MAX2(size, (size_t)MinChunkSize)); ++ } ++ // This is a virtual version of adjustObjectSize() that is called ++ // only occasionally when the compaction space changes and the type ++ // of the new compaction space is is only known to be CompactibleSpace. ++ size_t adjust_object_size_v(size_t size) const { ++ return adjustObjectSize(size); ++ } ++ // Minimum size of a free block. ++ virtual size_t minimum_free_block_size() const { return MinChunkSize; } ++ void removeFreeChunkFromFreeLists(FreeChunk* chunk); ++ void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, ++ bool coalesced); ++ ++ // Support for compaction. ++ void prepare_for_compaction(CompactPoint* cp); ++ void adjust_pointers(); ++ void compact(); ++ // Reset the space to reflect the fact that a compaction of the ++ // space has been done. ++ virtual void reset_after_compaction(); ++ ++ // Debugging support. ++ void print() const; ++ void print_on(outputStream* st) const; ++ void prepare_for_verify(); ++ void verify() const; ++ void verifyFreeLists() const PRODUCT_RETURN; ++ void verifyIndexedFreeLists() const; ++ void verifyIndexedFreeList(size_t size) const; ++ // Verify that the given chunk is in the free lists: ++ // i.e. either the binary tree dictionary, the indexed free lists ++ // or the linear allocation block. ++ bool verify_chunk_in_free_list(FreeChunk* fc) const; ++ // Verify that the given chunk is the linear allocation block. ++ bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; ++ // Do some basic checks on the the free lists. ++ void check_free_list_consistency() const PRODUCT_RETURN; ++ ++ // Printing support ++ void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); ++ void print_indexed_free_lists(outputStream* st) const; ++ void print_dictionary_free_lists(outputStream* st) const; ++ void print_promo_info_blocks(outputStream* st) const; ++ ++ NOT_PRODUCT ( ++ void initializeIndexedFreeListArrayReturnedBytes(); ++ size_t sumIndexedFreeListArrayReturnedBytes(); ++ // Return the total number of chunks in the indexed free lists. ++ size_t totalCountInIndexedFreeLists() const; ++ // Return the total number of chunks in the space. ++ size_t totalCount(); ++ ) ++ ++ // The census consists of counts of the quantities such as ++ // the current count of the free chunks, number of chunks ++ // created as a result of the split of a larger chunk or ++ // coalescing of smaller chucks, etc. The counts in the ++ // census is used to make decisions on splitting and ++ // coalescing of chunks during the sweep of garbage. ++ ++ // Print the statistics for the free lists. ++ void printFLCensus(size_t sweep_count) const; ++ ++ // Statistics functions ++ // Initialize census for lists before the sweep. ++ void beginSweepFLCensus(float inter_sweep_current, ++ float inter_sweep_estimate, ++ float intra_sweep_estimate); ++ // Set the surplus for each of the free lists. ++ void setFLSurplus(); ++ // Set the hint for each of the free lists. ++ void setFLHints(); ++ // Clear the census for each of the free lists. ++ void clearFLCensus(); ++ // Perform functions for the census after the end of the sweep. ++ void endSweepFLCensus(size_t sweep_count); ++ // Return true if the count of free chunks is greater ++ // than the desired number of free chunks. ++ bool coalOverPopulated(size_t size); ++ ++// Record (for each size): ++// ++// split-births = #chunks added due to splits in (prev-sweep-end, ++// this-sweep-start) ++// split-deaths = #chunks removed for splits in (prev-sweep-end, ++// this-sweep-start) ++// num-curr = #chunks at start of this sweep ++// num-prev = #chunks at end of previous sweep ++// ++// The above are quantities that are measured. Now define: ++// ++// num-desired := num-prev + split-births - split-deaths - num-curr ++// ++// Roughly, num-prev + split-births is the supply, ++// split-deaths is demand due to other sizes ++// and num-curr is what we have left. ++// ++// Thus, num-desired is roughly speaking the "legitimate demand" ++// for blocks of this size and what we are striving to reach at the ++// end of the current sweep. ++// ++// For a given list, let num-len be its current population. ++// Define, for a free list of a given size: ++// ++// coal-overpopulated := num-len >= num-desired * coal-surplus ++// (coal-surplus is set to 1.05, i.e. we allow a little slop when ++// coalescing -- we do not coalesce unless we think that the current ++// supply has exceeded the estimated demand by more than 5%). ++// ++// For the set of sizes in the binary tree, which is neither dense nor ++// closed, it may be the case that for a particular size we have never ++// had, or do not now have, or did not have at the previous sweep, ++// chunks of that size. We need to extend the definition of ++// coal-overpopulated to such sizes as well: ++// ++// For a chunk in/not in the binary tree, extend coal-overpopulated ++// defined above to include all sizes as follows: ++// ++// . a size that is non-existent is coal-overpopulated ++// . a size that has a num-desired <= 0 as defined above is ++// coal-overpopulated. ++// ++// Also define, for a chunk heap-offset C and mountain heap-offset M: ++// ++// close-to-mountain := C >= 0.99 * M ++// ++// Now, the coalescing strategy is: ++// ++// Coalesce left-hand chunk with right-hand chunk if and ++// only if: ++// ++// EITHER ++// . left-hand chunk is of a size that is coal-overpopulated ++// OR ++// . right-hand chunk is close-to-mountain ++ void smallCoalBirth(size_t size); ++ void smallCoalDeath(size_t size); ++ void coalBirth(size_t size); ++ void coalDeath(size_t size); ++ void smallSplitBirth(size_t size); ++ void smallSplitDeath(size_t size); ++ void split_birth(size_t size); ++ void splitDeath(size_t size); ++ void split(size_t from, size_t to1); ++ ++ double flsFrag() const; ++}; ++ ++// A parallel-GC-thread-local allocation buffer for allocation into a ++// CompactibleFreeListSpace. ++class CompactibleFreeListSpaceLAB : public CHeapObj { ++ // The space that this buffer allocates into. ++ CompactibleFreeListSpace* _cfls; ++ ++ // Our local free lists. ++ AdaptiveFreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; ++ ++ // Initialized from a command-line arg. ++ ++ // Allocation statistics in support of dynamic adjustment of ++ // #blocks to claim per get_from_global_pool() call below. ++ static AdaptiveWeightedAverage ++ _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; ++ static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; ++ static uint _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; ++ size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; ++ ++ // Internal work method ++ void get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl); ++ ++public: ++ static const int _default_dynamic_old_plab_size = 16; ++ static const int _default_static_old_plab_size = 50; ++ ++ CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls); ++ ++ // Allocate and return a block of the given size, or else return NULL. ++ HeapWord* alloc(size_t word_sz); ++ ++ // Return any unused portions of the buffer to the global pool. ++ void retire(int tid); ++ ++ // Dynamic OldPLABSize sizing ++ static void compute_desired_plab_size(); ++ // When the settings are modified from default static initialization ++ static void modify_initialization(size_t n, unsigned wt); ++}; ++ ++size_t PromotionInfo::refillSize() const { ++ const size_t CMSSpoolBlockSize = 256; ++ const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) ++ * CMSSpoolBlockSize); ++ return CompactibleFreeListSpace::adjustObjectSize(sz); ++} ++ ++#endif // SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP +diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp +index 28c5990c66e..72f571645a5 100644 +--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp ++++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp +@@ -325,10 +325,14 @@ void GenMarkSweep::mark_sweep_phase4() { + // in the same order in phase2, phase3 and phase4. We don't quite do that + // here (perm_gen first rather than last), so we tell the validate code + // to use a higher index (saved from phase2) when verifying perm_gen. ++ assert(_rescued_oops == NULL, "must be empty before processing"); + GenCollectedHeap* gch = GenCollectedHeap::heap(); + + GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer); + ++// MarkSweep::copy_rescued_objects_back(); ++ + GenCompactClosure blk; + gch->generation_iterate(&blk, true); ++ MarkSweep::copy_rescued_objects_back(); + } +diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp +index ebe0da25766..c7befd2f63d 100644 +--- a/src/hotspot/share/gc/serial/markSweep.cpp ++++ b/src/hotspot/share/gc/serial/markSweep.cpp +@@ -57,6 +57,8 @@ ReferenceProcessor* MarkSweep::_ref_processor = NULL; + STWGCTimer* MarkSweep::_gc_timer = NULL; + SerialOldTracer* MarkSweep::_gc_tracer = NULL; + ++GrowableArray* MarkSweep::_rescued_oops = NULL; ++ + MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; + + MarkAndPushClosure MarkSweep::mark_and_push_closure; +@@ -222,3 +224,100 @@ void MarkSweep::initialize() { + MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); + MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); + } ++ ++// (DCEVM) Copy the rescued objects to their destination address after compaction. ++void MarkSweep::copy_rescued_objects_back() { ++ ++ if (_rescued_oops != NULL) { ++ ++ for (int i=0; i<_rescued_oops->length(); i++) { ++ HeapWord* rescued_ptr = _rescued_oops->at(i); ++ oop rescued_obj = (oop) rescued_ptr; ++ ++ int size = rescued_obj->size(); ++ oop new_obj = rescued_obj->forwardee(); ++ ++ assert(rescued_obj->klass()->new_version() != NULL, "just checking"); ++ ++ if (rescued_obj->klass()->new_version()->update_information() != NULL) { ++ MarkSweep::update_fields(rescued_obj, new_obj); ++ } else { ++ rescued_obj->set_klass(rescued_obj->klass()->new_version()); ++ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); ++ } ++ ++ FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); ++ ++ new_obj->init_mark(); ++ assert(oopDesc::is_oop(new_obj), "must be a valid oop"); ++ } ++ _rescued_oops->clear(); ++ _rescued_oops = NULL; ++ } ++} ++ ++// (DCEVM) Update instances of a class whose fields changed. ++void MarkSweep::update_fields(oop q, oop new_location) { ++ ++ assert(q->klass()->new_version() != NULL, "class of old object must have new version"); ++ ++ Klass* old_klass_oop = q->klass(); ++ Klass* new_klass_oop = q->klass()->new_version(); ++ ++ InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); ++ InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); ++ ++ int size = q->size_given_klass(old_klass); ++ int new_size = q->size_given_klass(new_klass); ++ ++ HeapWord* tmp = NULL; ++ oop tmp_obj = q; ++ ++ // Save object somewhere, there is an overlap in fields ++ if (new_klass_oop->is_copying_backwards()) { ++ if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || ++ ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { ++ tmp = NEW_RESOURCE_ARRAY(HeapWord, size); ++ q = (oop) tmp; ++ Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); ++ } ++ } ++ ++ q->set_klass(new_klass_oop); ++ int *cur = new_klass_oop->update_information(); ++ assert(cur != NULL, "just checking"); ++ MarkSweep::update_fields(new_location, q, cur); ++ ++ if (tmp != NULL) { ++ FREE_RESOURCE_ARRAY(HeapWord, tmp, size); ++ } ++} ++ ++void MarkSweep::update_fields(oop new_location, oop tmp_obj, int *cur) { ++ assert(cur != NULL, "just checking"); ++ char* to = (char*)(HeapWord*)new_location; ++ while (*cur != 0) { ++ int size = *cur; ++ if (size > 0) { ++ cur++; ++ int offset = *cur; ++ HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); ++ if (size == HeapWordSize) { ++ *((HeapWord*)to) = *from; ++ } else if (size == HeapWordSize * 2) { ++ *((HeapWord*)to) = *from; ++ *(((HeapWord*)to) + 1) = *(from + 1); ++ } else { ++ Copy::conjoint_jbytes(from, to, size); ++ } ++ to += size; ++ cur++; ++ } else { ++ assert(size < 0, ""); ++ int skip = -*cur; ++ Copy::fill_to_bytes(to, skip, 0); ++ to += skip; ++ cur++; ++ } ++ } ++} +diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp +index e9588a527e1..e12ac327d90 100644 +--- a/src/hotspot/share/gc/serial/markSweep.hpp ++++ b/src/hotspot/share/gc/serial/markSweep.hpp +@@ -87,6 +87,10 @@ class MarkSweep : AllStatic { + friend class AdjustPointerClosure; + friend class KeepAliveClosure; + friend class VM_MarkSweep; ++ friend class GenMarkSweep; ++ ++ public: ++ static GrowableArray* _rescued_oops; + + // + // Vars +@@ -144,6 +148,9 @@ class MarkSweep : AllStatic { + + static int adjust_pointers(oop obj); + ++ static void copy_rescued_objects_back(); ++ static void update_fields(oop q, oop new_location); ++ static void update_fields(oop new_location, oop tmp_obj, int *cur); + static void follow_stack(); // Empty marking stack. + + static void follow_klass(Klass* klass); +diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp +index 39d860b20a1..fdb1c806559 100644 +--- a/src/hotspot/share/gc/shared/gcConfig.cpp ++++ b/src/hotspot/share/gc/shared/gcConfig.cpp +@@ -98,7 +98,10 @@ void GCConfig::fail_if_non_included_gc_is_selected() { + } + + void GCConfig::select_gc_ergonomically() { +- if (os::is_server_class_machine()) { ++ if (AllowEnhancedClassRedefinition) { ++ // Enhanced class redefinition only supports serial GC at the moment ++ FLAG_SET_ERGO(bool, UseSerialGC, true); ++ } else if (os::is_server_class_machine()) { + #if INCLUDE_G1GC + FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); + #elif INCLUDE_PARALLELGC +diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp +index 6e215c8e6b7..0fefc5da478 100644 +--- a/src/hotspot/share/gc/shared/space.cpp ++++ b/src/hotspot/share/gc/shared/space.cpp +@@ -350,9 +350,8 @@ void CompactibleSpace::clear(bool mangle_space) { + _compaction_top = bottom(); + } + +-HeapWord* CompactibleSpace::forward(oop q, size_t size, +- CompactPoint* cp, HeapWord* compact_top) { +- // q is alive ++// (DCEVM) Calculates the compact_top that will be used for placing the next object with the giving size on the heap. ++HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top) { + // First check if we should switch compaction space + assert(this == cp->space, "'this' should be current compaction space."); + size_t compaction_max_size = pointer_delta(end(), compact_top); +@@ -372,8 +371,15 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, + compaction_max_size = pointer_delta(cp->space->end(), compact_top); + } + ++ return compact_top; ++} ++ ++HeapWord* CompactibleSpace::forward(oop q, size_t size, ++ CompactPoint* cp, HeapWord* compact_top) { ++ compact_top = forward_compact_top(size, cp, compact_top); ++ + // store the forwarding pointer into the mark word +- if (cast_from_oop(q) != compact_top) { ++ if (cast_from_oop(q) != compact_top || (size_t)q->size() != size) { + q->forward_to(oop(compact_top)); + assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); + } else { +@@ -397,7 +403,132 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, + #if INCLUDE_SERIALGC + + void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { +- scan_and_forward(this, cp); ++ if (!Universe::is_redefining_gc_run()) { ++ scan_and_forward(this, cp, false); ++ } else { ++ // Redefinition run ++ scan_and_forward(this, cp, true); ++ } ++} ++ ++ ++#ifdef ASSERT ++ ++int CompactibleSpace::space_index(oop obj) { ++ GenCollectedHeap* heap = GenCollectedHeap::heap(); ++ ++ //if (heap->is_in_permanent(obj)) { ++ // return -1; ++ //} ++ ++ int index = 0; ++ CompactibleSpace* space = heap->old_gen()->first_compaction_space(); ++ while (space != NULL) { ++ if (space->is_in_reserved(obj)) { ++ return index; ++ } ++ space = space->next_compaction_space(); ++ index++; ++ } ++ ++ space = heap->young_gen()->first_compaction_space(); ++ while (space != NULL) { ++ if (space->is_in_reserved(obj)) { ++ return index; ++ } ++ space = space->next_compaction_space(); ++ index++; ++ } ++ ++ tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj); ++ index = 0; ++ ++ Generation* gen = heap->old_gen(); ++ tty->print_cr(" generation %s: %08xh - %08xh", gen->name(), gen->reserved().start(), gen->reserved().end()); ++ ++ space = gen->first_compaction_space(); ++ while (space != NULL) { ++ tty->print_cr(" %2d space %08xh - %08xh", index, space->bottom(), space->end()); ++ space = space->next_compaction_space(); ++ index++; ++ } ++ ++ gen = heap->young_gen(); ++ tty->print_cr(" generation %s: %08xh - %08xh", gen->name(), gen->reserved().start(), gen->reserved().end()); ++ ++ space = gen->first_compaction_space(); ++ while (space != NULL) { ++ tty->print_cr(" %2d space %08xh - %08xh", index, space->bottom(), space->end()); ++ space = space->next_compaction_space(); ++ index++; ++ } ++ ++ ShouldNotReachHere(); ++ return 0; ++} ++#endif ++ ++bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { ++ // Only redefined objects can have the need to be rescued. ++ if (oop(old_obj)->klass()->new_version() == NULL) return false; ++ ++ //if (old_obj->is_perm()) { ++ // // This object is in perm gen: Always rescue to satisfy invariant obj->klass() <= obj. ++ // return true; ++ //} ++ ++ int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); ++ int original_size = old_obj->size(); ++ ++ Generation* tenured_gen = GenCollectedHeap::heap()->old_gen(); ++ bool old_in_tenured = tenured_gen->is_in_reserved(old_obj); ++ bool new_in_tenured = tenured_gen->is_in_reserved(new_obj); ++ if (old_in_tenured == new_in_tenured) { ++ // Rescue if object may overlap with a higher memory address. ++ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); ++ if (old_in_tenured) { ++ // Old and new address are in same space, so just compare the address. ++ // Must rescue if object moves towards the top of the space. ++ assert(space_index(old_obj) == space_index(new_obj), "old_obj and new_obj must be in same space"); ++ } else { ++ // In the new generation, eden is located before the from space, so a ++ // simple pointer comparison is sufficient. ++ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); ++ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration"); ++ assert(overlap == (space_index(old_obj) < space_index(new_obj)), "slow and fast computation must yield same result"); ++ } ++ return overlap; ++ ++ } else { ++ assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces"); ++ if (tenured_gen->is_in_reserved(new_obj)) { ++ // Must never rescue when moving from the new into the old generation. ++ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); ++ assert(space_index(old_obj) > space_index(new_obj), "must be"); ++ return false; ++ ++ } else /* if (tenured_gen->is_in_reserved(old_obj)) */ { ++ // Must always rescue when moving from the old into the new generation. ++ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration"); ++ assert(space_index(old_obj) < space_index(new_obj), "must be"); ++ return true; ++ } ++ } ++} ++ ++HeapWord* CompactibleSpace::rescue(HeapWord* old_obj) { ++ assert(must_rescue(oop(old_obj), oop(old_obj)->forwardee()), "do not call otherwise"); ++ ++ int size = oop(old_obj)->size(); ++ HeapWord* rescued_obj = NEW_RESOURCE_ARRAY(HeapWord, size); ++ Copy::aligned_disjoint_words(old_obj, rescued_obj, size); ++ ++ if (MarkSweep::_rescued_oops == NULL) { ++ MarkSweep::_rescued_oops = new GrowableArray(128); ++ } ++ ++ MarkSweep::_rescued_oops->append(rescued_obj); ++ return rescued_obj; + } + + void CompactibleSpace::adjust_pointers() { +@@ -410,7 +541,12 @@ void CompactibleSpace::adjust_pointers() { + } + + void CompactibleSpace::compact() { +- scan_and_compact(this); ++ if(!Universe::is_redefining_gc_run()) { ++ scan_and_compact(this, false); ++ } else { ++ // Redefinition run ++ scan_and_compact(this, true); ++ } + } + + #endif // INCLUDE_SERIALGC +@@ -685,6 +821,58 @@ void OffsetTableContigSpace::verify() const { + guarantee(p == top(), "end of last object must match end of space"); + } + ++// Compute the forward sizes and leave out objects whose position could ++// possibly overlap other objects. ++HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, ++ CompactPoint* cp, HeapWord* compact_top) { ++ size_t forward_size = size; ++ ++ // (DCEVM) There is a new version of the class of q => different size ++ if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) { ++ ++ size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); ++ assert(size != new_size, "instances without changed size have to be updated prior to GC run"); ++ forward_size = new_size; ++ } ++ ++ compact_top = forward_compact_top(forward_size, cp, compact_top); ++ ++ if (must_rescue(oop(q), oop(compact_top))) { ++ if (MarkSweep::_rescued_oops == NULL) { ++ MarkSweep::_rescued_oops = new GrowableArray(128); ++ } ++ MarkSweep::_rescued_oops->append(q); ++ return compact_top; ++ } ++ ++ return forward(oop(q), forward_size, cp, compact_top); ++} ++ ++// Compute the forwarding addresses for the objects that need to be rescued. ++HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_top) { ++ // TODO: empty the _rescued_oops after ALL spaces are compacted! ++ if (MarkSweep::_rescued_oops != NULL) { ++ for (int i=0; ilength(); i++) { ++ HeapWord* q = MarkSweep::_rescued_oops->at(i); ++ ++ /* size_t size = oop(q)->size(); changing this for cms for perm gen */ ++ size_t size = block_size(q); ++ ++ // (DCEVM) There is a new version of the class of q => different size ++ if (oop(q)->klass()->new_version() != NULL) { ++ size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); ++ assert(size != new_size, "instances without changed size have to be updated prior to GC run"); ++ size = new_size; ++ } ++ ++ compact_top = cp->space->forward(oop(q), size, cp, compact_top); ++ assert(compact_top <= end(), "must not write over end of space!"); ++ } ++ MarkSweep::_rescued_oops->clear(); ++ MarkSweep::_rescued_oops = NULL; ++ } ++ return compact_top; ++} + + size_t TenuredSpace::allowed_dead_ratio() const { + return MarkSweepDeadRatio; +diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp +index 0b760364bbc..c9bfc365f0f 100644 +--- a/src/hotspot/share/gc/shared/space.hpp ++++ b/src/hotspot/share/gc/shared/space.hpp +@@ -404,6 +404,9 @@ public: + // indicates when the next such action should be taken. + virtual void prepare_for_compaction(CompactPoint* cp) = 0; + // MarkSweep support phase3 ++ DEBUG_ONLY(int space_index(oop obj)); ++ bool must_rescue(oop old_obj, oop new_obj); ++ HeapWord* rescue(HeapWord* old_obj); + virtual void adjust_pointers(); + // MarkSweep support phase4 + virtual void compact(); +@@ -434,6 +437,15 @@ public: + // accordingly". + virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, + HeapWord* compact_top); ++ // (DCEVM) same as forwad, but can rescue objects. Invoked only during ++ // redefinition runs ++ HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp, ++ HeapWord* compact_top); ++ ++ HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top); ++ ++ // (tw) Compute new compact top without actually forwarding the object. ++ virtual HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); + + // Return a size with adjustments as required of the space. + virtual size_t adjust_object_size_v(size_t size) const { return size; } +@@ -467,12 +479,12 @@ protected: + + // Frequently calls obj_size(). + template +- static inline void scan_and_compact(SpaceType* space); ++ static inline void scan_and_compact(SpaceType* space, bool redefinition_run); + + // Frequently calls scanned_block_is_obj() and scanned_block_size(). + // Requires the scan_limit() function. + template +- static inline void scan_and_forward(SpaceType* space, CompactPoint* cp); ++ static inline void scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); + }; + + class GenSpaceMangler; +@@ -483,7 +495,7 @@ class ContiguousSpace: public CompactibleSpace { + friend class VMStructs; + // Allow scan_and_forward function to call (private) overrides for auxiliary functions on this class + template +- friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp); ++ friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); + + private: + // Auxiliary functions for scan_and_forward support. +diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp +index 37ae2765e71..8e3722b01b1 100644 +--- a/src/hotspot/share/gc/shared/space.inline.hpp ++++ b/src/hotspot/share/gc/shared/space.inline.hpp +@@ -133,7 +133,7 @@ public: + }; + + template +-inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { ++inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run) { + // Compute the new addresses for the live objects and store it in the mark + // Used by universe::mark_sweep_phase2() + +@@ -171,7 +171,18 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + // prefetch beyond cur_obj + Prefetch::write(cur_obj, interval); + size_t size = space->scanned_block_size(cur_obj); +- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); ++ ++ if (redefinition_run) { ++ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top); ++ if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) { ++ /* Was moved (otherwise, forward would reset mark), ++ set first_dead to here */ ++ first_dead = cur_obj; ++ } ++ } else { ++ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); ++ } ++ + cur_obj += size; + end_of_live = cur_obj; + } else { +@@ -206,6 +217,10 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + } + } + ++ if (redefinition_run) { ++ compact_top = space->forward_rescued(cp, compact_top); ++ } ++ + assert(cur_obj == scan_limit, "just checking"); + space->_end_of_live = end_of_live; + if (first_dead != NULL) { +@@ -292,7 +307,7 @@ inline void CompactibleSpace::clear_empty_region(SpaceType* space) { + } + + template +-inline void CompactibleSpace::scan_and_compact(SpaceType* space) { ++inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run) { + // Copy all live objects to their new location + // Used by MarkSweep::mark_sweep_phase4() + +@@ -316,7 +331,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { + if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // All object before _first_dead can be skipped. They should not be moved. + // A pointer to the first live object is stored at the memory location for _first_dead. +- cur_obj = *(HeapWord**)(space->_first_dead); ++ cur_obj = space->_first_dead; + } + + debug_only(HeapWord* prev_obj = NULL); +@@ -334,11 +349,35 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { + size_t size = space->obj_size(cur_obj); + HeapWord* compaction_top = cast_from_oop(oop(cur_obj)->forwardee()); + ++ if (redefinition_run && space->must_rescue(oop(cur_obj), oop(cur_obj)->forwardee())) { ++ space->rescue(cur_obj); ++ debug_only(Copy::fill_to_words(cur_obj, size, 0)); ++ cur_obj += size; ++ continue; ++ } ++ + // prefetch beyond compaction_top + Prefetch::write(compaction_top, copy_interval); + + // copy object and reinit its mark +- assert(cur_obj != compaction_top, "everything in this pass should be moving"); ++ assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL, ++ "everything in this pass should be moving"); ++ if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) { ++ Klass* new_version = oop(cur_obj)->klass()->new_version(); ++ if (new_version->update_information() == NULL) { ++ Copy::aligned_conjoint_words(cur_obj, compaction_top, size); ++ oop(compaction_top)->set_klass(new_version); ++ } else { ++ MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); ++ } ++ oop(compaction_top)->init_mark(); ++ assert(oop(compaction_top)->klass() != NULL, "should have a class"); ++ ++ debug_only(prev_obj = cur_obj); ++ cur_obj += size; ++ continue; ++ } ++ + Copy::aligned_conjoint_words(cur_obj, compaction_top, size); + oop(compaction_top)->init_mark_raw(); + assert(oop(compaction_top)->klass() != NULL, "should have a class"); +diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp +index d8e01e80d2e..ed15db841c6 100644 +--- a/src/hotspot/share/interpreter/linkResolver.cpp ++++ b/src/hotspot/share/interpreter/linkResolver.cpp +@@ -284,7 +284,7 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass, + } + + Reflection::VerifyClassAccessResults vca_result = +- Reflection::verify_class_access(ref_klass, InstanceKlass::cast(base_klass), true); ++ Reflection::verify_class_access(ref_klass->newest_version(), InstanceKlass::cast(base_klass->newest_version()), true); + if (vca_result != Reflection::ACCESS_OK) { + ResourceMark rm(THREAD); + char* msg = Reflection::verify_class_access_msg(ref_klass, +@@ -566,7 +566,7 @@ void LinkResolver::check_method_accessability(Klass* ref_klass, + // We'll check for the method name first, as that's most likely + // to be false (so we'll short-circuit out of these tests). + if (sel_method->name() == vmSymbols::clone_name() && +- sel_klass == SystemDictionary::Object_klass() && ++ sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version() && + resolved_klass->is_array_klass()) { + // We need to change "protected" to "public". + assert(flags.is_protected(), "clone not protected?"); +@@ -1011,7 +1011,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, + // or by the method (in case of an instance field). + if (is_put && fd.access_flags().is_final()) { + +- if (sel_klass != current_klass) { ++ if (sel_klass != current_klass && sel_klass != current_klass->active_version()) { + ResourceMark rm(THREAD); + stringStream ss; + ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", +@@ -1400,6 +1400,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, + assert(resolved_method->can_be_statically_bound(), "cannot override this method"); + selected_method = resolved_method; + } else { ++ assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent"); + selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); + } + } +diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +index 793ee757879..96fc139bea3 100644 +--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp ++++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +@@ -1471,6 +1471,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre + cld, + &cl_info, + ClassFileParser::INTERNAL, // internal visibility ++ false, + THREAD); + if (HAS_PENDING_EXCEPTION) { + log_pending_exception(PENDING_EXCEPTION); +diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp +index dfb9edf6721..1f3f746b2b7 100644 +--- a/src/hotspot/share/memory/universe.cpp ++++ b/src/hotspot/share/memory/universe.cpp +@@ -156,6 +156,7 @@ int Universe::_base_vtable_size = 0; + bool Universe::_bootstrapping = false; + bool Universe::_module_initialized = false; + bool Universe::_fully_initialized = false; ++bool Universe::_is_redefining_gc_run = false; // FIXME: review + + size_t Universe::_heap_capacity_at_last_gc; + size_t Universe::_heap_used_at_last_gc = 0; +@@ -177,6 +178,44 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { + #define DO_PRIMITIVE_MIRROR(m) \ + f->do_oop((oop*) &m); + ++// FIXME: This method should iterate all pointers that are not within heap objects. ++void Universe::root_oops_do(OopClosure *oopClosure) { ++ ++ class AlwaysTrueClosure: public BoolObjectClosure { ++ public: ++ void do_object(oop p) { ShouldNotReachHere(); } ++ bool do_object_b(oop p) { return true; } ++ }; ++ AlwaysTrueClosure always_true; ++ ++ Universe::oops_do(oopClosure); ++// ReferenceProcessor::oops_do(oopClosure); (tw) check why no longer there ++ JNIHandles::oops_do(oopClosure); // Global (strong) JNI handles ++ Threads::oops_do(oopClosure, NULL); ++ ObjectSynchronizer::oops_do(oopClosure); ++ // TODO: review, flat profiler was removed in j10 ++ // FlatProfiler::oops_do(oopClosure); ++ JvmtiExport::oops_do(oopClosure); ++ ++ // Now adjust pointers in remaining weak roots. (All of which should ++ // have been cleared if they pointed to non-surviving objects.) ++ // Global (weak) JNI handles ++ JNIHandles::weak_oops_do(&always_true, oopClosure); ++ ++ CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); ++ CodeCache::blobs_do(&blobClosure); ++ StringTable::oops_do(oopClosure); ++ ++ // (DCEVM) TODO: Check if this is correct? ++ //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); ++ //Management::oops_do(oopClosure); ++ //ref_processor()->weak_oops_do(&oopClosure); ++ //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); ++ ++ // SO_AllClasses ++ SystemDictionary::oops_do(oopClosure); ++} ++ + void Universe::oops_do(OopClosure* f) { + PRIMITIVE_MIRRORS_DO(DO_PRIMITIVE_MIRROR); + +diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp +index 5d528f522d4..f382a709d18 100644 +--- a/src/hotspot/share/memory/universe.hpp ++++ b/src/hotspot/share/memory/universe.hpp +@@ -53,7 +53,13 @@ class LatestMethodCache : public CHeapObj { + Klass* _klass; + int _method_idnum; + ++ static bool _is_redefining_gc_run; ++ + public: ++ ++ static bool is_redefining_gc_run() { return _is_redefining_gc_run; } ++ static void set_redefining_gc_run(bool b) { _is_redefining_gc_run = b; } ++ + LatestMethodCache() { _klass = NULL; _method_idnum = -1; } + ~LatestMethodCache() { _klass = NULL; _method_idnum = -1; } + +@@ -211,10 +217,15 @@ class Universe: AllStatic { + + static uintptr_t _verify_oop_mask; + static uintptr_t _verify_oop_bits; ++ static bool _is_redefining_gc_run; + + public: + static void calculate_verify_data(HeapWord* low_boundary, HeapWord* high_boundary) PRODUCT_RETURN; + ++ // Advanced class redefinition. FIXME: review? ++ static bool is_redefining_gc_run() { return _is_redefining_gc_run; } ++ static void set_redefining_gc_run(bool b) { _is_redefining_gc_run = b; } ++ + // Known classes in the VM + static Klass* boolArrayKlassObj() { return typeArrayKlassObj(T_BOOLEAN); } + static Klass* byteArrayKlassObj() { return typeArrayKlassObj(T_BYTE); } +@@ -344,6 +355,7 @@ class Universe: AllStatic { + + // Iteration + ++ static void root_oops_do(OopClosure *oopClosure); // FIXME: kill... + // Apply "f" to the addresses of all the direct heap pointers maintained + // as static fields of "Universe". + static void oops_do(OopClosure* f); +diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp +index d939880ed12..ac1c7d397e8 100644 +--- a/src/hotspot/share/oops/cpCache.cpp ++++ b/src/hotspot/share/oops/cpCache.cpp +@@ -450,7 +450,8 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& + if (has_appendix) { + const int appendix_index = f2_as_index(); + assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); +- assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); ++ // FIXME (DCEVM) relaxing for now... ++ //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); + resolved_references->obj_at_put(appendix_index, appendix()); + } + +@@ -640,6 +641,35 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry() { + } + return m; + } ++ ++// Enhanced RedefineClasses() API support (DCEVM): ++// Clear cached entry, let it be re-resolved ++void ConstantPoolCacheEntry::clear_entry() { ++ // Always clear for invokehandle/invokedynamic to re-resolve them ++ bool clearData = bytecode_1() == Bytecodes::_invokehandle || bytecode_1() == Bytecodes::_invokedynamic; ++ _indices = constant_pool_index(); ++ ++ if (clearData) { ++ if (!is_resolved_reference()) { ++ _f2 = 0; ++ } ++ // FIXME: (DCEVM) we want to clear flags, but parameter size is actually used ++ // after we return from the method, before entry is re-initialized. So let's ++ // keep parameter size the same. ++ // For example, it's used in TemplateInterpreterGenerator::generate_return_entry_for ++ // Also, we need to keep flag marking entry as one containing resolved_reference ++ _flags &= parameter_size_mask | (1 << is_resolved_ref_shift); ++ _f1 = NULL; ++ } ++} ++ ++// Enhanced RedefineClasses() API support (DCEVM): ++// Clear all entries ++void ConstantPoolCache::clear_entries() { ++ for (int i = 0; i < length(); i++) { ++ entry_at(i)->clear_entry(); ++ } ++} + #endif // INCLUDE_JVMTI + + void ConstantPoolCacheEntry::print(outputStream* st, int index) const { +diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp +index 38d424c9019..121a13b1dda 100644 +--- a/src/hotspot/share/oops/cpCache.hpp ++++ b/src/hotspot/share/oops/cpCache.hpp +@@ -148,13 +148,13 @@ class ConstantPoolCacheEntry { + void set_bytecode_2(Bytecodes::Code code); + void set_f1(Metadata* f1) { + Metadata* existing_f1 = _f1; // read once +- assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); ++ //assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); + _f1 = f1; + } + void release_set_f1(Metadata* f1); + void set_f2(intx f2) { + intx existing_f2 = _f2; // read once +- assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); ++ //assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); + _f2 = f2; + } + void set_f2_as_vfinal_method(Method* f2) { +@@ -180,6 +180,8 @@ class ConstantPoolCacheEntry { + tos_state_bits = 4, + tos_state_mask = right_n_bits(tos_state_bits), + tos_state_shift = BitsPerInt - tos_state_bits, // see verify_tos_state_shift below ++ // (DCEVM) We need to remember entries which has resolved reference indices as we don't want to clean them ++ is_resolved_ref_shift = 27, + // misc. option bits; can be any bit position in [16..27] + is_field_entry_shift = 26, // (F) is it a field or a method? + has_local_signature_shift = 25, // (S) does the call site have a per-site signature (sig-poly methods)? +@@ -213,6 +215,7 @@ class ConstantPoolCacheEntry { + void initialize_resolved_reference_index(int ref_index) { + assert(_f2 == 0, "set once"); // note: ref_index might be zero also + _f2 = ref_index; ++ _flags = 1 << is_resolved_ref_shift; + } + + void set_field( // sets entry to resolved field state +@@ -353,6 +356,7 @@ class ConstantPoolCacheEntry { + bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } + bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } + bool is_long() const { return flag_state() == ltos; } ++ bool is_resolved_reference() const { return (_flags & (1 << is_resolved_ref_shift)) != 0; } + bool is_double() const { return flag_state() == dtos; } + TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); + return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } +@@ -379,6 +383,10 @@ class ConstantPoolCacheEntry { + bool* trace_name_printed); + bool check_no_old_or_obsolete_entries(); + Method* get_interesting_method_entry(); ++ ++ // Enhanced RedefineClasses() API support (DCEVM): ++ // Clear cached entry, let it be re-resolved ++ void clear_entry(); + #endif // INCLUDE_JVMTI + + // Debugging & Printing +@@ -501,6 +509,10 @@ class ConstantPoolCache: public MetaspaceObj { + void adjust_method_entries(bool* trace_name_printed); + bool check_no_old_or_obsolete_entries(); + void dump_cache(); ++ ++ // Enhanced RedefineClasses() API support (DCEVM): ++ // Clear all entries ++ void clear_entries(); + #endif // INCLUDE_JVMTI + + // RedefineClasses support +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index cfd7fe74321..51bee899aa9 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -998,7 +998,8 @@ bool InstanceKlass::link_class_impl(TRAPS) { + // itable().verify(tty, true); + #endif + set_init_state(linked); +- if (JvmtiExport::should_post_class_prepare()) { ++ // (DCEVM) Must check for old version in order to prevent infinite loops. ++ if (JvmtiExport::should_post_class_prepare() && old_version() == NULL /* JVMTI deadlock otherwise */) { + Thread *thread = THREAD; + assert(thread->is_Java_thread(), "thread->is_Java_thread()"); + JvmtiExport::post_class_prepare((JavaThread *) thread, this); +@@ -1078,7 +1079,8 @@ void InstanceKlass::initialize_impl(TRAPS) { + // If we were to use wait() instead of waitInterruptibly() then + // we might end up throwing IE from link/symbol resolution sites + // that aren't expected to throw. This would wreak havoc. See 6320309. +- while (is_being_initialized() && !is_reentrant_initialization(jt)) { ++ while ((is_being_initialized() && !is_reentrant_initialization(jt)) ++ || (old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { + wait = true; + jt->set_class_to_be_initialized(this); + ol.wait_uninterruptibly(jt); +@@ -1362,6 +1364,18 @@ bool InstanceKlass::implements_interface(Klass* k) const { + return false; + } + ++bool InstanceKlass::implements_interface_any_version(Klass* k) const { ++ k = k->newest_version(); ++ if (this->newest_version() == k) return true; ++ assert(k->is_interface(), "should be an interface class"); ++ for (int i = 0; i < transitive_interfaces()->length(); i++) { ++ if (transitive_interfaces()->at(i)->newest_version() == k) { ++ return true; ++ } ++ } ++ return false; ++} ++ + bool InstanceKlass::is_same_or_direct_interface(Klass *k) const { + // Verify direct super interface + if (this == k) return true; +@@ -1628,6 +1642,23 @@ void InstanceKlass::methods_do(void f(Method* method)) { + } + } + ++/** ++ Update information contains mapping of fields from old class to the new class. ++ Info is stored on HEAP, you need to call clear_update_information to free the space. ++*/ ++void InstanceKlass::store_update_information(GrowableArray &values) { ++ int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass); ++ for (int i = 0; i < values.length(); i++) { ++ arr[i] = values.at(i); ++ } ++ set_update_information(arr); ++} ++ ++void InstanceKlass::clear_update_information() { ++ FREE_C_HEAP_ARRAY(int, update_information()); ++ set_update_information(NULL); ++} ++ + + void InstanceKlass::do_local_static_fields(FieldClosure* cl) { + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { +@@ -2310,12 +2341,30 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { + + void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { + dependencies().remove_dependent_nmethod(nm); ++ // (DCEVM) Hack as dependencies get wrong version of Klass* ++// if (this->old_version() != NULL) { ++// InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true); ++// return; ++// } + } + + void InstanceKlass::clean_dependency_context() { + dependencies().clean_unloading_dependents(); + } + ++bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) { ++ size_t idnum = (size_t)method->method_idnum(); ++ jmethodID* jmeths = methods_jmethod_ids_acquire(); ++ size_t length; // length assigned as debugging crumb ++ jmethodID id = NULL; ++ if (jmeths != NULL && // If there is a cache ++ (length = (size_t)jmeths[0]) > idnum) { // and if it is long enough, ++ jmeths[idnum+1] = newMethodID; // Set method id (may be NULL) ++ return true; ++ } ++ return false; ++} ++ + #ifndef PRODUCT + void InstanceKlass::print_dependent_nmethods(bool verbose) { + dependencies().print_dependent_nmethods(verbose); +@@ -3718,7 +3767,7 @@ void InstanceKlass::verify_on(outputStream* st) { + } + + guarantee(sib->is_klass(), "should be klass"); +- guarantee(sib->super() == super, "siblings should have same superklass"); ++ guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); + } + + // Verify local interfaces +diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp +index b1894200fc1..aa3d38d95e0 100644 +--- a/src/hotspot/share/oops/instanceKlass.hpp ++++ b/src/hotspot/share/oops/instanceKlass.hpp +@@ -137,6 +137,7 @@ class InstanceKlass: public Klass { + friend class JVMCIVMStructs; + friend class ClassFileParser; + friend class CompileReplay; ++ friend class VM_EnhancedRedefineClasses; + + public: + static const KlassID ID = InstanceKlassID; +@@ -955,6 +956,7 @@ public: + size_t *length_p, jmethodID* id_p); + void ensure_space_for_methodids(int start_offset = 0); + jmethodID jmethod_id_or_null(Method* method); ++ bool update_jmethod_id(Method* method, jmethodID newMethodID); + + // annotations support + Annotations* annotations() const { return _annotations; } +@@ -1029,6 +1031,7 @@ public: + + // subclass/subinterface checks + bool implements_interface(Klass* k) const; ++ bool implements_interface_any_version(Klass* k) const; + bool is_same_or_direct_interface(Klass* k) const; + + #ifdef ASSERT +@@ -1060,6 +1063,10 @@ public: + void do_nonstatic_fields(FieldClosure* cl); // including inherited fields + void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS); + ++ // Advanced class redefinition: FIXME: why here? ++ void store_update_information(GrowableArray &values); ++ void clear_update_information(); ++ + void methods_do(void f(Method* method)); + void array_klasses_do(void f(Klass* k)); + void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); +diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp +index 98d0ce1b753..352d8f84631 100644 +--- a/src/hotspot/share/oops/klass.cpp ++++ b/src/hotspot/share/oops/klass.cpp +@@ -200,7 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word + Klass::Klass(KlassID id) : _id(id), + _java_mirror(NULL), + _prototype_header(markWord::prototype()), +- _shared_class_path_index(-1) { ++ _shared_class_path_index(-1), ++ _new_version(NULL), ++ _old_version(NULL), ++ _is_redefining(false), ++ _is_copying_backwards(false), ++ _redefinition_flags(Klass::NoRedefinition), ++ _update_information(NULL) { + CDS_ONLY(_shared_class_flags = 0;) + CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;) + _primary_supers[0] = this; +@@ -465,6 +471,27 @@ void Klass::clean_subklass() { + } + } + ++void Klass::remove_from_sibling_list() { ++ debug_only(verify();) ++ ++ // remove ourselves to superklass' subklass list ++ InstanceKlass* super = superklass(); ++ if (super == NULL) return; // special case: class Object ++ if (super->subklass() == this) { ++ // this klass is the first subklass ++ super->set_subklass(next_sibling()); ++ } else { ++ Klass* sib = super->subklass(); ++ assert(sib != NULL, "cannot find this class in sibling list!"); ++ while (sib->next_sibling() != this) { ++ sib = sib->next_sibling(); ++ assert(sib != NULL, "cannot find this class in sibling list!"); ++ } ++ sib->set_next_sibling(next_sibling()); ++ } ++ debug_only(verify();) ++} ++ + void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses) { + if (!ClassUnloading || !unloading_occurred) { + return; +diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp +index c90477cca96..e06c068cdd7 100644 +--- a/src/hotspot/share/oops/klass.hpp ++++ b/src/hotspot/share/oops/klass.hpp +@@ -165,6 +165,18 @@ class Klass : public Metadata { + markWord _prototype_header; // Used when biased locking is both enabled and disabled for this type + jint _biased_lock_revocation_count; + ++ // Advanced class redefinition ++ ++ // Old version (used in advanced class redefinition) ++ Klass* _old_version; ++ // New version (used in advanced class redefinition) ++ Klass* _new_version; ++ ++ int _redefinition_flags; // Level of class redefinition ++ bool _is_redefining; ++ int* _update_information; ++ bool _is_copying_backwards; // Does the class need to copy fields backwards? => possibly overwrite itself? ++ + private: + // This is an index into FileMapHeader::_shared_path_table[], to + // associate this class with the JAR file where it's loaded from during +@@ -291,6 +303,7 @@ protected: + + InstanceKlass* superklass() const; + void append_to_sibling_list(); // add newly created receiver to superklass' subklass list ++ void remove_from_sibling_list(); // enhanced class redefinition + + void set_next_link(Klass* k) { _next_link = k; } + Klass* next_link() const { return _next_link; } // The next klass defined by the class loader. +@@ -334,11 +347,45 @@ protected: + virtual ModuleEntry* module() const = 0; + virtual PackageEntry* package() const = 0; + ++ // Advanced class redefinition ++ Klass* old_version() const { return _old_version; } ++ void set_old_version(Klass* klass) { assert(_old_version == NULL || klass == NULL, "Old version can only be set once!"); _old_version = klass; } ++ Klass* new_version() const { return _new_version; } ++ void set_new_version(Klass* klass) { assert(_new_version == NULL || klass == NULL, "New version can only be set once!"); _new_version = klass; } ++ bool is_redefining() const { return _is_redefining; } ++ void set_redefining(bool b) { _is_redefining = b; } ++ int redefinition_flags() const { return _redefinition_flags; } ++ bool check_redefinition_flag(int flags) const { return (_redefinition_flags & flags) != 0; } ++ void clear_redefinition_flag(int flag) { _redefinition_flags &= ~flag; } ++ void set_redefinition_flag(int flag) { _redefinition_flags |= flag; } ++ void set_redefinition_flags(int flags) { _redefinition_flags = flags; } ++ ++ const Klass* newest_version() const { return _new_version == NULL ? this : _new_version->newest_version(); } ++ Klass* newest_version() { return _new_version == NULL ? this : _new_version->newest_version(); } ++ ++ const Klass* active_version() const { return _new_version == NULL || _new_version->is_redefining() ? this : _new_version->active_version(); } ++ Klass* active_version() { return _new_version == NULL || _new_version->is_redefining() ? this : _new_version->active_version(); } ++ ++ // update information ++ int *update_information() const { return _update_information; } ++ void set_update_information(int *info) { _update_information = info; } ++ bool is_copying_backwards() const { return _is_copying_backwards; } ++ void set_copying_backwards(bool b) { _is_copying_backwards = b; } ++ + protected: // internal accessors + void set_subklass(Klass* s); + void set_next_sibling(Klass* s); + + public: ++ enum RedefinitionFlags { ++ NoRedefinition, // This class is not redefined at all! ++ ModifyClass = 1, // There are changes to the class meta data. ++ ModifyClassSize = ModifyClass << 1, // The size of the class meta data changes. ++ ModifyInstances = ModifyClassSize << 1, // There are change to the instance format. ++ ModifyInstanceSize = ModifyInstances << 1, // The size of instances changes. ++ RemoveSuperType = ModifyInstanceSize << 1, // A super type of this class is removed. ++ MarkedAsAffected = RemoveSuperType << 1 // This class has been marked as an affected class. ++ }; + + // Compiler support + static ByteSize super_offset() { return in_ByteSize(offset_of(Klass, _super)); } +diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp +index 3d8ade5496c..516f2bb8f2f 100644 +--- a/src/hotspot/share/oops/method.cpp ++++ b/src/hotspot/share/oops/method.cpp +@@ -1540,6 +1540,8 @@ methodHandle Method::clone_with_new_data(const methodHandle& m, u_char* new_code + + // Reset correct method/const method, method size, and parameter info + newm->set_constMethod(newcm); ++ newm->set_new_version(newm->new_version()); ++ newm->set_old_version(newm->old_version()); + newm->constMethod()->set_code_size(new_code_length); + newm->constMethod()->set_constMethod_size(new_const_method_size); + assert(newm->code_size() == new_code_length, "check"); +@@ -2204,6 +2206,10 @@ void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) { + + // Add a method id to the jmethod_ids + jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) { ++ // FIXME: (DCEVM) ??? ++ if (m != m->newest_version()) { ++ m = m->newest_version(); ++ } + ClassLoaderData* cld = loader_data; + + if (!SafepointSynchronize::is_at_safepoint()) { +diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp +index 5b912ca6f5d..83ed2d9c3c1 100644 +--- a/src/hotspot/share/oops/method.hpp ++++ b/src/hotspot/share/oops/method.hpp +@@ -78,6 +78,9 @@ class Method : public Metadata { + MethodCounters* _method_counters; + AccessFlags _access_flags; // Access flags + int _vtable_index; // vtable index of this method (see VtableIndexFlag) ++ // (DCEVM) Newer version of method available? ++ Method* _new_version; ++ Method* _old_version; + // note: can have vtables with >2**16 elements (because of inheritance) + u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) + +@@ -154,6 +157,23 @@ class Method : public Metadata { + int name_index() const { return constMethod()->name_index(); } + void set_name_index(int index) { constMethod()->set_name_index(index); } + ++ Method* new_version() const { return _new_version; } ++ void set_new_version(Method* m) { _new_version = m; } ++ Method* newest_version() { return (_new_version == NULL) ? this : _new_version->newest_version(); } ++ ++ Method* old_version() const { return _old_version; } ++ void set_old_version(Method* m) { ++ /*if (m == NULL) { ++ _old_version = NULL; ++ return; ++ }*/ ++ ++ assert(_old_version == NULL, "may only be set once"); ++ assert(this->code_size() == m->code_size(), "must have same code length"); ++ _old_version = m; ++ } ++ const Method* oldest_version() const { return (_old_version == NULL) ? this : _old_version->oldest_version(); } ++ + // signature + Symbol* signature() const { return constants()->symbol_at(signature_index()); } + int signature_index() const { return constMethod()->signature_index(); } +diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp +index 3c91e8e2ead..51243524106 100644 +--- a/src/hotspot/share/prims/jni.cpp ++++ b/src/hotspot/share/prims/jni.cpp +@@ -338,6 +338,7 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR + class_loader, + Handle(), + &st, ++ NULL, + CHECK_NULL); + + if (log_is_enabled(Debug, class, resolve) && k != NULL) { +diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp +index 2d866dee6dd..333b65ccfc1 100644 +--- a/src/hotspot/share/prims/jvm.cpp ++++ b/src/hotspot/share/prims/jvm.cpp +@@ -963,6 +963,7 @@ static jclass jvm_define_class_common(JNIEnv *env, const char *name, + class_loader, + protection_domain, + &st, ++ NULL, + CHECK_NULL); + + if (log_is_enabled(Debug, class, resolve) && k != NULL) { +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +new file mode 100644 +index 00000000000..83c0952de37 +--- /dev/null ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -0,0 +1,2255 @@ ++/* ++ * Copyright (c) 2003, 2016, 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 "aot/aotLoader.hpp" ++#include "classfile/classFileStream.hpp" ++#include "classfile/metadataOnStackMark.hpp" ++#include "classfile/systemDictionary.hpp" ++#include "classfile/verifier.hpp" ++#include "interpreter/oopMapCache.hpp" ++#include "interpreter/rewriter.hpp" ++#include "logging/logStream.hpp" ++#include "memory/metadataFactory.hpp" ++#include "memory/metaspaceShared.hpp" ++#include "memory/resourceArea.hpp" ++#include "memory/iterator.inline.hpp" ++#include "gc/serial/markSweep.hpp" // FIXME: other GC? ++#include "oops/fieldStreams.hpp" ++#include "oops/klassVtable.hpp" ++#include "oops/oop.inline.hpp" ++#include "oops/constantPool.inline.hpp" ++#include "prims/jvmtiImpl.hpp" ++#include "prims/jvmtiClassFileReconstituter.hpp" ++#include "prims/jvmtiEnhancedRedefineClasses.hpp" ++#include "prims/methodComparator.hpp" ++#include "prims/resolvedMethodTable.hpp" ++#include "runtime/deoptimization.hpp" ++#include "runtime/jniHandles.inline.hpp" ++#include "runtime/relocator.hpp" ++#include "utilities/bitMap.inline.hpp" ++#include "prims/jvmtiThreadState.inline.hpp" ++#include "utilities/events.hpp" ++#include "oops/constantPool.inline.hpp" ++ ++Array* VM_EnhancedRedefineClasses::_old_methods = NULL; ++Array* VM_EnhancedRedefineClasses::_new_methods = NULL; ++Method** VM_EnhancedRedefineClasses::_matching_old_methods = NULL; ++Method** VM_EnhancedRedefineClasses::_matching_new_methods = NULL; ++Method** VM_EnhancedRedefineClasses::_deleted_methods = NULL; ++Method** VM_EnhancedRedefineClasses::_added_methods = NULL; ++int VM_EnhancedRedefineClasses::_matching_methods_length = 0; ++int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; ++int VM_EnhancedRedefineClasses::_added_methods_length = 0; ++Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; ++ ++/** ++ * Create new instance of enhanced class redefiner. ++ * ++ * This class implements VM_GC_Operation - the usual usage should be: ++ * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++ * VMThread::execute(&op); ++ * Which ++ * ++ * @param class_count size of class_defs ++ * @param class_defs class definition - either new class or redefined class ++ * note that this is not the final array of classes to be redefined ++ * we need to scan for all affected classes (e.g. subclasses) and ++ * caculcate redefinition for them as well. ++ * @param class_load_kind always jvmti_class_load_kind_redefine ++ */ ++VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : ++ VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { ++ _affected_klasses = NULL; ++ _class_count = class_count; ++ _class_defs = class_defs; ++ _class_load_kind = class_load_kind; ++ _res = JVMTI_ERROR_NONE; ++ _any_class_has_resolved_methods = false; ++} ++ ++static inline InstanceKlass* get_ik(jclass def) { ++ oop mirror = JNIHandles::resolve_non_null(def); ++ return InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); ++} ++ ++/** ++ * Start the redefinition: ++ * - Load new class definitions - @see load_new_class_versions ++ * - Start mark&sweep GC. ++ * @return true if success, otherwise all chnages are rollbacked. ++ */ ++bool VM_EnhancedRedefineClasses::doit_prologue() { ++ ++ if (_class_count == 0) { ++ _res = JVMTI_ERROR_NONE; ++ return false; ++ } ++ if (_class_defs == NULL) { ++ _res = JVMTI_ERROR_NULL_POINTER; ++ return false; ++ } ++ for (int i = 0; i < _class_count; i++) { ++ if (_class_defs[i].klass == NULL) { ++ _res = JVMTI_ERROR_INVALID_CLASS; ++ return false; ++ } ++ if (_class_defs[i].class_byte_count == 0) { ++ _res = JVMTI_ERROR_INVALID_CLASS_FORMAT; ++ return false; ++ } ++ if (_class_defs[i].class_bytes == NULL) { ++ _res = JVMTI_ERROR_NULL_POINTER; ++ return false; ++ } ++ ++ // classes for primitives and arrays and vm anonymous classes cannot be redefined ++ // check here so following code can assume these classes are InstanceKlass ++ oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); ++ if (!is_modifiable_class(mirror)) { ++ _res = JVMTI_ERROR_UNMODIFIABLE_CLASS; ++ return false; ++ } ++ } ++ ++ // Start timer after all the sanity checks; not quite accurate, but ++ // better than adding a bunch of stop() calls. ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_vm_op_prologue.start(); ++ } ++ ++ // We first load new class versions in the prologue, because somewhere down the ++ // call chain it is required that the current thread is a Java thread. ++ _res = load_new_class_versions(Thread::current()); ++ ++ // prepare GC, lock heap ++ if (_res == JVMTI_ERROR_NONE && !VM_GC_Operation::doit_prologue()) { ++ _res = JVMTI_ERROR_INTERNAL; ++ } ++ ++ if (_res != JVMTI_ERROR_NONE) { ++ rollback(); ++ // TODO free any successfully created classes ++ /*for (int i = 0; i < _class_count; i++) { ++ if (_new_classes[i] != NULL) { ++ ClassLoaderData* cld = _new_classes[i]->class_loader_data(); ++ // Free the memory for this class at class unloading time. Not before ++ // because CMS might think this is still live. ++ cld->add_to_deallocate_list(InstanceKlass::cast(_new_classes[i])); ++ } ++ }*/ ++ delete _new_classes; ++ _new_classes = NULL; ++ delete _affected_klasses; ++ _affected_klasses = NULL; ++ ++ _timer_vm_op_prologue.stop(); ++ return false; ++ } ++ ++ _timer_vm_op_prologue.stop(); ++ return true; ++} ++ ++/** ++ * Closer for static fields - copy value from old class to the new class. ++ */ ++class FieldCopier : public FieldClosure { ++ public: ++ void do_field(fieldDescriptor* fd) { ++ InstanceKlass* cur = InstanceKlass::cast(fd->field_holder()); ++ oop cur_oop = cur->java_mirror(); ++ ++ InstanceKlass* old = InstanceKlass::cast(cur->old_version()); ++ oop old_oop = old->java_mirror(); ++ ++ fieldDescriptor result; ++ bool found = old->find_local_field(fd->name(), fd->signature(), &result); ++ if (found && result.is_static()) { ++ log_trace(redefine, class, obsolete, metadata)("Copying static field value for field %s old_offset=%d new_offset=%d", ++ fd->name()->as_C_string(), result.offset(), fd->offset()); ++ memcpy(cur_oop->obj_field_addr_raw(fd->offset()), ++ old_oop->obj_field_addr_raw(result.offset()), ++ type2aelembytes(fd->field_type())); ++ ++ // Static fields may have references to java.lang.Class ++ if (fd->field_type() == T_OBJECT) { ++ oop oop = cur_oop->obj_field(fd->offset()); ++ if (oop != NULL && oop->is_instance() && InstanceKlass::cast(oop->klass())->is_mirror_instance_klass()) { ++ Klass* klass = java_lang_Class::as_Klass(oop); ++ if (klass != NULL && klass->is_instance_klass()) { ++ assert(oop == InstanceKlass::cast(klass)->java_mirror(), "just checking"); ++ if (klass->new_version() != NULL) { ++ oop = InstanceKlass::cast(klass->new_version())->java_mirror(); ++ cur_oop->obj_field_put(fd->offset(), oop); ++ } ++ } ++ } ++ } ++ } ++ } ++}; ++ ++ ++// TODO: review... ++void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { ++ if (!nm->on_scavenge_root_list()) { ++ CodeCache::add_scavenge_root_nmethod(nm); ++ } ++} ++ ++// TODO comment ++struct StoreBarrier { ++ // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store ++ template static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); } ++}; ++ ++ ++// TODO comment ++struct StoreNoBarrier { ++ template static void oop_store(T* p, oop v) { RawAccess::oop_store(p, v); } ++}; ++ ++/** ++ Closure to scan all heap objects and update method handles ++*/ ++template ++class ChangePointersOopClosure : public BasicOopIterateClosure { ++ // import java_lang_invoke_MemberName.* ++ enum { ++ REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT, ++ REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK, ++ }; ++ ++ ++ bool update_member_name(oop obj) { ++ int flags = java_lang_invoke_MemberName::flags(obj); ++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; ++ if (MethodHandles::ref_kind_is_method(ref_kind)) { ++ Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj); ++ if (m != NULL && m->method_holder()->new_version() != NULL) { ++ // Let's try to re-resolve method ++ InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version()); ++ Method* new_method = newest->find_method(m->name(), m->signature()); ++ ++ if (new_method != NULL) { ++ // Note: we might set NULL at this point, which should force AbstractMethodError at runtime ++ Thread *thread = Thread::current(); ++ CallInfo info(new_method, newest, thread); ++ Handle objHandle(thread, obj); // TODO : review thread ++ MethodHandles::init_method_MemberName(objHandle, info); ++ } else { ++ java_lang_invoke_MemberName::set_method(obj, NULL); ++ } ++ } ++ } else if (MethodHandles::ref_kind_is_field(ref_kind)) { ++ Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj); ++ if (k == NULL) { ++ return false; // Was cleared before, this MemberName is invalid. ++ } ++ ++ if (k != NULL && k->new_version() != NULL) { ++ // Let's try to re-resolve field ++ fieldDescriptor fd; ++ int offset = java_lang_invoke_MemberName::vmindex(obj); ++ bool is_static = MethodHandles::ref_kind_is_static(ref_kind); ++ InstanceKlass* ik = InstanceKlass::cast(k); ++ if (ik->find_local_field_from_offset(offset, is_static, &fd)) { ++ InstanceKlass* newest = InstanceKlass::cast(k->newest_version()); ++ fieldDescriptor fd_new; ++ if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) { ++ Handle objHandle(Thread::current(), obj); // TODO : review thread ++ MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind)); ++ } else { ++ // Matching field is not found in new version, not much we can do here. ++ // JVM will crash once faulty MH is invoked. ++ // However, to avoid that all DMH's using this faulty MH are cleared (set to NULL) ++ // Eventually, we probably want to replace them with something more meaningful, ++ // like instance throwing NoSuchFieldError or DMH that will resort to dynamic ++ // field resolution (with possibility of type conversion) ++ java_lang_invoke_MemberName::set_method(obj, NULL); ++ java_lang_invoke_MemberName::set_vmindex(obj, 0); ++ return false; ++ } ++ } ++ } ++ } ++ return true; ++ } ++ ++ bool update_direct_method_handle(oop obj) { ++ // Always update member name first. ++ oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj); ++ if (!update_member_name(mem_name)) { ++ return false; ++ } ++ ++ // Here we rely on DirectMethodHandle implementation. ++ // The current implementation caches field offset in $StaticAccessor/$Accessor ++ int flags = java_lang_invoke_MemberName::flags(mem_name); ++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; ++ if (MethodHandles::ref_kind_is_field(ref_kind)) { ++ // Note: we don't care about staticBase field (which is java.lang.Class) ++ // It should be processed during normal object update. ++ // Update offset in StaticAccessor ++ int offset = java_lang_invoke_MemberName::vmindex(mem_name); ++ if (offset != 0) { // index of 0 means that field no longer exist ++ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) { ++ java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(obj, offset); ++ } else if (java_lang_invoke_DirectMethodHandle_Accessor::is_instance(obj)) { ++ java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(obj, offset); ++ } ++ } ++ } ++ return true; ++ } ++ ++ // Forward pointers to InstanceKlass and mirror class to new versions ++ template ++ inline void do_oop_work(T* p) { ++ oop obj = RawAccess<>::oop_load(p); ++ if (obj == NULL) { ++ return; ++ } ++ if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { ++ Klass* klass = java_lang_Class::as_Klass(obj); ++ if (klass != NULL && klass->is_instance_klass()) { ++ assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking"); ++ if (klass->new_version() != NULL) { ++ obj = InstanceKlass::cast(klass->new_version())->java_mirror(); ++ S::oop_store(p, obj); ++ } ++ } ++ } ++ ++ // JSR 292 support, uptade java.lang.invoke.MemberName instances ++ if (java_lang_invoke_MemberName::is_instance(obj)) { ++ update_member_name(obj); ++ } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) { ++ if (!update_direct_method_handle(obj)) { ++ // DMH is no longer valid, replace it with null reference. ++ // See note above. We probably want to replace this with something more meaningful. ++ S::oop_store(p, NULL); ++ } ++ } ++ } ++ ++ virtual void do_oop(oop* o) { ++ do_oop_work(o); ++ } ++ ++ virtual void do_oop(narrowOop* o) { ++ do_oop_work(o); ++ } ++}; ++ ++/** ++ * Closure to scan all objects on heap for objects of changed classes ++ * - if the fields are compatible, only update class definition reference ++ * - otherwise if the new object size is smaller then old size, reshufle ++ * the fields and fill the gap with "dead_space" ++ * - otherwise set the _needs_instance_update flag, we need to do full GC ++ * and reshuffle object positions durring mark&sweep ++ */ ++class ChangePointersObjectClosure : public ObjectClosure { ++ private: ++ ++ OopIterateClosure *_closure; ++ bool _needs_instance_update; ++ oop _tmp_obj; ++ int _tmp_obj_size; ++ ++public: ++ ChangePointersObjectClosure(OopIterateClosure *closure) : _closure(closure), _needs_instance_update(false), _tmp_obj(NULL), _tmp_obj_size(0) {} ++ ++ bool needs_instance_update() { ++ return _needs_instance_update; ++ } ++ ++ void copy_to_tmp(oop o) { ++ int size = o->size(); ++ if (_tmp_obj_size < size) { ++ _tmp_obj_size = size; ++ _tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize); ++ } ++ Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size); ++ } ++ ++ virtual void do_object(oop obj) { ++ if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { ++ // static fields may have references to old java.lang.Class instances, update them ++ // at the same time, we don't want to update other oops in the java.lang.Class ++ // Causes SIGSEGV? ++ //instanceMirrorKlass::oop_fields_iterate(obj, _closure); ++ } else { ++ obj->oop_iterate(_closure); ++ } ++ ++ if (obj->klass()->new_version() != NULL) { ++ Klass* new_klass = obj->klass()->new_version(); ++ ++ if (new_klass->update_information() != NULL) { ++ int size_diff = obj->size() - obj->size_given_klass(new_klass); ++ ++ // Either new size is bigger or gap is to small to be filled ++ if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) { ++ // We need an instance update => set back to old klass ++ _needs_instance_update = true; ++ } else { ++ oop src = obj; ++ if (new_klass->is_copying_backwards()) { ++ copy_to_tmp(obj); ++ src = _tmp_obj; ++ } ++ src->set_klass(obj->klass()->new_version()); ++ // FIXME: instance updates... ++ //guarantee(false, "instance updates!"); ++ MarkSweep::update_fields(obj, src, new_klass->update_information()); ++ ++ if (size_diff > 0) { ++ HeapWord* dead_space = ((HeapWord *)obj) + obj->size(); ++ CollectedHeap::fill_with_object(dead_space, size_diff); ++ } ++ } ++ } else { ++ obj->set_klass(obj->klass()->new_version()); ++ } ++ } ++ } ++}; ++ ++ ++/** ++ Main transformation method - runs in VM thread. ++ ++ - UseSharedSpaces - TODO what does it mean? ++ - for each sratch class call redefine_single_class ++ - clear code cache (flush_dependent_code) ++ - iterate the heap and update object defintions, check it old/new class fields ++ are compatible. If new class size is smaller then old, it can be solved directly here. ++ - iterate the heap and update method handles to new version ++ - Swap marks to have same hashcodes ++ - copy static fields ++ - notify JVM of the modification ++*/ ++void VM_EnhancedRedefineClasses::doit() { ++ Thread *thread = Thread::current(); ++ ++ if (UseSharedSpaces) { ++ // Sharing is enabled so we remap the shared readonly space to ++ // shared readwrite, private just in case we need to redefine ++ // a shared class. We do the remap during the doit() phase of ++ // the safepoint to be safer. ++ if (!MetaspaceShared::remap_shared_readonly_as_readwrite()) { ++ log_info(redefine, class, load)("failed to remap shared readonly space to readwrite, private"); ++ _res = JVMTI_ERROR_INTERNAL; ++ return; ++ } ++ } ++ ++ // Mark methods seen on stack and everywhere else so old methods are not ++ // cleaned up if they're on the stack. ++ MetadataOnStackMark md_on_stack(true); ++ HandleMark hm(thread); // make sure any handles created are deleted ++ // before the stack walk again. ++ ++ for (int i = 0; i < _new_classes->length(); i++) { ++ redefine_single_class(_new_classes->at(i), thread); ++ } ++ ++ // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) ++ flush_dependent_code(NULL, thread); ++ ++ // JSR-292 support ++ if (_any_class_has_resolved_methods) { ++ bool trace_name_printed = false; ++ ResolvedMethodTable::adjust_method_entries(&trace_name_printed); ++ } ++ ++ ChangePointersOopClosure oopClosureNoBarrier; ++ ChangePointersOopClosure oopClosure; ++ ChangePointersObjectClosure objectClosure(&oopClosure); ++ ++ log_trace(redefine, class, obsolete, metadata)("Before updating instances"); ++ { ++ // Since we may update oops inside nmethod's code blob to point to java.lang.Class in new generation, we need to ++ // make sure such references are properly recognized by GC. For that, If ScavengeRootsInCode is true, we need to ++ // mark such nmethod's as "scavengable". ++ // For now, mark all nmethod's as scavengable that are not scavengable already ++ if (ScavengeRootsInCode) { ++ CodeCache::nmethods_do(mark_as_scavengable); ++ } ++ ++ Universe::heap()->ensure_parsability(false); ++ Universe::heap()->object_iterate(&objectClosure); ++ Universe::root_oops_do(&oopClosureNoBarrier); ++ } ++ log_trace(redefine, class, obsolete, metadata)("After updating instances"); ++ ++ for (int i = 0; i < _new_classes->length(); i++) { ++ InstanceKlass* cur = InstanceKlass::cast(_new_classes->at(i)); ++ InstanceKlass* old = InstanceKlass::cast(cur->old_version()); ++ ++ // Swap marks to have same hashcodes ++ markOop cur_mark = cur->prototype_header(); ++ markOop old_mark = old->prototype_header(); ++ cur->set_prototype_header(old_mark); ++ old->set_prototype_header(cur_mark); ++ ++ //swap_marks(cur, old); ++ cur_mark = cur->java_mirror()->mark(); ++ old_mark = old->java_mirror()->mark(); ++ cur->java_mirror()->set_mark(old_mark); ++ old->java_mirror()->set_mark(cur_mark); ++ ++ ++ // Revert pool holder for old version of klass (it was updated by one of ours closure!) ++ old->constants()->set_pool_holder(old); ++ ++ Klass* array_klasses = old->array_klasses(); ++ if (array_klasses != NULL) { ++ assert(cur->array_klasses() == NULL, "just checking"); ++ ++ // Transfer the array classes, otherwise we might get cast exceptions when casting array types. ++ // Also, set array klasses element klass. ++ cur->set_array_klasses(array_klasses); ++ ObjArrayKlass::cast(array_klasses)->set_element_klass(cur); ++ java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses); ++ java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror()); ++ } ++ ++ // Initialize the new class! Special static initialization that does not execute the ++ // static constructor but copies static field values from the old class if name ++ // and signature of a static field match. ++ FieldCopier copier; ++ cur->do_local_static_fields(&copier); // TODO (tw): What about internal static fields?? ++ //java_lang_Class::set_klass(old->java_mirror(), cur); // FIXME-isd (from JDK8): is that correct? ++ //FIXME-isd (from JDK8): do we need this: ??? old->set_java_mirror(cur->java_mirror()); ++ ++ // Transfer init state ++ InstanceKlass::ClassState state = old->init_state(); ++ if (state > InstanceKlass::linked) { ++ cur->set_init_state(state); ++ } ++ } ++ ++// if (objectClosure.needs_instance_update()) { ++ // Do a full garbage collection to update the instance sizes accordingly ++ Universe::set_redefining_gc_run(true); ++ notify_gc_begin(true); ++ Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); ++ notify_gc_end(); ++ Universe::set_redefining_gc_run(false); ++// } ++ ++ // Unmark Klass*s as "redefining" ++ for (int i = 0; i < _new_classes->length(); i++) { ++ InstanceKlass* cur = _new_classes->at(i); ++ cur->set_redefining(false); ++ cur->clear_update_information(); ++ } ++ ++ // TODO: explain... ++ SystemDictionary::update_constraints_after_redefinition(); ++ ++ // TODO: explain... ++ ciObjectFactory::resort_shared_ci_metadata(); ++ ++ // FIXME - check if it was in JDK8. Copied from standard JDK9 hotswap. ++ //MethodDataCleaner clean_weak_method_links; ++ //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); ++ ++ // Disable any dependent concurrent compilations ++ SystemDictionary::notice_modification(); ++ ++ // Set flag indicating that some invariants are no longer true. ++ // See jvmtiExport.hpp for detailed explanation. ++ JvmtiExport::set_has_redefined_a_class(); ++ ++ // check_class() is optionally called for product bits, but is ++ // always called for non-product bits. ++#ifdef PRODUCT ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++#endif ++ log_trace(redefine, class, obsolete, metadata)("calling check_class"); ++ CheckClass check_class(thread); ++ ClassLoaderDataGraph::classes_do(&check_class); ++#ifdef PRODUCT ++ } ++#endif ++} ++ ++/** ++ * Cleanup - runs in JVM thread ++ * - free used memory ++ * - end GC ++ */ ++void VM_EnhancedRedefineClasses::doit_epilogue() { ++ VM_GC_Operation::doit_epilogue(); ++ ++ if (_new_classes != NULL) { ++ delete _new_classes; ++ } ++ _new_classes = NULL; ++ if (_affected_klasses != NULL) { ++ delete _affected_klasses; ++ } ++ _affected_klasses = NULL; ++ ++ // Reset the_class_oop to null for error printing. ++ _the_class_oop = NULL; ++ ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ // Used to have separate timers for "doit" and "all", but the timer ++ // overhead skewed the measurements. ++ jlong doit_time = _timer_rsc_phase1.milliseconds() + ++ _timer_rsc_phase2.milliseconds(); ++ jlong all_time = _timer_vm_op_prologue.milliseconds() + doit_time; ++ ++ log_info(redefine, class, timer) ++ ("vm_op: all=" JLONG_FORMAT " prologue=" JLONG_FORMAT " doit=" JLONG_FORMAT, ++ all_time, _timer_vm_op_prologue.milliseconds(), doit_time); ++ log_info(redefine, class, timer) ++ ("redefine_single_class: phase1=" JLONG_FORMAT " phase2=" JLONG_FORMAT, ++ _timer_rsc_phase1.milliseconds(), _timer_rsc_phase2.milliseconds()); ++ } ++} ++ ++/** ++ * Exclude java primitives and arrays from redefinition ++ * @param klass_mirror pointer to the klass ++ * @return true if is modifiable ++ */ ++bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { ++ // classes for primitives cannot be redefined ++ if (java_lang_Class::is_primitive(klass_mirror)) { ++ return false; ++ } ++ Klass* k = java_lang_Class::as_Klass(klass_mirror); ++ // classes for arrays cannot be redefined ++ if (k == NULL || !k->is_instance_klass()) { ++ return false; ++ } ++ ++ // Cannot redefine or retransform an anonymous class. ++ if (InstanceKlass::cast(k)->is_anonymous()) { ++ return false; ++ } ++ return true; ++} ++ ++/** ++ Load and link new classes (either redefined or affected by redefinition - subclass, ...) ++ ++ - find sorted affected classes ++ - resolve new class ++ - calculate redefine flags (field change, method change, supertype change, ...) ++ - calculate modified fields and mapping to old fields ++ - link new classes ++ ++ The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. ++*/ ++jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { ++ ++ _affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); ++ _new_classes = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); ++ ++ ResourceMark rm(THREAD); ++ ++ // Retrieve an array of all classes that need to be redefined into _affected_klasses ++ jvmtiError err = find_sorted_affected_classes(THREAD); ++ if (err != JVMTI_ERROR_NONE) { ++ return err; ++ } ++ ++ // thread local state - used to transfer class_being_redefined object to SystemDictonery::resolve_from_stream ++ JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current()); ++ // state can only be NULL if the current thread is exiting which ++ // should not happen since we're trying to do a RedefineClasses ++ guarantee(state != NULL, "exiting thread calling load_new_class_versions"); ++ ++ _max_redefinition_flags = Klass::NoRedefinition; ++ ++ for (int i = 0; i < _affected_klasses->length(); i++) { ++ // Create HandleMark so that any handles created while loading new class ++ // versions are deleted. Constant pools are deallocated while merging ++ // constant pools ++ HandleMark hm(THREAD); ++ InstanceKlass* the_class = InstanceKlass::cast(_affected_klasses->at(i)); ++ Symbol* the_class_sym = the_class->name(); ++ ++ // Ensure class is linked before redefine ++ if (!the_class->is_linked()) { ++ the_class->link_class(THREAD); ++ if (HAS_PENDING_EXCEPTION) { ++ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); ++ log_info(redefine, class, load, exceptions)("link_class exception: '%s'", ex_name->as_C_string()); ++ CLEAR_PENDING_EXCEPTION; ++ if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { ++ return JVMTI_ERROR_OUT_OF_MEMORY; ++ } else { ++ return JVMTI_ERROR_INTERNAL; ++ } ++ } ++ } ++ ++ log_debug(redefine, class, load) ++ ("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)", ++ the_class->external_name(), _class_load_kind, os::available_memory() >> 10); ++ ++ // class bytes... ++ const unsigned char* class_bytes; ++ jint class_byte_count; ++ jvmtiError error; ++ jboolean not_changed; ++ if ((error = find_class_bytes(the_class, &class_bytes, &class_byte_count, ¬_changed)) != JVMTI_ERROR_NONE) { ++ log_info(redefine, class, load, exceptions)("error finding class bytes: %d", (int) error); ++ return error; ++ } ++ assert(class_bytes != NULL && class_byte_count != 0, "class bytes should be defined at this point!"); ++ ++ ClassFileStream st((u1*)class_bytes, ++ class_byte_count, ++ "__VM_EnhancedRedefineClasses__", ++ ClassFileStream::verify); ++ ++ // Parse the stream. ++ Handle the_class_loader(THREAD, the_class->class_loader()); ++ Handle protection_domain(THREAD, the_class->protection_domain()); ++ // Set redefined class handle in JvmtiThreadState class. ++ // This redefined class is sent to agent event handler for class file ++ // load hook event. ++ state->set_class_being_redefined(the_class, _class_load_kind); ++ ++ InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym, ++ the_class_loader, ++ protection_domain, ++ &st, ++ the_class, ++ THREAD); ++ // Clear class_being_redefined just to be sure. ++ state->clear_class_being_redefined(); ++ ++ if (HAS_PENDING_EXCEPTION) { ++ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); ++ log_info(redefine, class, load, exceptions)("parse_stream exception: '%s'", ex_name->as_C_string()); ++ CLEAR_PENDING_EXCEPTION; ++ ++ if (ex_name == vmSymbols::java_lang_UnsupportedClassVersionError()) { ++ return JVMTI_ERROR_UNSUPPORTED_VERSION; ++ } else if (ex_name == vmSymbols::java_lang_ClassFormatError()) { ++ return JVMTI_ERROR_INVALID_CLASS_FORMAT; ++ } else if (ex_name == vmSymbols::java_lang_ClassCircularityError()) { ++ return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; ++ } else if (ex_name == vmSymbols::java_lang_NoClassDefFoundError()) { ++ // The message will be "XXX (wrong name: YYY)" ++ return JVMTI_ERROR_NAMES_DONT_MATCH; ++ } else if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { ++ return JVMTI_ERROR_OUT_OF_MEMORY; ++ } else { // Just in case more exceptions can be thrown.. ++ return JVMTI_ERROR_FAILS_VERIFICATION; ++ } ++ } ++ ++ InstanceKlass* new_class = k; ++ the_class->set_new_version(new_class); ++ _new_classes->append(new_class); ++ ++ int redefinition_flags = Klass::NoRedefinition; ++ if (not_changed) { ++ redefinition_flags = Klass::NoRedefinition; ++ } else { ++ redefinition_flags = calculate_redefinition_flags(new_class); ++ if (redefinition_flags >= Klass::RemoveSuperType) { ++ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; ++ } ++ } ++ ++ if (new_class->super() != NULL) { ++ redefinition_flags = redefinition_flags | new_class->super()->redefinition_flags(); ++ } ++ ++ for (int j = 0; j < new_class->local_interfaces()->length(); j++) { ++ redefinition_flags = redefinition_flags | (new_class->local_interfaces()->at(j))->redefinition_flags(); ++ } ++ ++ new_class->set_redefinition_flags(redefinition_flags); ++ ++ _max_redefinition_flags = _max_redefinition_flags | redefinition_flags; ++ ++ if ((redefinition_flags & Klass::ModifyInstances) != 0) { ++ calculate_instance_update_information(_new_classes->at(i)); ++ } else { ++ // Fields were not changed, transfer special flags only ++ assert(new_class->layout_helper() >> 1 == new_class->old_version()->layout_helper() >> 1, "must be equal"); ++ assert(new_class->fields()->length() == InstanceKlass::cast(new_class->old_version())->fields()->length(), "must be equal"); ++ ++ JavaFieldStream old_fs(the_class); ++ JavaFieldStream new_fs(new_class); ++ for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { ++ AccessFlags flags = new_fs.access_flags(); ++ flags.set_is_field_modification_watched(old_fs.access_flags().is_field_modification_watched()); ++ flags.set_is_field_access_watched(old_fs.access_flags().is_field_access_watched()); ++ flags.set_has_field_initialized_final_update(old_fs.access_flags().has_field_initialized_final_update()); ++ new_fs.set_access_flags(flags); ++ } ++ } ++ ++ log_debug(redefine, class, load) ++ ("loaded name=%s (avail_mem=" UINT64_FORMAT "K)", the_class->external_name(), os::available_memory() >> 10); ++ } ++ ++ // Link and verify new classes _after_ all classes have been updated in the system dictionary! ++ for (int i = 0; i < _affected_klasses->length(); i++) { ++ Klass* the_class = _affected_klasses->at(i); ++ assert (the_class->new_version() != NULL, "new version must be present"); ++ InstanceKlass* new_class(InstanceKlass::cast(the_class->new_version())); ++ ++ new_class->link_class(THREAD); ++ ++ if (HAS_PENDING_EXCEPTION) { ++ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); ++ log_info(redefine, class, load, exceptions)("link_class exception: '%s'", new_class->name()->as_C_string()); ++ CLEAR_PENDING_EXCEPTION; ++ if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { ++ return JVMTI_ERROR_OUT_OF_MEMORY; ++ } else { ++ return JVMTI_ERROR_INTERNAL; ++ } ++ } ++ } ++ return JVMTI_ERROR_NONE; ++} ++ ++/** ++ Calculated the difference between new and old class (field change, method change, supertype change, ...). ++*/ ++int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { ++ int result = Klass::NoRedefinition; ++ log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); ++ ++ assert(new_class->old_version() != NULL, "must have old version"); ++ InstanceKlass* the_class = InstanceKlass::cast(new_class->old_version()); ++ ++ // Check whether class is in the error init state. ++ if (the_class->is_in_error_state()) { ++ // TBD #5057930: special error code is needed in 1.6 ++ //result = Klass::union_redefinition_level(result, Klass::Invalid); ++ } ++ ++ int i; ++ ++ // Check superclasses ++ assert(new_class->super() == NULL || new_class->super()->new_version() == NULL, "superclass must be of newest version"); ++ if (the_class->super() != new_class->super()) { ++ // Super class changed ++ Klass* cur_klass = the_class->super(); ++ while (cur_klass != NULL) { ++ if (!new_class->is_subclass_of(cur_klass->newest_version())) { ++ log_info(redefine, class, load)("removed super class %s", cur_klass->name()->as_C_string()); ++ result = result | Klass::RemoveSuperType | Klass::ModifyInstances | Klass::ModifyClass; ++ } ++ cur_klass = cur_klass->super(); ++ } ++ ++ cur_klass = new_class->super(); ++ while (cur_klass != NULL) { ++ if (!the_class->is_subclass_of(cur_klass->old_version())) { ++ log_info(redefine, class, load)("added super class %s", cur_klass->name()->as_C_string()); ++ result = result | Klass::ModifyClass | Klass::ModifyInstances; ++ } ++ cur_klass = cur_klass->super(); ++ } ++ } ++ ++ // Check interfaces ++ ++ // Interfaces removed? ++ Array* old_interfaces = the_class->transitive_interfaces(); ++ for (i = 0; i < old_interfaces->length(); i++) { ++ InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i)); ++ if (!new_class->implements_interface_any_version(old_interface)) { ++ result = result | Klass::RemoveSuperType | Klass::ModifyClass; ++ log_info(redefine, class, load)("removed interface %s", old_interface->name()->as_C_string()); ++ } ++ } ++ ++ // Interfaces added? ++ Array* new_interfaces = new_class->transitive_interfaces(); ++ for (i = 0; ilength(); i++) { ++ if (!the_class->implements_interface_any_version(new_interfaces->at(i))) { ++ result = result | Klass::ModifyClass; ++ log_info(redefine, class, load)("added interface %s", new_interfaces->at(i)->name()->as_C_string()); ++ } ++ } ++ ++ // Check whether class modifiers are the same. ++ jushort old_flags = (jushort) the_class->access_flags().get_flags(); ++ jushort new_flags = (jushort) new_class->access_flags().get_flags(); ++ if (old_flags != new_flags) { ++ // FIXME: Can this have any effects? ++ } ++ ++ // Check if the number, names, types and order of fields declared in these classes ++ // are the same. ++ JavaFieldStream old_fs(the_class); ++ JavaFieldStream new_fs(new_class); ++ for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { ++ // access ++ old_flags = old_fs.access_flags().as_short(); ++ new_flags = new_fs.access_flags().as_short(); ++ if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { ++ // FIXME: can this have any effect? ++ } ++ // offset ++ if (old_fs.offset() != new_fs.offset()) { ++ result = result | Klass::ModifyInstances; ++ } ++ // name and signature ++ Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index()); ++ Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index()); ++ Symbol* name_sym2 = new_class->constants()->symbol_at(new_fs.name_index()); ++ Symbol* sig_sym2 = new_class->constants()->symbol_at(new_fs.signature_index()); ++ if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { ++ result = result | Klass::ModifyInstances; ++ } ++ } ++ ++ // If both streams aren't done then we have a differing number of ++ // fields. ++ if (!old_fs.done() || !new_fs.done()) { ++ result = result | Klass::ModifyInstances; ++ } ++ ++ // Do a parallel walk through the old and new methods. Detect ++ // cases where they match (exist in both), have been added in ++ // the new methods, or have been deleted (exist only in the ++ // old methods). The class file parser places methods in order ++ // by method name, but does not order overloaded methods by ++ // signature. In order to determine what fate befell the methods, ++ // this code places the overloaded new methods that have matching ++ // old methods in the same order as the old methods and places ++ // new overloaded methods at the end of overloaded methods of ++ // that name. The code for this order normalization is adapted ++ // from the algorithm used in InstanceKlass::find_method(). ++ // Since we are swapping out of order entries as we find them, ++ // we only have to search forward through the overloaded methods. ++ // Methods which are added and have the same name as an existing ++ // method (but different signature) will be put at the end of ++ // the methods with that name, and the name mismatch code will ++ // handle them. ++ Array* k_old_methods(the_class->methods()); ++ Array* k_new_methods(new_class->methods()); ++ int n_old_methods = k_old_methods->length(); ++ int n_new_methods = k_new_methods->length(); ++ Thread* thread = Thread::current(); ++ ++ int ni = 0; ++ int oi = 0; ++ while (true) { ++ Method* k_old_method; ++ Method* k_new_method; ++ enum { matched, added, deleted, undetermined } method_was = undetermined; ++ ++ if (oi >= n_old_methods) { ++ if (ni >= n_new_methods) { ++ break; // we've looked at everything, done ++ } ++ // New method at the end ++ k_new_method = k_new_methods->at(ni); ++ method_was = added; ++ } else if (ni >= n_new_methods) { ++ // Old method, at the end, is deleted ++ k_old_method = k_old_methods->at(oi); ++ method_was = deleted; ++ } else { ++ // There are more methods in both the old and new lists ++ k_old_method = k_old_methods->at(oi); ++ k_new_method = k_new_methods->at(ni); ++ if (k_old_method->name() != k_new_method->name()) { ++ // Methods are sorted by method name, so a mismatch means added ++ // or deleted ++ if (k_old_method->name()->fast_compare(k_new_method->name()) > 0) { ++ method_was = added; ++ } else { ++ method_was = deleted; ++ } ++ } else if (k_old_method->signature() == k_new_method->signature()) { ++ // Both the name and signature match ++ method_was = matched; ++ } else { ++ // The name matches, but the signature doesn't, which means we have to ++ // search forward through the new overloaded methods. ++ int nj; // outside the loop for post-loop check ++ for (nj = ni + 1; nj < n_new_methods; nj++) { ++ Method* m = k_new_methods->at(nj); ++ if (k_old_method->name() != m->name()) { ++ // reached another method name so no more overloaded methods ++ method_was = deleted; ++ break; ++ } ++ if (k_old_method->signature() == m->signature()) { ++ // found a match so swap the methods ++ k_new_methods->at_put(ni, m); ++ k_new_methods->at_put(nj, k_new_method); ++ k_new_method = m; ++ method_was = matched; ++ break; ++ } ++ } ++ ++ if (nj >= n_new_methods) { ++ // reached the end without a match; so method was deleted ++ method_was = deleted; ++ } ++ } ++ } ++ ++ switch (method_was) { ++ case matched: ++ // methods match, be sure modifiers do too ++ old_flags = (jushort) k_old_method->access_flags().get_flags(); ++ new_flags = (jushort) k_new_method->access_flags().get_flags(); ++ if ((old_flags ^ new_flags) & ~(JVM_ACC_NATIVE)) { ++ // TODO Can this have any effects? Probably yes on vtables? ++ result = result | Klass::ModifyClass; ++ } ++ { ++ u2 new_num = k_new_method->method_idnum(); ++ u2 old_num = k_old_method->method_idnum(); ++ if (new_num != old_num) { ++ Method* idnum_owner = new_class->method_with_idnum(old_num); ++ if (idnum_owner != NULL) { ++ // There is already a method assigned this idnum -- switch them ++ // Take current and original idnum from the new_method ++ idnum_owner->set_method_idnum(new_num); ++ idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum()); ++ } ++ // Take current and original idnum from the old_method ++ k_new_method->set_method_idnum(old_num); ++ k_new_method->set_orig_method_idnum(k_old_method->orig_method_idnum()); ++ if (thread->has_pending_exception()) { ++ return JVMTI_ERROR_OUT_OF_MEMORY; ++ } ++ } ++ } ++ log_trace(redefine, class, normalize) ++ ("Method matched: new: %s [%d] == old: %s [%d]", ++ k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi); ++ // advance to next pair of methods ++ ++oi; ++ ++ni; ++ break; ++ case added: ++ // method added, see if it is OK ++ new_flags = (jushort) k_new_method->access_flags().get_flags(); ++ if ((new_flags & JVM_ACC_PRIVATE) == 0 ++ // hack: private should be treated as final, but alas ++ || (new_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 ++ ) { ++ // new methods must be private ++ result = result | Klass::ModifyClass; ++ } ++ { ++ u2 num = new_class->next_method_idnum(); ++ if (num == ConstMethod::UNSET_IDNUM) { ++ // cannot add any more methods ++ result = result | Klass::ModifyClass; ++ } ++ u2 new_num = k_new_method->method_idnum(); ++ Method* idnum_owner = new_class->method_with_idnum(num); ++ if (idnum_owner != NULL) { ++ // There is already a method assigned this idnum -- switch them ++ // Take current and original idnum from the new_method ++ idnum_owner->set_method_idnum(new_num); ++ idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum()); ++ } ++ k_new_method->set_method_idnum(num); ++ k_new_method->set_orig_method_idnum(num); ++ if (thread->has_pending_exception()) { ++ return JVMTI_ERROR_OUT_OF_MEMORY; ++ } ++ } ++ log_trace(redefine, class, normalize) ++ ("Method added: new: %s [%d]", k_new_method->name_and_sig_as_C_string(), ni); ++ ++ni; // advance to next new method ++ break; ++ case deleted: ++ // method deleted, see if it is OK ++ old_flags = (jushort) k_old_method->access_flags().get_flags(); ++ if ((old_flags & JVM_ACC_PRIVATE) == 0 ++ // hack: private should be treated as final, but alas ++ || (old_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 ++ ) { ++ // deleted methods must be private ++ result = result | Klass::ModifyClass; ++ } ++ log_trace(redefine, class, normalize) ++ ("Method deleted: old: %s [%d]", k_old_method->name_and_sig_as_C_string(), oi); ++ ++oi; // advance to next old method ++ break; ++ default: ++ ShouldNotReachHere(); ++ } ++ } ++ ++ if (new_class->size() != new_class->old_version()->size()) { ++ result |= Klass::ModifyClassSize; ++ } ++ ++ if (new_class->size_helper() != (InstanceKlass::cast((new_class->old_version()))->size_helper())) { ++ result |= Klass::ModifyInstanceSize; ++ } ++ ++ // TODO Check method bodies to be able to return NoChange? ++ return result; ++} ++ ++ ++/** ++ Searches for the class bytecode of the given class and returns it as a byte array. ++ ++ @param the_class definition of a class, either existing class or new_class ++ @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. ++ @param class_byte_count - size of class_bytes ++ @param not_changed - new_class not available or same as current class ++*/ ++jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) { ++ ++ *not_changed = false; ++ ++ // Search for the index in the redefinition array that corresponds to the current class ++ int i; ++ for (i = 0; i < _class_count; i++) { ++ if (the_class == get_ik(_class_defs[i].klass)) ++ break; ++ } ++ ++ if (i == _class_count) { ++ *not_changed = true; ++ ++ // Redefine with same bytecodes. This is a class that is only indirectly affected by redefinition, ++ // so the user did not specify a different bytecode for that class. ++ if (the_class->get_cached_class_file_bytes() == NULL) { ++ // Not cached, we need to reconstitute the class file from the ++ // VM representation. We don't attach the reconstituted class ++ // bytes to the InstanceKlass here because they have not been ++ // validated and we're not at a safepoint. ++ JvmtiClassFileReconstituter reconstituter(the_class); ++ if (reconstituter.get_error() != JVMTI_ERROR_NONE) { ++ return reconstituter.get_error(); ++ } ++ ++ *class_byte_count = (jint)reconstituter.class_file_size(); ++ *class_bytes = (unsigned char*) reconstituter.class_file_bytes(); ++ } else { ++ // it is cached, get it from the cache ++ *class_byte_count = the_class->get_cached_class_file_len(); ++ *class_bytes = the_class->get_cached_class_file_bytes(); ++ } ++ } else { ++ // Redefine with bytecodes at index j ++ *class_bytes = _class_defs[i].class_bytes; ++ *class_byte_count = _class_defs[i].class_byte_count; ++ } ++ ++ return JVMTI_ERROR_NONE; ++} ++ ++/** ++ Calculate difference between non static fields of old and new class and store the info into new class: ++ instanceKlass->store_update_information ++ instanceKlass->copy_backwards ++*/ ++void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) { ++ ++ class CalculateFieldUpdates : public FieldClosure { ++ ++ private: ++ InstanceKlass* _old_ik; ++ GrowableArray _update_info; ++ int _position; ++ bool _copy_backwards; ++ ++ public: ++ ++ bool does_copy_backwards() { ++ return _copy_backwards; ++ } ++ ++ CalculateFieldUpdates(InstanceKlass* old_ik) : ++ _old_ik(old_ik), _position(instanceOopDesc::base_offset_in_bytes()), _copy_backwards(false) { ++ _update_info.append(_position); ++ _update_info.append(0); ++ } ++ ++ GrowableArray &finish() { ++ _update_info.append(0); ++ return _update_info; ++ } ++ ++ void do_field(fieldDescriptor* fd) { ++ int alignment = fd->offset() - _position; ++ if (alignment > 0) { ++ // This field was aligned, so we need to make sure that we fill the gap ++ fill(alignment); ++ } ++ ++ assert(_position == fd->offset(), "must be correct offset!"); ++ ++ fieldDescriptor old_fd; ++ if (_old_ik->find_field(fd->name(), fd->signature(), false, &old_fd) != NULL) { ++ // Found field in the old class, copy ++ copy(old_fd.offset(), type2aelembytes(fd->field_type())); ++ ++ if (old_fd.offset() < fd->offset()) { ++ _copy_backwards = true; ++ } ++ ++ // Transfer special flags ++ fd->set_is_field_modification_watched(old_fd.is_field_modification_watched()); ++ fd->set_is_field_access_watched(old_fd.is_field_access_watched()); ++ } else { ++ // New field, fill ++ fill(type2aelembytes(fd->field_type())); ++ } ++ } ++ ++ private: ++ void fill(int size) { ++ if (_update_info.length() > 0 && _update_info.at(_update_info.length() - 1) < 0) { ++ (*_update_info.adr_at(_update_info.length() - 1)) -= size; ++ } else { ++ _update_info.append(-size); ++ } ++ _position += size; ++ } ++ ++ void copy(int offset, int size) { ++ int prev_end = -1; ++ if (_update_info.length() > 0 && _update_info.at(_update_info.length() - 1) > 0) { ++ prev_end = _update_info.at(_update_info.length() - 2) + _update_info.at(_update_info.length() - 1); ++ } ++ ++ if (prev_end == offset) { ++ (*_update_info.adr_at(_update_info.length() - 2)) += size; ++ } else { ++ _update_info.append(size); ++ _update_info.append(offset); ++ } ++ ++ _position += size; ++ } ++ }; ++ ++ InstanceKlass* ik = InstanceKlass::cast(new_version); ++ InstanceKlass* old_ik = InstanceKlass::cast(new_version->old_version()); ++ ++ // ++ CalculateFieldUpdates cl(old_ik); ++ ik->do_nonstatic_fields(&cl); ++ ++ GrowableArray result = cl.finish(); ++ ik->store_update_information(result); ++ ik->set_copying_backwards(cl.does_copy_backwards()); ++/* TODO logging ++ if (RC_TRACE_ENABLED(0x00000001)) { ++ RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string())); ++ if (cl.does_copy_backwards()) { ++ RC_TRACE(0x00000001, ("\tDoes copy backwards!")); ++ } ++ for (int i=0; i 0) { ++ RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1))); ++ i++; ++ } else { ++ RC_TRACE(0x00000001, ("\tEND")); ++ } ++ } ++ }*/ ++} ++ ++/** ++ Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. ++*/ ++void VM_EnhancedRedefineClasses::rollback() { ++ log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); ++ ClassLoaderDataGraph::rollback_redefinition(); ++ ++ for (int i = 0; i < _new_classes->length(); i++) { ++ SystemDictionary::remove_from_hierarchy(_new_classes->at(i)); ++ } ++ ++ for (int i = 0; i < _new_classes->length(); i++) { ++ InstanceKlass* new_class = _new_classes->at(i); ++ new_class->set_redefining(false); ++ new_class->old_version()->set_new_version(NULL); ++ new_class->set_old_version(NULL); ++ } ++ _new_classes->clear(); ++} ++ ++ ++// Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp ++// The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not ++// do that, they assume that cache entry is resolved already. ++void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { ++ RawBytecodeStream bcs(method); ++ Bytecodes::Code code; ++ Bytecodes::Code java_code; ++ while (!bcs.is_last_bytecode()) { ++ code = bcs.raw_next(); ++ ++ // dcevm : workaround check _illegal in case of lambda methods etc. ++ // TODO: skip lambda/intrinsic before while loop? (method()->is_method_handle_intrinsic() || method()->is_compiled_lambda_form()) ++ if (code == Bytecodes::_illegal) { ++ return; ++ } ++ ++ address bcp = bcs.bcp(); ++ ++ if (code == Bytecodes::_breakpoint) { ++ int bci = method->bci_from(bcp); ++ code = method->orig_bytecode_at(bci); ++ java_code = Bytecodes::java_code(code); ++ if (code != java_code && ++ (java_code == Bytecodes::_getfield || ++ java_code == Bytecodes::_putfield || ++ java_code == Bytecodes::_aload_0)) { ++ // Let breakpoint table handling unpatch bytecode ++ method->set_orig_bytecode_at(bci, java_code); ++ } ++ } else { ++ java_code = Bytecodes::java_code(code); ++ if (code != java_code && ++ (java_code == Bytecodes::_getfield || ++ java_code == Bytecodes::_putfield || ++ java_code == Bytecodes::_aload_0)) { ++ *bcp = java_code; ++ } ++ } ++ ++ // Additionally, we need to unpatch bytecode at bcp+1 for fast_xaccess (which would be fast field access) ++ if (code == Bytecodes::_fast_iaccess_0 || code == Bytecodes::_fast_aaccess_0 || code == Bytecodes::_fast_faccess_0) { ++ Bytecodes::Code code2 = Bytecodes::code_or_bp_at(bcp + 1); ++ assert(code2 == Bytecodes::_fast_igetfield || ++ code2 == Bytecodes::_fast_agetfield || ++ code2 == Bytecodes::_fast_fgetfield, ""); ++ *(bcp + 1) = Bytecodes::java_code(code2); ++ } ++ } ++ } ++ ++// Unevolving classes may point to methods of the_class directly ++// from their constant pool caches, itables, and/or vtables. We ++// use the ClassLoaderDataGraph::classes_do() facility and this helper ++// to fix up these pointers. ++// Adjust cpools and vtables closure ++void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { ++ // This is a very busy routine. We don't want too much tracing ++ // printed out. ++ bool trace_name_printed = false; ++ InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop); ++ ++ // If the class being redefined is java.lang.Object, we need to fix all ++ // array class vtables also ++ if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { ++ k->vtable().adjust_method_entries(the_class, &trace_name_printed); ++ } else if (k->is_instance_klass()) { ++ HandleMark hm(_thread); ++ InstanceKlass *ik = InstanceKlass::cast(k); ++ ++ // HotSpot specific optimization! HotSpot does not currently ++ // support delegation from the bootstrap class loader to a ++ // user-defined class loader. This means that if the bootstrap ++ // class loader is the initiating class loader, then it will also ++ // be the defining class loader. This also means that classes ++ // loaded by the bootstrap class loader cannot refer to classes ++ // loaded by a user-defined class loader. Note: a user-defined ++ // class loader can delegate to the bootstrap class loader. ++ // ++ // If the current class being redefined has a user-defined class ++ // loader as its defining class loader, then we can skip all ++ // classes loaded by the bootstrap class loader. ++ bool is_user_defined = ++ InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; ++ if (is_user_defined && ik->class_loader() == NULL) { ++ return; ++ } ++ ++ // Fix the vtable embedded in the_class and subclasses of the_class, ++ // if one exists. We discard scratch_class and we don't keep an ++ // InstanceKlass around to hold obsolete methods so we don't have ++ // any other InstanceKlass embedded vtables to update. The vtable ++ // holds the Method*s for virtual (but not final) methods. ++ // Default methods, or concrete methods in interfaces are stored ++ // in the vtable, so if an interface changes we need to check ++ // adjust_method_entries() for every InstanceKlass, which will also ++ // adjust the default method vtable indices. ++ // We also need to adjust any default method entries that are ++ // not yet in the vtable, because the vtable setup is in progress. ++ // This must be done after we adjust the default_methods and ++ // default_vtable_indices for methods already in the vtable. ++ // If redefining Unsafe, walk all the vtables looking for entries. ++// FIXME - code from standard redefine - if needed, it should switch to new_class ++// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() ++// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() ++// || ik->is_subtype_of(_the_class_oop))) { ++// // ik->vtable() creates a wrapper object; rm cleans it up ++// ResourceMark rm(_thread); ++// ++// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed); ++// ik->adjust_default_methods(the_class, &trace_name_printed); ++// } ++ ++ // If the current class has an itable and we are either redefining an ++ // interface or if the current class is a subclass of the_class, then ++ // we potentially have to fix the itable. If we are redefining an ++ // interface, then we have to call adjust_method_entries() for ++ // every InstanceKlass that has an itable since there isn't a ++ // subclass relationship between an interface and an InstanceKlass. ++ // If redefining Unsafe, walk all the itables looking for entries. ++// FIXME - code from standard redefine - if needed, it should switch to new_class ++// if (ik->itable_length() > 0 && (_the_class_oop->is_interface() ++// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() ++// || ik->is_subclass_of(_the_class_oop))) { ++// // ik->itable() creates a wrapper object; rm cleans it up ++// ResourceMark rm(_thread); ++// ++// ik->itable()->adjust_method_entries(the_class, &trace_name_printed); ++// } ++ ++ constantPoolHandle other_cp = constantPoolHandle(ik->constants()); ++ ++ // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. ++ if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { ++ ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); ++ } ++ ++ for (int i = 0; i < other_cp->length(); i++) { ++ if (other_cp->tag_at(i).is_klass()) { ++ Klass* klass = other_cp->resolved_klass_at(i); ++ if (klass->new_version() != NULL) { ++ // Constant pool entry points to redefined class -- update to the new version ++ other_cp->klass_at_put(i, klass->newest_version()); ++ } ++ klass = other_cp->resolved_klass_at(i); ++ assert(klass->new_version() == NULL, "Must be new klass!"); ++ } ++ } ++ ++ // DCEVM - clear whole cache (instead special methods for class/method update in standard redefinition) ++ ConstantPoolCache* cp_cache = other_cp->cache(); ++ if (cp_cache != NULL) { ++ cp_cache->clear_entries(); ++ } ++ ++ // If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries ++ if (RewriteBytecodes) { ++ ik->methods_do(unpatch_bytecode); ++ } ++ } ++} ++ ++// Clean method data for this class ++void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { ++ if (k->is_instance_klass()) { ++ InstanceKlass *ik = InstanceKlass::cast(k); ++ // Clean MethodData of this class's methods so they don't refer to ++ // old methods that are no longer running. ++ Array* methods = ik->methods(); ++ int num_methods = methods->length(); ++ for (int index = 0; index < num_methods; ++index) { ++ if (methods->at(index)->method_data() != NULL) { ++ methods->at(index)->method_data()->clean_weak_method_links(); ++ } ++ } ++ } ++} ++ ++void VM_EnhancedRedefineClasses::update_jmethod_ids() { ++ for (int j = 0; j < _matching_methods_length; ++j) { ++ Method* old_method = _matching_old_methods[j]; ++ jmethodID jmid = old_method->find_jmethod_id_or_null(); ++ if (old_method->new_version() != NULL && jmid == NULL) { ++ // (DCEVM) Have to create jmethodID in this case ++ jmid = old_method->jmethod_id(); ++ } ++ ++ if (jmid != NULL) { ++ // There is a jmethodID, change it to point to the new method ++ methodHandle new_method_h(_matching_new_methods[j]); ++ ++ if (old_method->new_version() == NULL) { ++ methodHandle old_method_h(_matching_old_methods[j]); ++ jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h()); ++ bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id); ++ } else { ++ jmethodID mid = new_method_h->jmethod_id(); ++ bool result = InstanceKlass::cast(new_method_h->method_holder())->update_jmethod_id(new_method_h(), jmid); ++ } ++ ++ Method::change_method_associated_with_jmethod_id(jmid, new_method_h()); ++ assert(Method::resolve_jmethod_id(jmid) == _matching_new_methods[j], "should be replaced"); ++ } ++ } ++} ++ ++/** ++ Set method as obsolete / old / deleted. ++*/ ++void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() { ++ for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) { ++ Method* old_method = _matching_old_methods[j]; ++ Method* new_method = _matching_new_methods[j]; ++ ++ if (MethodComparator::methods_EMCP(old_method, new_method)) { ++ old_method->set_new_version(new_method); ++ new_method->set_old_version(old_method); ++ ++ // Transfer breakpoints ++ InstanceKlass *ik = InstanceKlass::cast(old_method->method_holder()); ++ for (BreakpointInfo* bp = ik->breakpoints(); bp != NULL; bp = bp->next()) { ++ if (bp->match(old_method)) { ++ assert(bp->match(new_method), "if old method is method, then new method must match too"); ++ new_method->set_breakpoint(bp->bci()); ++ } ++ } ++ } else { ++ // mark obsolete methods as such ++ old_method->set_is_obsolete(); ++ ++ // obsolete methods need a unique idnum so they become new entries in ++ // the jmethodID cache in InstanceKlass ++ assert(old_method->method_idnum() == new_method->method_idnum(), "must match"); ++// u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum(); ++// if (num != ConstMethod::UNSET_IDNUM) { ++// old_method->set_method_idnum(num); ++// } ++ } ++ old_method->set_is_old(); ++ } ++ for (int i = 0; i < _deleted_methods_length; ++i) { ++ Method* old_method = _deleted_methods[i]; ++ ++ old_method->set_is_old(); ++ old_method->set_is_obsolete(); ++ // FIXME: this flag was added in dcevm10 since it is required in resolvedMethodTable.cpp ++ old_method->set_is_deleted(); ++ } ++} ++ ++// This internal class transfers the native function registration from old methods ++// to new methods. It is designed to handle both the simple case of unchanged ++// native methods and the complex cases of native method prefixes being added and/or ++// removed. ++// It expects only to be used during the VM_EnhancedRedefineClasses op (a safepoint). ++// ++// This class is used after the new methods have been installed in "the_class". ++// ++// So, for example, the following must be handled. Where 'm' is a method and ++// a number followed by an underscore is a prefix. ++// ++// Old Name New Name ++// Simple transfer to new method m -> m ++// Add prefix m -> 1_m ++// Remove prefix 1_m -> m ++// Simultaneous add of prefixes m -> 3_2_1_m ++// Simultaneous removal of prefixes 3_2_1_m -> m ++// Simultaneous add and remove 1_m -> 2_m ++// Same, caused by prefix removal only 3_2_1_m -> 3_2_m ++// ++class TransferNativeFunctionRegistration { ++ private: ++ InstanceKlass* the_class; ++ int prefix_count; ++ char** prefixes; ++ ++ // Recursively search the binary tree of possibly prefixed method names. ++ // Iteration could be used if all agents were well behaved. Full tree walk is ++ // more resilent to agents not cleaning up intermediate methods. ++ // Branch at each depth in the binary tree is: ++ // (1) without the prefix. ++ // (2) with the prefix. ++ // where 'prefix' is the prefix at that 'depth' (first prefix, second prefix,...) ++ Method* search_prefix_name_space(int depth, char* name_str, size_t name_len, ++ Symbol* signature) { ++ TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len); ++ if (name_symbol != NULL) { ++ Method* method = the_class->lookup_method(name_symbol, signature); ++ if (method != NULL) { ++ // Even if prefixed, intermediate methods must exist. ++ if (method->is_native()) { ++ // Wahoo, we found a (possibly prefixed) version of the method, return it. ++ return method; ++ } ++ if (depth < prefix_count) { ++ // Try applying further prefixes (other than this one). ++ method = search_prefix_name_space(depth+1, name_str, name_len, signature); ++ if (method != NULL) { ++ return method; // found ++ } ++ ++ // Try adding this prefix to the method name and see if it matches ++ // another method name. ++ char* prefix = prefixes[depth]; ++ size_t prefix_len = strlen(prefix); ++ size_t trial_len = name_len + prefix_len; ++ char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1); ++ strcpy(trial_name_str, prefix); ++ strcat(trial_name_str, name_str); ++ method = search_prefix_name_space(depth+1, trial_name_str, trial_len, ++ signature); ++ if (method != NULL) { ++ // If found along this branch, it was prefixed, mark as such ++ method->set_is_prefixed_native(); ++ return method; // found ++ } ++ } ++ } ++ } ++ return NULL; // This whole branch bore nothing ++ } ++ ++ // Return the method name with old prefixes stripped away. ++ char* method_name_without_prefixes(Method* method) { ++ Symbol* name = method->name(); ++ char* name_str = name->as_utf8(); ++ ++ // Old prefixing may be defunct, strip prefixes, if any. ++ for (int i = prefix_count-1; i >= 0; i--) { ++ char* prefix = prefixes[i]; ++ size_t prefix_len = strlen(prefix); ++ if (strncmp(prefix, name_str, prefix_len) == 0) { ++ name_str += prefix_len; ++ } ++ } ++ return name_str; ++ } ++ ++ // Strip any prefixes off the old native method, then try to find a ++ // (possibly prefixed) new native that matches it. ++ Method* strip_and_search_for_new_native(Method* method) { ++ ResourceMark rm; ++ char* name_str = method_name_without_prefixes(method); ++ return search_prefix_name_space(0, name_str, strlen(name_str), ++ method->signature()); ++ } ++ ++ public: ++ ++ // Construct a native method transfer processor for this class. ++ TransferNativeFunctionRegistration(InstanceKlass* _the_class) { ++ assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); ++ ++ the_class = _the_class; ++ prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); ++ } ++ ++ // Attempt to transfer any of the old or deleted methods that are native ++ void transfer_registrations(Method** old_methods, int methods_length) { ++ for (int j = 0; j < methods_length; j++) { ++ Method* old_method = old_methods[j]; ++ ++ if (old_method->is_native() && old_method->has_native_function()) { ++ Method* new_method = strip_and_search_for_new_native(old_method); ++ if (new_method != NULL) { ++ // Actually set the native function in the new method. ++ // Redefine does not send events (except CFLH), certainly not this ++ // behind the scenes re-registration. ++ new_method->set_native_function(old_method->native_function(), ++ !Method::native_bind_event_is_interesting); ++ } ++ } ++ } ++ } ++}; ++ ++// Don't lose the association between a native method and its JNI function. ++void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(InstanceKlass* the_class) { ++ TransferNativeFunctionRegistration transfer(the_class); ++ transfer.transfer_registrations(_deleted_methods, _deleted_methods_length); ++ transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); ++} ++ ++// DCEVM - it always deoptimases everything! (because it is very difficult to find only correct dependencies) ++// Deoptimize all compiled code that depends on this class. ++// ++// If the can_redefine_classes capability is obtained in the onload ++// phase then the compiler has recorded all dependencies from startup. ++// In that case we need only deoptimize and throw away all compiled code ++// that depends on the class. ++// ++// If can_redefine_classes is obtained sometime after the onload ++// phase then the dependency information may be incomplete. In that case ++// the first call to RedefineClasses causes all compiled code to be ++// thrown away. As can_redefine_classes has been obtained then ++// all future compilations will record dependencies so second and ++// subsequent calls to RedefineClasses need only throw away code ++// that depends on the class. ++// ++void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) { ++ assert_locked_or_safepoint(Compile_lock); ++ ++ // All dependencies have been recorded from startup or this is a second or ++ // subsequent use of RedefineClasses ++ // FIXME: for now, deoptimize all! ++ if (0 && JvmtiExport::all_dependencies_are_recorded()) { ++ CodeCache::flush_evol_dependents_on(k_h); ++ } else { ++ CodeCache::mark_all_nmethods_for_deoptimization(); ++ ++ ResourceMark rm(THREAD); ++ DeoptimizationMarker dm; ++ ++ // Deoptimize all activations depending on marked nmethods ++ Deoptimization::deoptimize_dependents(); ++ ++ // Make the dependent methods not entrant ++ CodeCache::make_marked_nmethods_not_entrant(); ++ ++ // From now on we know that the dependency information is complete ++ JvmtiExport::set_all_dependencies_are_recorded(true); ++ } ++} ++ ++/** ++ Compare _old_methods and _new_methods arrays and store the result into ++ _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods ++ ++ Setup _old_methods and _new_methods before the call - it should be called for one class only! ++*/ ++void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { ++ Method* old_method; ++ Method* new_method; ++ ++ _matching_old_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); ++ _matching_new_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); ++ _added_methods = NEW_RESOURCE_ARRAY(Method*, _new_methods->length()); ++ _deleted_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); ++ ++ _matching_methods_length = 0; ++ _deleted_methods_length = 0; ++ _added_methods_length = 0; ++ ++ int nj = 0; ++ int oj = 0; ++ while (true) { ++ if (oj >= _old_methods->length()) { ++ if (nj >= _new_methods->length()) { ++ break; // we've looked at everything, done ++ } ++ // New method at the end ++ new_method = _new_methods->at(nj); ++ _added_methods[_added_methods_length++] = new_method; ++ ++nj; ++ } else if (nj >= _new_methods->length()) { ++ // Old method, at the end, is deleted ++ old_method = _old_methods->at(oj); ++ _deleted_methods[_deleted_methods_length++] = old_method; ++ ++oj; ++ } else { ++ old_method = _old_methods->at(oj); ++ new_method = _new_methods->at(nj); ++ if (old_method->name() == new_method->name()) { ++ if (old_method->signature() == new_method->signature()) { ++ _matching_old_methods[_matching_methods_length ] = old_method; ++ _matching_new_methods[_matching_methods_length++] = new_method; ++ ++nj; ++ ++oj; ++ } else { ++ // added overloaded have already been moved to the end, ++ // so this is a deleted overloaded method ++ _deleted_methods[_deleted_methods_length++] = old_method; ++ ++oj; ++ } ++ } else { // names don't match ++ if (old_method->name()->fast_compare(new_method->name()) > 0) { ++ // new method ++ _added_methods[_added_methods_length++] = new_method; ++ ++nj; ++ } else { ++ // deleted method ++ _deleted_methods[_deleted_methods_length++] = old_method; ++ ++oj; ++ } ++ } ++ } ++ } ++ assert(_matching_methods_length + _deleted_methods_length == _old_methods->length(), "sanity"); ++ assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity"); ++} ++ ++/** ++ FIXME - swap_annotations is never called, check that annotations work ++*/ ++void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class, ++ InstanceKlass* new_class) { ++ // FIXME - probably original implementation only ++ // Swap annotation fields values ++ Annotations* old_annotations = the_class->annotations(); ++ the_class->set_annotations(new_class->annotations()); ++ new_class->set_annotations(old_annotations); ++} ++ ++ ++// Install the redefinition of a class: ++// - house keeping (flushing breakpoints and caches, deoptimizing ++// dependent compiled code) ++// - replacing parts in the_class with parts from new_class ++// - adding a weak reference to track the obsolete but interesting ++// parts of the_class ++// - adjusting constant pool caches and vtables in other classes ++// that refer to methods in the_class. These adjustments use the ++// ClassLoaderDataGraph::classes_do() facility which only allows ++// a helper method to be specified. The interesting parameters ++// that we would like to pass to the helper method are saved in ++// static global fields in the VM operation. ++void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_oop, TRAPS) { ++ ++ HandleMark hm(THREAD); // make sure handles from this call are freed ++ ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_rsc_phase1.start(); ++ } ++ ++ InstanceKlass* new_class = new_class_oop; ++ InstanceKlass* the_class = InstanceKlass::cast(new_class_oop->old_version()); ++ assert(the_class != NULL, "must have old version"); ++ ++ // Remove all breakpoints in methods of this class ++ JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); ++ jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); ++ ++ // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined ++ // Deoptimize all compiled code that depends on this class ++ // flush_dependent_code(the_class, THREAD); ++ ++ _old_methods = the_class->methods(); ++ _new_methods = new_class->methods(); ++ _the_class_oop = the_class; ++ compute_added_deleted_matching_methods(); ++ ++ // track number of methods that are EMCP for add_previous_version() call below ++ check_methods_and_mark_as_obsolete(); ++ update_jmethod_ids(); ++ ++ _any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods; ++ ++ transfer_old_native_function_registrations(the_class); ++ ++ ++ // JSR-292 support ++ /* FIXME: j10 dropped support for it? ++ MemberNameTable* mnt = the_class->member_names(); ++ assert(new_class->member_names() == NULL, ""); ++ if (mnt != NULL) { ++ new_class->set_member_names(mnt); ++ the_class->set_member_names(NULL); ++ ++ // FIXME: adjust_method_entries is used in standard hotswap JDK9 ++ // bool trace_name_printed = false; ++ // mnt->adjust_method_entries(new_class(), &trace_name_printed); ++ } ++ */ ++ ++ // Adjust constantpool caches for all classes that reference methods of the evolved class. ++ ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD); ++ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); ++ ++ { ++ ResourceMark rm(THREAD); ++ // increment the classRedefinedCount field in the_class and in any ++ // direct and indirect subclasses of the_class ++ increment_class_counter(the_class, THREAD); ++ log_info(redefine, class, load) ++ ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", ++ the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10); ++ Events::log_redefinition(THREAD, "redefined class name=%s, count=%d", ++ the_class->external_name(), ++ java_lang_Class::classRedefinedCount(the_class->java_mirror())); ++ ++ } ++ _timer_rsc_phase2.stop(); ++} // end redefine_single_class() ++ ++ ++// Increment the classRedefinedCount field in the specific InstanceKlass ++// and in all direct and indirect subclasses. ++void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { ++ oop class_mirror = ik->java_mirror(); ++ Klass* class_oop = java_lang_Class::as_Klass(class_mirror); ++ int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; ++ java_lang_Class::set_classRedefinedCount(class_mirror, new_count); ++ ++ if (class_oop != _the_class_oop) { ++ // _the_class_oop count is printed at end of redefine_single_class() ++ log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count); ++ } ++ ++ for (Klass *subk = ik->subklass(); subk != NULL; ++ subk = subk->next_sibling()) { ++ if (subk->is_instance_klass()) { ++ // Only update instanceKlasses ++ InstanceKlass *subik = InstanceKlass::cast(subk); ++ // recursively do subclasses of the current subclass ++ increment_class_counter(subik, THREAD); ++ } ++ } ++} ++ ++// FIXME - class check is currently disabled ++void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) { ++ return; ++ bool no_old_methods = true; // be optimistic ++ ++ // Both array and instance classes have vtables. ++ // a vtable should never contain old or obsolete methods ++ ResourceMark rm(_thread); ++ if (k->vtable_length() > 0 && ++ !k->vtable().check_no_old_or_obsolete_entries()) { ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++ log_trace(redefine, class, obsolete, metadata) ++ ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", ++ k->signature_name()); ++ k->vtable().dump_vtable(); ++ } ++ no_old_methods = false; ++ } ++ ++ if (k->is_instance_klass()) { ++ HandleMark hm(_thread); ++ InstanceKlass *ik = InstanceKlass::cast(k); ++ ++ // an itable should never contain old or obsolete methods ++ if (ik->itable_length() > 0 && ++ !ik->itable().check_no_old_or_obsolete_entries()) { ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++ log_trace(redefine, class, obsolete, metadata) ++ ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", ++ ik->signature_name()); ++ ik->itable().dump_itable(); ++ } ++ no_old_methods = false; ++ } ++ ++ // the constant pool cache should never contain non-deleted old or obsolete methods ++ if (ik->constants() != NULL && ++ ik->constants()->cache() != NULL && ++ !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++ log_trace(redefine, class, obsolete, metadata) ++ ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", ++ ik->signature_name()); ++ ik->constants()->cache()->dump_cache(); ++ } ++ no_old_methods = false; ++ } ++ } ++ ++ // print and fail guarantee if old methods are found. ++ if (!no_old_methods) { ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++ dump_methods(); ++ } else { ++ log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option " ++ "to see more info about the following guarantee() failure."); ++ } ++ guarantee(false, "OLD and/or OBSOLETE method(s) found"); ++ } ++} ++ ++/** ++ * Logging of all methods (old, new, changed, ...) ++ */ ++void VM_EnhancedRedefineClasses::dump_methods() { ++ int j; ++ log_trace(redefine, class, dump)("_old_methods --"); ++ for (j = 0; j < _old_methods->length(); ++j) { ++ LogStreamHandle(Trace, redefine, class, dump) log_stream; ++ Method* m = _old_methods->at(j); ++ log_stream.print("%4d (%5d) ", j, m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.print(" -- "); ++ m->print_name(&log_stream); ++ log_stream.cr(); ++ } ++ log_trace(redefine, class, dump)("_new_methods --"); ++ for (j = 0; j < _new_methods->length(); ++j) { ++ LogStreamHandle(Trace, redefine, class, dump) log_stream; ++ Method* m = _new_methods->at(j); ++ log_stream.print("%4d (%5d) ", j, m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.print(" -- "); ++ m->print_name(&log_stream); ++ log_stream.cr(); ++ } ++ log_trace(redefine, class, dump)("_matching_methods --"); ++ for (j = 0; j < _matching_methods_length; ++j) { ++ LogStreamHandle(Trace, redefine, class, dump) log_stream; ++ Method* m = _matching_old_methods[j]; ++ log_stream.print("%4d (%5d) ", j, m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.print(" -- "); ++ m->print_name(); ++ log_stream.cr(); ++ ++ m = _matching_new_methods[j]; ++ log_stream.print(" (%5d) ", m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.cr(); ++ } ++ log_trace(redefine, class, dump)("_deleted_methods --"); ++ for (j = 0; j < _deleted_methods_length; ++j) { ++ LogStreamHandle(Trace, redefine, class, dump) log_stream; ++ Method* m = _deleted_methods[j]; ++ log_stream.print("%4d (%5d) ", j, m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.print(" -- "); ++ m->print_name(&log_stream); ++ log_stream.cr(); ++ } ++ log_trace(redefine, class, dump)("_added_methods --"); ++ for (j = 0; j < _added_methods_length; ++j) { ++ LogStreamHandle(Trace, redefine, class, dump) log_stream; ++ Method* m = _added_methods[j]; ++ log_stream.print("%4d (%5d) ", j, m->vtable_index()); ++ m->access_flags().print_on(&log_stream); ++ log_stream.print(" -- "); ++ m->print_name(&log_stream); ++ log_stream.cr(); ++ } ++} ++ ++// TODO - is it called anywhere? ++void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const { ++ VM_Operation::print_on_error(st); ++ if (_the_class_oop != NULL) { ++ ResourceMark rm; ++ st->print_cr(", redefining class %s", _the_class_oop->external_name()); ++ } ++} ++ ++/** ++ Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. ++*/ ++class AffectedKlassClosure : public KlassClosure { ++ private: ++ GrowableArray* _affected_klasses; ++ public: ++ AffectedKlassClosure(GrowableArray* affected_klasses) : _affected_klasses(affected_klasses) {} ++ ++ void do_klass(Klass* klass) { ++ assert(!_affected_klasses->contains(klass), "must not occur more than once!"); ++ ++ if (klass->new_version() != NULL) { ++ return; ++ } ++ assert(klass->new_version() == NULL, "only last version is valid"); ++ ++ if (klass->check_redefinition_flag(Klass::MarkedAsAffected)) { ++ _affected_klasses->append(klass); ++ return; ++ } ++ ++ int super_depth = klass->super_depth(); ++ int idx; ++ for (idx = 0; idx < super_depth; idx++) { ++ Klass* primary = klass->primary_super_of_depth(idx); ++ if (primary == NULL) { ++ break; ++ } ++ if (primary->check_redefinition_flag(Klass::MarkedAsAffected)) { ++ log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); ++ klass->set_redefinition_flag(Klass::MarkedAsAffected); ++ _affected_klasses->append(klass); ++ return; ++ } ++ } ++ ++ int secondary_length = klass->secondary_supers()->length(); ++ for (idx = 0; idx < secondary_length; idx++) { ++ Klass* secondary = klass->secondary_supers()->at(idx); ++ if (secondary->check_redefinition_flag(Klass::MarkedAsAffected)) { ++ log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); ++ klass->set_redefinition_flag(Klass::MarkedAsAffected); ++ _affected_klasses->append(klass); ++ return; ++ } ++ } ++ } ++}; ++ ++/** ++ Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). ++ Affected classes are stored in _affected_klasses and parent classes always precedes child class. ++*/ ++jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { ++ for (int i = 0; i < _class_count; i++) { ++ InstanceKlass* klass_handle = get_ik(_class_defs[i].klass); ++ klass_handle->set_redefinition_flag(Klass::MarkedAsAffected); ++ assert(klass_handle->new_version() == NULL, "must be new class"); ++ ++ log_trace(redefine, class, load)("marking class as being redefined: %s", klass_handle->name()->as_C_string()); ++ } ++ ++ // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) ++ AffectedKlassClosure closure(_affected_klasses); ++ // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure); ++ ClassLoaderDataGraph::dictionary_classes_do(&closure); ++ log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); ++ ++ // Sort the affected klasses such that a supertype is always on a smaller array index than its subtype. ++ jvmtiError result = do_topological_class_sorting(THREAD); ++ ++ if (log_is_enabled(Trace, redefine, class, load)) { ++ log_trace(redefine, class, load)("redefine order:"); ++ for (int i = 0; i < _affected_klasses->length(); i++) { ++ log_trace(redefine, class, load)("%s", _affected_klasses->at(i)->name()->as_C_string()); ++ } ++ } ++ return JVMTI_ERROR_NONE; ++} ++ ++/** ++ Pairs of class dependencies (for topological sort) ++*/ ++struct KlassPair { ++ const Klass* _left; ++ const Klass* _right; ++ ++ KlassPair() { } ++ KlassPair(const Klass* left, const Klass* right) : _left(left), _right(right) { } ++}; ++ ++static bool match_second(void* value, KlassPair elem) { ++ return elem._right == value; ++} ++ ++/** ++ For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. ++ First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). ++ Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) ++ ++ For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. ++ ++ TODO - the class file is potentionally parsed multiple times - introduce a cache? ++*/ ++jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { ++ ResourceMark mark(THREAD); ++ ++ // Collect dependencies ++ GrowableArray links; ++ for (int i = 0; i < _class_count; i++) { ++ InstanceKlass* klass = get_ik(_class_defs[i].klass); ++ ++ ClassFileStream st((u1*)_class_defs[i].class_bytes, ++ _class_defs[i].class_byte_count, ++ "__VM_EnhancedRedefineClasses__", ++ ClassFileStream::verify); ++ ++ Handle protection_domain(THREAD, klass->protection_domain()); ++ ++ ClassFileParser parser(&st, ++ klass->name(), ++ klass->class_loader_data(), ++ protection_domain, ++ NULL, // host_klass ++ NULL, // cp_patches ++ ClassFileParser::INTERNAL, // publicity level ++ true, ++ THREAD); ++ ++ const Klass* super_klass = parser.super_klass(); ++ if (super_klass != NULL && _affected_klasses->contains((Klass*) super_klass)) { ++ links.append(KlassPair(super_klass, klass)); ++ } ++ ++ Array* local_interfaces = parser.local_interfaces(); ++ for (int j = 0; j < local_interfaces->length(); j++) { ++ Klass* iface = local_interfaces->at(j); ++ if (iface != NULL && _affected_klasses->contains(iface)) { ++ links.append(KlassPair(iface, klass)); ++ } ++ } ++ ++ assert(klass->check_redefinition_flag(Klass::MarkedAsAffected), ""); ++ klass->clear_redefinition_flag(Klass::MarkedAsAffected); ++ } ++ ++ // Append dependencies based on current class definition ++ for (int i = 0; i < _affected_klasses->length(); i++) { ++ InstanceKlass* klass = InstanceKlass::cast(_affected_klasses->at(i)); ++ ++ if (klass->check_redefinition_flag(Klass::MarkedAsAffected)) { ++ klass->clear_redefinition_flag(Klass::MarkedAsAffected); ++ Klass* super_klass = klass->super(); ++ if (_affected_klasses->contains(super_klass)) { ++ links.append(KlassPair(super_klass, klass)); ++ } ++ ++ Array* local_interfaces = klass->local_interfaces(); ++ for (int j = 0; j < local_interfaces->length(); j++) { ++ Klass* interfaceKlass = local_interfaces->at(j); ++ if (_affected_klasses->contains(interfaceKlass)) { ++ links.append(KlassPair(interfaceKlass, klass)); ++ } ++ } ++ } ++ } ++ ++ for (int i = 0; i < _affected_klasses->length(); i++) { ++ int j; ++ for (j = i; j < _affected_klasses->length(); j++) { ++ // Search for node with no incoming edges ++ Klass* klass = _affected_klasses->at(j); ++ int k = links.find(klass, match_second); ++ if (k == -1) break; ++ } ++ if (j == _affected_klasses->length()) { ++ return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; ++ } ++ ++ // Remove all links from this node ++ const Klass* klass = _affected_klasses->at(j); ++ int k = 0; ++ while (k < links.length()) { ++ if (links.at(k)._left == klass) { ++ links.delete_at(k); ++ } else { ++ k++; ++ } ++ } ++ ++ // Swap node ++ Klass* tmp = _affected_klasses->at(j); ++ _affected_klasses->at_put(j, _affected_klasses->at(i)); ++ _affected_klasses->at_put(i, tmp); ++ } ++ ++ return JVMTI_ERROR_NONE; ++} +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +new file mode 100644 +index 00000000000..b712d69a193 +--- /dev/null ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (c) 2003, 2016, 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_PRIMS_JVMTIREDEFINECLASSES2_HPP ++#define SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP ++ ++#include "jvmtifiles/jvmtiEnv.hpp" ++#include "memory/oopFactory.hpp" ++#include "memory/resourceArea.hpp" ++#include "oops/objArrayKlass.hpp" ++#include "oops/objArrayOop.hpp" ++#include "runtime/vm_operations.hpp" ++#include "gc/shared/vmGCOperations.hpp" ++#include "../../../java.base/unix/native/include/jni_md.h" ++ ++/** ++ * Enhanced class redefiner. ++ * ++ * This class implements VM_GC_Operation - the usual usage should be: ++ * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++ * VMThread::execute(&op); ++ * Which in turn runs: ++ * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions ++ * - doit() - main redefition, adjust existing objects on the heap, clear caches ++ * - doit_epilogue() - cleanup ++*/ ++class VM_EnhancedRedefineClasses: public VM_GC_Operation { ++ private: ++ // These static fields are needed by ClassLoaderDataGraph::classes_do() ++ // facility and the AdjustCpoolCacheAndVtable helper: ++ static Array* _old_methods; ++ static Array* _new_methods; ++ static Method** _matching_old_methods; ++ static Method** _matching_new_methods; ++ static Method** _deleted_methods; ++ static Method** _added_methods; ++ static int _matching_methods_length; ++ static int _deleted_methods_length; ++ static int _added_methods_length; ++ static Klass* _the_class_oop; ++ ++ // The instance fields are used to pass information from ++ // doit_prologue() to doit() and doit_epilogue(). ++ jint _class_count; ++ const jvmtiClassDefinition *_class_defs; // ptr to _class_count defs ++ ++ // This operation is used by both RedefineClasses and ++ // RetransformClasses. Indicate which. ++ JvmtiClassLoadKind _class_load_kind; ++ ++ // _index_map_count is just an optimization for knowing if ++ // _index_map_p contains any entries. ++ int _index_map_count; ++ intArray * _index_map_p; ++ ++ // _operands_index_map_count is just an optimization for knowing if ++ // _operands_index_map_p contains any entries. ++ int _operands_cur_length; ++ int _operands_index_map_count; ++ intArray * _operands_index_map_p; ++ ++ GrowableArray* _new_classes; ++ jvmtiError _res; ++ ++ // Set if any of the InstanceKlasses have entries in the ResolvedMethodTable ++ // to avoid walking after redefinition if the redefined classes do not ++ // have any entries. ++ bool _any_class_has_resolved_methods; ++ ++ // Enhanced class redefinition, affected klasses contain all classes which should be redefined ++ // either because of redefine, class hierarchy or interface change ++ GrowableArray* _affected_klasses; ++ ++ int _max_redefinition_flags; ++ ++ // Performance measurement support. These timers do not cover all ++ // the work done for JVM/TI RedefineClasses() but they do cover ++ // the heavy lifting. ++ elapsedTimer _timer_rsc_phase1; ++ elapsedTimer _timer_rsc_phase2; ++ elapsedTimer _timer_vm_op_prologue; ++ ++ // These routines are roughly in call order unless otherwise noted. ++ ++ /** ++ Load and link new classes (either redefined or affected by redefinition - subclass, ...) ++ ++ - find sorted affected classes ++ - resolve new class ++ - calculate redefine flags (field change, method change, supertype change, ...) ++ - calculate modified fields and mapping to old fields ++ - link new classes ++ ++ The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. ++ */ ++ jvmtiError load_new_class_versions(TRAPS); ++ ++ // Searches for all affected classes and performs a sorting such tha ++ // a supertype is always before a subtype. ++ jvmtiError find_sorted_affected_classes(TRAPS); ++ ++ jvmtiError do_topological_class_sorting(TRAPS); ++ ++ jvmtiError find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed); ++ int calculate_redefinition_flags(InstanceKlass* new_class); ++ void calculate_instance_update_information(Klass* new_version); ++ ++ void rollback(); ++ static void mark_as_scavengable(nmethod* nm); ++ static void unpatch_bytecode(Method* method); ++ ++ // Figure out which new methods match old methods in name and signature, ++ // which methods have been added, and which are no longer present ++ void compute_added_deleted_matching_methods(); ++ ++ // Change jmethodIDs to point to the new methods ++ void update_jmethod_ids(); ++ ++ // marking methods as old and/or obsolete ++ void check_methods_and_mark_as_obsolete(); ++ void transfer_old_native_function_registrations(InstanceKlass* the_class); ++ ++ // Install the redefinition of a class ++ void redefine_single_class(InstanceKlass* new_class_oop, TRAPS); ++ ++ void swap_annotations(InstanceKlass* new_class, ++ InstanceKlass* scratch_class); ++ ++ // Increment the classRedefinedCount field in the specific InstanceKlass ++ // and in all direct and indirect subclasses. ++ void increment_class_counter(InstanceKlass *ik, TRAPS); ++ ++ void flush_dependent_code(InstanceKlass* k_h, TRAPS); ++ ++ static void dump_methods(); ++ ++ // Check that there are no old or obsolete methods ++ class CheckClass : public KlassClosure { ++ Thread* _thread; ++ public: ++ CheckClass(Thread* t) : _thread(t) {} ++ void do_klass(Klass* k); ++ }; ++ ++ // Unevolving classes may point to methods of the_class directly ++ // from their constant pool caches, itables, and/or vtables. We ++ // use the ClassLoaderDataGraph::classes_do() facility and this helper ++ // to fix up these pointers. ++ class ClearCpoolCacheAndUnpatch : public KlassClosure { ++ Thread* _thread; ++ public: ++ ClearCpoolCacheAndUnpatch(Thread* t) : _thread(t) {} ++ void do_klass(Klass* k); ++ }; ++ ++ // Clean MethodData out ++ class MethodDataCleaner : public KlassClosure { ++ public: ++ MethodDataCleaner() {} ++ void do_klass(Klass* k); ++ }; ++ public: ++ VM_EnhancedRedefineClasses(jint class_count, ++ const jvmtiClassDefinition *class_defs, ++ JvmtiClassLoadKind class_load_kind); ++ VMOp_Type type() const { return VMOp_RedefineClasses; } ++ bool doit_prologue(); ++ void doit(); ++ void doit_epilogue(); ++ ++ bool allow_nested_vm_operations() const { return true; } ++ jvmtiError check_error() { return _res; } ++ ++ // Modifiable test must be shared between IsModifiableClass query ++ // and redefine implementation ++ static bool is_modifiable_class(oop klass_mirror); ++ ++ // Error printing ++ void print_on_error(outputStream* st) const; ++}; ++#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP +diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp +index 342a0467112..b6838ac034d 100644 +--- a/src/hotspot/share/prims/jvmtiEnv.cpp ++++ b/src/hotspot/share/prims/jvmtiEnv.cpp +@@ -51,6 +51,7 @@ + #include "prims/jvmtiManageCapabilities.hpp" + #include "prims/jvmtiRawMonitor.hpp" + #include "prims/jvmtiRedefineClasses.hpp" ++#include "prims/jvmtiEnhancedRedefineClasses.hpp" + #include "prims/jvmtiTagMap.hpp" + #include "prims/jvmtiThreadState.inline.hpp" + #include "prims/jvmtiUtil.hpp" +@@ -383,8 +384,13 @@ JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr + // is_modifiable_class_ptr - pre-checked for NULL + jvmtiError + JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) { +- *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? +- JNI_TRUE : JNI_FALSE; ++ if (AllowEnhancedClassRedefinition) { ++ *is_modifiable_class_ptr = VM_EnhancedRedefineClasses::is_modifiable_class(k_mirror)? ++ JNI_TRUE : JNI_FALSE; ++ } else { ++ *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? ++ JNI_TRUE : JNI_FALSE; ++ } + return JVMTI_ERROR_NONE; + } /* end IsModifiableClass */ + +@@ -414,7 +420,8 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { + return JVMTI_ERROR_INVALID_CLASS; + } + +- if (!VM_RedefineClasses::is_modifiable_class(k_mirror)) { ++ if ((!AllowEnhancedClassRedefinition && !VM_RedefineClasses::is_modifiable_class(k_mirror)) || ++ (AllowEnhancedClassRedefinition && !VM_EnhancedRedefineClasses::is_modifiable_class(k_mirror))) { + return JVMTI_ERROR_UNMODIFIABLE_CLASS; + } + +@@ -446,10 +453,20 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { + } + class_definitions[index].klass = jcls; + } ++ + EventRetransformClasses event; +- VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); +- VMThread::execute(&op); +- jvmtiError error = op.check_error(); ++ jvmtiError error; ++ ++ if (AllowEnhancedClassRedefinition) { ++ MutexLocker sd_mutex(EnhancedRedefineClasses_lock); ++ VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); ++ VMThread::execute(&op); ++ error = (op.check_error()); ++ } else { ++ VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); ++ VMThread::execute(&op); ++ error = op.check_error(); ++ } + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); + event.set_redefinitionId(op.id()); +@@ -465,9 +482,18 @@ jvmtiError + JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { + //TODO: add locking + EventRedefineClasses event; +- VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); +- VMThread::execute(&op); +- jvmtiError error = op.check_error(); ++ jvmtiError error; ++ ++ if (AllowEnhancedClassRedefinition) { ++ MutexLocker sd_mutex(EnhancedRedefineClasses_lock); ++ VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++ VMThread::execute(&op); ++ error = (op.check_error()); ++ } else { ++ VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++ VMThread::execute(&op); ++ error = op.check_error(); ++ } + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); + event.set_redefinitionId(op.id()); +diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp +index d4579dfa43d..8e20fb64a8b 100644 +--- a/src/hotspot/share/prims/jvmtiExport.cpp ++++ b/src/hotspot/share/prims/jvmtiExport.cpp +@@ -2796,7 +2796,7 @@ JvmtiDynamicCodeEventCollector::JvmtiDynamicCodeEventCollector() : _code_blobs(N + // iterate over any code blob descriptors collected and post a + // DYNAMIC_CODE_GENERATED event to the profiler. + JvmtiDynamicCodeEventCollector::~JvmtiDynamicCodeEventCollector() { +- assert(!JavaThread::current()->owns_locks(), "all locks must be released to post deferred events"); ++ assert(AllowEnhancedClassRedefinition || !JavaThread::current()->owns_locks(), "all locks must be released to post deferred events"); + // iterate over any code blob descriptors that we collected + if (_code_blobs != NULL) { + for (int i=0; i<_code_blobs->length(); i++) { +diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp +index f903b32be64..345cb21af33 100644 +--- a/src/hotspot/share/prims/jvmtiExport.hpp ++++ b/src/hotspot/share/prims/jvmtiExport.hpp +@@ -176,6 +176,7 @@ class JvmtiExport : public AllStatic { + // systems as needed to relax invariant checks. + static uint64_t _redefinition_count; + friend class VM_RedefineClasses; ++ friend class VM_EnhancedRedefineClasses; + inline static void increment_redefinition_count() { + JVMTI_ONLY(_redefinition_count++;) + } +diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +index 4918d90212f..1c7677f270f 100644 +--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +@@ -70,12 +70,19 @@ public: + + void do_klass(Klass* k) { + // Collect all jclasses +- _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); +- if (_dictionary_walk) { +- // Collect array classes this way when walking the dictionary (because array classes are +- // not in the dictionary). +- for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) { +- _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror()))); ++ // Collect all jclasses ++ // DCEVM : LoadedClassesClosure in dcevm7 iterates over classes from SystemDictionary therefore the class "k" is always ++ // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was ++ // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we ++ // must use new versions only. ++ if (k->new_version()==NULL) { ++ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); ++ if (_dictionary_walk) { ++ // Collect array classes this way when walking the dictionary (because array classes are ++ // not in the dictionary). ++ for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) { ++ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror()))); ++ } + } + } + } +diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp +index c22eb9a3dc8..a1ea25de1ea 100644 +--- a/src/hotspot/share/prims/jvmtiImpl.cpp ++++ b/src/hotspot/share/prims/jvmtiImpl.cpp +@@ -247,6 +247,11 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { + Symbol* m_name = _method->name(); + Symbol* m_signature = _method->signature(); + ++ // (DCEVM) Go through old versions of method ++ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { ++ (m->*meth_act)(_bci); ++ } ++ + // search previous versions if they exist + for (InstanceKlass* pv_node = ik->previous_versions(); + pv_node != NULL; +diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp +index 18307a4c6d8..6148bce5b9b 100644 +--- a/src/hotspot/share/runtime/arguments.cpp ++++ b/src/hotspot/share/runtime/arguments.cpp +@@ -2122,6 +2122,36 @@ unsigned int addopens_count = 0; + unsigned int addmods_count = 0; + unsigned int patch_mod_count = 0; + ++// Check consistency of GC selection ++bool Arguments::check_gc_consistency() { ++ // Ensure that the user has not selected conflicting sets ++ // of collectors. ++ uint i = 0; ++ if (UseSerialGC) i++; ++ if (UseConcMarkSweepGC) i++; ++ if (UseParallelGC || UseParallelOldGC) i++; ++ if (UseG1GC) i++; ++ if (AllowEnhancedClassRedefinition) { ++ // Must use serial GC. This limitation applies because the instance size changing GC modifications ++ // are only built into the mark and compact algorithm. ++ if (!UseSerialGC && i >= 1) { ++ jio_fprintf(defaultStream::error_stream(), ++ "Must use the serial GC with enhanced class redefinition\n"); ++ return false; ++ } ++ } ++ ++ if (i > 1) { ++ jio_fprintf(defaultStream::error_stream(), ++ "Conflicting collector combinations in option list; " ++ "please refer to the release notes for the combinations " ++ "allowed\n"); ++ return false; ++ } ++ ++ return true; ++} ++ + // Check the consistency of vm_init_args + bool Arguments::check_vm_args_consistency() { + // Method for adding checks for flag consistency. +@@ -2138,6 +2168,8 @@ bool Arguments::check_vm_args_consistency() { + status = false; + } + ++ status = status && check_gc_consistency(); ++ + if (PrintNMTStatistics) { + #if INCLUDE_NMT + if (MemTracker::tracking_level() == NMT_off) { +diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp +index c652ee3f9fe..9c656124d5b 100644 +--- a/src/hotspot/share/runtime/arguments.hpp ++++ b/src/hotspot/share/runtime/arguments.hpp +@@ -511,6 +511,7 @@ class Arguments : AllStatic { + static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized); + + static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; } ++ + // Return the maximum size a heap with compressed oops can take + static size_t max_heap_for_compressed_oops(); + +diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp +index 0fa47b34c40..de9193ca447 100644 +--- a/src/hotspot/share/runtime/globals.hpp ++++ b/src/hotspot/share/runtime/globals.hpp +@@ -2458,6 +2458,11 @@ const size_t minimumSymbolTableSize = 1024; + \ + diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \ + "Make nmethod barriers deoptimise a lot.") \ ++ \ ++ product(bool, AllowEnhancedClassRedefinition, true, \ ++ "Allow enhanced class redefinition beyond swapping method " \ ++ "bodies") ++ + + // Interface macros + #define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; +diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp +index 3793aaa8d75..9126dd7dffc 100644 +--- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp ++++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp +@@ -220,8 +220,8 @@ class ThreadToNativeFromVM : public ThreadStateTransition { + public: + ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) { + // We are leaving the VM at this point and going directly to native code. +- // Block, if we are in the middle of a safepoint synchronization. +- assert(!thread->owns_locks(), "must release all locks when leaving VM"); ++ // DCEVM allow locks on leaving JVM ++ assert(AllowEnhancedClassRedefinition || !thread->owns_locks(), "must release all locks when leaving VM"); + thread->frame_anchor()->make_walkable(thread); + trans(_thread_in_vm, _thread_in_native); + // Check for pending. async. exceptions or suspends. +diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp +index e08b1232777..a543935c995 100644 +--- a/src/hotspot/share/runtime/javaCalls.cpp ++++ b/src/hotspot/share/runtime/javaCalls.cpp +@@ -56,7 +56,8 @@ JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle recei + bool clear_pending_exception = true; + + guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code"); +- assert(!thread->owns_locks(), "must release all locks when leaving VM"); ++ // DCEVM allow locks on leaving JVM ++ assert(AllowEnhancedClassRedefinition || !thread->owns_locks(), "must release all locks when leaving VM"); + guarantee(thread->can_call_java(), "cannot make java calls from the native compiler"); + _result = result; + +diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp +index e45e8982768..6f982072909 100644 +--- a/src/hotspot/share/runtime/mutexLocker.cpp ++++ b/src/hotspot/share/runtime/mutexLocker.cpp +@@ -5,7 +5,7 @@ + * 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 +@@ -115,6 +115,7 @@ Mutex* FreeList_lock = NULL; + Mutex* OldSets_lock = NULL; + Monitor* RootRegionScan_lock = NULL; + ++Mutex* EnhancedRedefineClasses_lock = NULL; + Mutex* Management_lock = NULL; + Monitor* Service_lock = NULL; + Monitor* Notification_lock = NULL; +@@ -286,6 +287,7 @@ void mutex_init() { + def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never); + def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never); + def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); ++ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel + def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions + def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always); + +diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp +index 90b17b0c234..29d1b67d921 100644 +--- a/src/hotspot/share/runtime/mutexLocker.hpp ++++ b/src/hotspot/share/runtime/mutexLocker.hpp +@@ -106,6 +106,8 @@ extern Mutex* PerfDataMemAlloc_lock; // a lock on the allocator for + extern Mutex* PerfDataManager_lock; // a long on access to PerfDataManager resources + extern Mutex* OopMapCacheAlloc_lock; // protects allocation of oop_map caches + ++extern Mutex* EnhancedRedefineClasses_lock; // locks classes from parallel enhanced redefinition ++ + extern Mutex* FreeList_lock; // protects the free region list during safepoints + extern Mutex* OldSets_lock; // protects the old region sets + extern Monitor* RootRegionScan_lock; // used to notify that the CM threads have finished scanning the IM snapshot regions +diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp +index 02e7b1973fa..0e7722dba7d 100644 +--- a/src/hotspot/share/runtime/reflection.cpp ++++ b/src/hotspot/share/runtime/reflection.cpp +@@ -626,6 +626,12 @@ bool Reflection::verify_member_access(const Klass* current_class, + bool classloader_only, + bool protected_restriction, + TRAPS) { ++ ++ // (DCEVM) Decide accessibility based on active version ++ if (current_class != NULL) { ++ current_class = current_class->active_version(); ++ } ++ + // Verify that current_class can access a member of member_class, where that + // field's access bits are "access". We assume that we've already verified + // that current_class can access member_class. +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch b/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch new file mode 100644 index 000000000000..5415fe6897f3 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch @@ -0,0 +1,1569 @@ +From 356238c4099e3dfb6cd15d4ee4cf25f030bb2ca3 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Wed, 14 Nov 2018 21:18:22 +0100 +Subject: [PATCH 02/34] dcevm11 fixes + +1. We need to set classRedefinitionCount on new class, not old class. + +2.Fix crashes in MetadataOnStackMark::~MetadataOnSta + +MetadataOnStackMark should not remove dcevm stuff. It was added +accidentaly in dcevm9 and never was part of doit() in previous versions. + +3. Fix problem with nested members + +Reported at : +https://stackoverflow.com/questions/53370380/hotswapagent-incompatibleclasschangeerror-type-headerpanel1-is-not-a-nest-mem + +4. Use init_mark_raw() + +method changed since j8 - it used init_mark() + +5. Fix methodHandles and fieldHandles + +6. Code cleanup + +7. Fix force_forward in dead space + +8. Fix check_class + +9. increment_class_counter() using orig dcevm code + +Probably it is cause of SISEGV on: +_ +VM_EnhancedRedefineClasses::redefine_single_class->java_mirror() + +10 Fix 11.0.7 compilation issues + +11. Refactor ClearCpoolCacheAndUnpatch + +12. not nullable oop_store_not_null() method+handle NULL in mem_name in +dmh + +13. Use INCLUDE_CDS condition on "UseSharedSpaces" block from master + +14. Add codecache flush optimization, but just flush all cache. + +15. Cleanup + +16. Use original code for adjust_method_entries in standard redefinition + +17. iterate old method version only in dcevm + +18. Revert code for !AllowEnhancedClassRedefinition + +19. Code cleanup + +20. Activate cpCache definition asserts for !dcevm + +21. Skip GC runs for redefinitions without instance size change + +22. This is the 2nd commit message: +--- + .../share/classfile/classFileParser.cpp | 4 +- + .../share/classfile/classFileParser.hpp | 2 +- + .../share/classfile/classLoaderDataGraph.cpp | 2 + + src/hotspot/share/classfile/dictionary.cpp | 4 + + src/hotspot/share/classfile/dictionary.hpp | 1 + + .../share/classfile/loaderConstraints.cpp | 3 +- + .../share/classfile/systemDictionary.cpp | 8 +- + src/hotspot/share/gc/shared/space.cpp | 2 +- + src/hotspot/share/gc/shared/space.inline.hpp | 3 +- + .../share/interpreter/linkResolver.cpp | 1 + + src/hotspot/share/memory/universe.cpp | 4 +- + src/hotspot/share/oops/cpCache.cpp | 3 +- + src/hotspot/share/oops/instanceKlass.cpp | 22 +- + src/hotspot/share/oops/instanceKlass.hpp | 1 + + .../prims/jvmtiEnhancedRedefineClasses.cpp | 537 +++++++----------- + .../prims/jvmtiEnhancedRedefineClasses.hpp | 63 +- + src/hotspot/share/prims/jvmtiImpl.cpp | 6 +- + .../share/prims/resolvedMethodTable.cpp | 63 ++ + .../share/prims/resolvedMethodTable.hpp | 1 + + 19 files changed, 329 insertions(+), 401 deletions(-) + +diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp +index 0192e9e006f..6b54b1d63eb 100644 +--- a/src/hotspot/share/classfile/classFileParser.cpp ++++ b/src/hotspot/share/classfile/classFileParser.cpp +@@ -964,6 +964,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, + CHECK); + } + ++ // (DCEVM) pick newest + interf = (Klass *) maybe_newest(interf); + + if (!interf->is_interface()) { +@@ -4014,6 +4015,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, + // However, make sure it is not an array type. + bool is_array = false; + if (cp->tag_at(super_class_index).is_klass()) { ++ // (DCEVM) pick newest + super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index))); + if (need_verify) + is_array = super_klass->is_array_klass(); +@@ -4617,7 +4619,7 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { + if (!_has_empty_finalizer) { + if (_has_finalizer || + (super != NULL && super->has_finalizer())) { +- // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active ++ // FIXME - (DCEVM) this is condition from previous DCEVM version, however after reload a new finalize() method is not active + if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) { + ik->set_has_finalizer(); + } +diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp +index 6660616ccad..e5761e61767 100644 +--- a/src/hotspot/share/classfile/classFileParser.hpp ++++ b/src/hotspot/share/classfile/classFileParser.hpp +@@ -544,7 +544,7 @@ class ClassFileParser { + TRAPS); + + void update_class_name(Symbol* new_name); +- // Enhanced class redefinition ++ // (DCEVM) Enhanced class redefinition + inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; } + + public: +diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp +index db0fbcc45dc..53f6b78c380 100644 +--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp ++++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp +@@ -439,12 +439,14 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), + } + } + ++// (DCEVM) - iterate over dict classes + void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) { + FOR_ALL_DICTIONARY(cld) { + cld->dictionary()->classes_do(klass_closure); + } + } + ++// (DCEVM) rollback redefined classes + void ClassLoaderDataGraph::rollback_redefinition() { + FOR_ALL_DICTIONARY(cld) { + cld->dictionary()->rollback_redefinition(); +diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp +index 45c979a1738..55fbcf85f73 100644 +--- a/src/hotspot/share/classfile/dictionary.cpp ++++ b/src/hotspot/share/classfile/dictionary.cpp +@@ -216,6 +216,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) { + } + } + ++ ++// (DCEVM) iterate over dict entry + void Dictionary::classes_do(KlassClosure* closure) { + for (int index = 0; index < table_size(); index++) { + for (DictionaryEntry* probe = bucket(index); +@@ -310,6 +312,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, + return NULL; + } + ++// (DCEVM) replace old_class by new class in dictionary + bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) { + // There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class. + bool found = false; +@@ -324,6 +327,7 @@ bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* + return found; + } + ++// (DCEVM) rollback redefinition + void Dictionary::rollback_redefinition() { + for (int index = 0; index < table_size(); index++) { + for (DictionaryEntry* entry = bucket(index); +diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp +index b4f5cd5c4df..114a983e783 100644 +--- a/src/hotspot/share/classfile/dictionary.hpp ++++ b/src/hotspot/share/classfile/dictionary.hpp +@@ -111,6 +111,7 @@ public: + + void rollback_redefinition(); + ++ // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k" + static InstanceKlass* old_if_redefined(InstanceKlass* k) { + return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; + } +diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp +index fd1bd46b8bd..2c6a729fa19 100644 +--- a/src/hotspot/share/classfile/loaderConstraints.cpp ++++ b/src/hotspot/share/classfile/loaderConstraints.cpp +@@ -4,7 +4,7 @@ + * + * 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. ++ * published by the Free Software Foundation) replace old_class by new class in dictionary. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +@@ -91,6 +91,7 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( + return pp; + } + ++// (DCEVM) update constraint entries to new classes, called from dcevm redefinition code only + void LoaderConstraintTable::update_after_redefinition() { + for (int index = 0; index < table_size(); index++) { + LoaderConstraintEntry** p = bucket_addr(index); +diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp +index e6b25e90f18..bd0cae7cb9b 100644 +--- a/src/hotspot/share/classfile/systemDictionary.cpp ++++ b/src/hotspot/share/classfile/systemDictionary.cpp +@@ -967,7 +967,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, + ClassLoaderData* loader_data = k->class_loader_data(); + MutexLocker mu(THREAD, SystemDictionary_lock); + InstanceKlass* kk = find_class(name, loader_data); +- // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) ++ // FIXME: (DCEVM) ++ // assert(kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) + assert(kk == k, "should be present in dictionary"); + } + #endif +@@ -1178,7 +1179,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + InstanceKlass* k = NULL; + + #if INCLUDE_CDS +- // FIXME: what to do during redefinition? ++ // FIXME: (DCEVM) what to do during redefinition? + if (!DumpSharedSpaces) { + k = SystemDictionaryShared::lookup_from_stream(class_name, + class_loader, +@@ -1989,7 +1990,7 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { + } + } + +-// Enhanced class redefinition ++// (DCEVM) - remove from klass hierarchy + void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { + assert(k != NULL, "just checking"); + +@@ -1997,6 +1998,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { + k->remove_from_sibling_list(); + } + ++// (DCEVM) + void SystemDictionary::update_constraints_after_redefinition() { + constraints()->update_after_redefinition(); + } +diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp +index 0fefc5da478..875a6dc854f 100644 +--- a/src/hotspot/share/gc/shared/space.cpp ++++ b/src/hotspot/share/gc/shared/space.cpp +@@ -828,7 +828,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, + size_t forward_size = size; + + // (DCEVM) There is a new version of the class of q => different size +- if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) { ++ if (oop(q)->klass()->new_version() != NULL) { + + size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); + assert(size != new_size, "instances without changed size have to be updated prior to GC run"); +diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp +index 8e3722b01b1..875c3fdf319 100644 +--- a/src/hotspot/share/gc/shared/space.inline.hpp ++++ b/src/hotspot/share/gc/shared/space.inline.hpp +@@ -209,6 +209,7 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + // see if this is the first dead region. + if (first_dead == NULL) { + first_dead = cur_obj; ++ force_forward = true; + } + } + +@@ -370,7 +371,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti + } else { + MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); + } +- oop(compaction_top)->init_mark(); ++ oop(compaction_top)->init_mark_raw(); + assert(oop(compaction_top)->klass() != NULL, "should have a class"); + + debug_only(prev_obj = cur_obj); +diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp +index ed15db841c6..3425e3f893d 100644 +--- a/src/hotspot/share/interpreter/linkResolver.cpp ++++ b/src/hotspot/share/interpreter/linkResolver.cpp +@@ -1400,6 +1400,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, + assert(resolved_method->can_be_statically_bound(), "cannot override this method"); + selected_method = resolved_method; + } else { ++ // TODO: (DCEVM) explain + assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent"); + selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); + } +diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp +index 1f3f746b2b7..d38cd348e1b 100644 +--- a/src/hotspot/share/memory/universe.cpp ++++ b/src/hotspot/share/memory/universe.cpp +@@ -178,7 +178,7 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { + #define DO_PRIMITIVE_MIRROR(m) \ + f->do_oop((oop*) &m); + +-// FIXME: This method should iterate all pointers that are not within heap objects. ++// FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects. + void Universe::root_oops_do(OopClosure *oopClosure) { + + class AlwaysTrueClosure: public BoolObjectClosure { +@@ -205,7 +205,7 @@ void Universe::root_oops_do(OopClosure *oopClosure) { + CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); + CodeCache::blobs_do(&blobClosure); + StringTable::oops_do(oopClosure); +- ++ + // (DCEVM) TODO: Check if this is correct? + //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); + //Management::oops_do(oopClosure); +diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp +index ac1c7d397e8..79a38dbeff0 100644 +--- a/src/hotspot/share/oops/cpCache.cpp ++++ b/src/hotspot/share/oops/cpCache.cpp +@@ -450,8 +450,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& + if (has_appendix) { + const int appendix_index = f2_as_index(); + assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); +- // FIXME (DCEVM) relaxing for now... +- //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); ++ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(appendix_index) == NULL, "init just once"); + resolved_references->obj_at_put(appendix_index, appendix()); + } + +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index 51bee899aa9..994fc8a3bc8 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -199,6 +199,7 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { + // able to perform that loading but we can't exclude the compiler threads from + // executing this logic. But it should actually be impossible to trigger loading here. + Klass* k2 = _constants->klass_at(cp_index, THREAD); ++ k2 = k2->newest_version(); + assert(!HAS_PENDING_EXCEPTION || PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass()), + "Exceptions should not be possible here"); + if (k2 == k) { +@@ -1307,6 +1308,15 @@ void InstanceKlass::init_implementor() { + } + } + ++// (DCEVM) - init_implementor() for dcevm ++void InstanceKlass::init_implementor_from_redefine() { ++ assert(is_interface(), "not interface"); ++ Klass** addr = adr_implementor(); ++ assert(addr != NULL, "null addr"); ++ if (addr != NULL) { ++ *addr = NULL; ++ } ++} + + void InstanceKlass::process_interfaces(Thread *thread) { + // link this class into the implementors list of every interface it implements +@@ -1364,6 +1374,8 @@ bool InstanceKlass::implements_interface(Klass* k) const { + return false; + } + ++ ++// (DCEVM) + bool InstanceKlass::implements_interface_any_version(Klass* k) const { + k = k->newest_version(); + if (this->newest_version() == k) return true; +@@ -1642,10 +1654,8 @@ void InstanceKlass::methods_do(void f(Method* method)) { + } + } + +-/** +- Update information contains mapping of fields from old class to the new class. +- Info is stored on HEAP, you need to call clear_update_information to free the space. +-*/ ++// (DCEVM) Update information contains mapping of fields from old class to the new class. ++// Info is stored on HEAP, you need to call clear_update_information to free the space. + void InstanceKlass::store_update_information(GrowableArray &values) { + int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass); + for (int i = 0; i < values.length(); i++) { +@@ -2341,7 +2351,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { + + void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { + dependencies().remove_dependent_nmethod(nm); +- // (DCEVM) Hack as dependencies get wrong version of Klass* ++ // FIXME: (DCEVM) Hack as dependencies get wrong version of Klass* + // if (this->old_version() != NULL) { + // InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true); + // return; +@@ -2352,6 +2362,7 @@ void InstanceKlass::clean_dependency_context() { + dependencies().clean_unloading_dependents(); + } + ++// DCEVM - update jmethod ids + bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) { + size_t idnum = (size_t)method->method_idnum(); + jmethodID* jmeths = methods_jmethod_ids_acquire(); +@@ -3767,6 +3778,7 @@ void InstanceKlass::verify_on(outputStream* st) { + } + + guarantee(sib->is_klass(), "should be klass"); ++ // TODO: (DCEVM) explain + guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); + } + +diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp +index aa3d38d95e0..6ead9426728 100644 +--- a/src/hotspot/share/oops/instanceKlass.hpp ++++ b/src/hotspot/share/oops/instanceKlass.hpp +@@ -1045,6 +1045,7 @@ public: + int nof_implementors() const; + void add_implementor(Klass* k); // k is a new class that implements this interface + void init_implementor(); // initialize ++ void init_implementor_from_redefine(); // initialize + + // link this class into the implementors list of every interface it implements + void process_interfaces(Thread *thread); +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 83c0952de37..92ce6c27b8a 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -1,4 +1,4 @@ +-/* ++ /* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * +@@ -28,6 +28,7 @@ + #include "classfile/metadataOnStackMark.hpp" + #include "classfile/systemDictionary.hpp" + #include "classfile/verifier.hpp" ++#include "classfile/dictionary.hpp" + #include "interpreter/oopMapCache.hpp" + #include "interpreter/rewriter.hpp" + #include "logging/logStream.hpp" +@@ -35,7 +36,7 @@ + #include "memory/metaspaceShared.hpp" + #include "memory/resourceArea.hpp" + #include "memory/iterator.inline.hpp" +-#include "gc/serial/markSweep.hpp" // FIXME: other GC? ++#include "gc/serial/markSweep.hpp" + #include "oops/fieldStreams.hpp" + #include "oops/klassVtable.hpp" + #include "oops/oop.inline.hpp" +@@ -48,6 +49,7 @@ + #include "runtime/deoptimization.hpp" + #include "runtime/jniHandles.inline.hpp" + #include "runtime/relocator.hpp" ++#include "runtime/fieldDescriptor.inline.hpp" + #include "utilities/bitMap.inline.hpp" + #include "prims/jvmtiThreadState.inline.hpp" + #include "utilities/events.hpp" +@@ -64,21 +66,19 @@ int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; + int VM_EnhancedRedefineClasses::_added_methods_length = 0; + Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; + +-/** +- * Create new instance of enhanced class redefiner. +- * +- * This class implements VM_GC_Operation - the usual usage should be: +- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); +- * VMThread::execute(&op); +- * Which +- * +- * @param class_count size of class_defs +- * @param class_defs class definition - either new class or redefined class +- * note that this is not the final array of classes to be redefined +- * we need to scan for all affected classes (e.g. subclasses) and +- * caculcate redefinition for them as well. +- * @param class_load_kind always jvmti_class_load_kind_redefine +- */ ++// ++// Create new instance of enhanced class redefiner. ++// ++// This class implements VM_GC_Operation - the usual usage should be: ++// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++// VMThread::execute(&op); ++// Which ++// - class_count size of class_defs ++// - class_defs class definition - either new class or redefined class ++// note that this is not the final array of classes to be redefined ++// we need to scan for all affected classes (e.g. subclasses) and ++// caculcate redefinition for them as well. ++// @param class_load_kind always jvmti_class_load_kind_redefine + VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : + VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { + _affected_klasses = NULL; +@@ -94,12 +94,10 @@ static inline InstanceKlass* get_ik(jclass def) { + return InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); + } + +-/** +- * Start the redefinition: +- * - Load new class definitions - @see load_new_class_versions +- * - Start mark&sweep GC. +- * @return true if success, otherwise all chnages are rollbacked. +- */ ++// Start the redefinition: ++// - Load new class definitions - @see load_new_class_versions ++// - Start mark&sweep GC. ++// - true if success, otherwise all chnages are rollbacked. + bool VM_EnhancedRedefineClasses::doit_prologue() { + + if (_class_count == 0) { +@@ -172,9 +170,7 @@ bool VM_EnhancedRedefineClasses::doit_prologue() { + return true; + } + +-/** +- * Closer for static fields - copy value from old class to the new class. +- */ ++// Closer for static fields - copy value from old class to the new class. + class FieldCopier : public FieldClosure { + public: + void do_field(fieldDescriptor* fd) { +@@ -222,18 +218,18 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { + // TODO comment + struct StoreBarrier { + // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store +- template static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); } ++ template static void oop_store_not_null(T* p, oop v) { HeapAccess::oop_store(p, v); } ++ template static void oop_store(T* p) { HeapAccess<>::oop_store(p, oop(NULL)); } + }; + + + // TODO comment + struct StoreNoBarrier { +- template static void oop_store(T* p, oop v) { RawAccess::oop_store(p, v); } ++ template static void oop_store_not_null(T* p, oop v) { RawAccess::oop_store(p, v); } ++ template static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); } + }; + +-/** +- Closure to scan all heap objects and update method handles +-*/ ++// Closure to scan all heap objects and update method handles + template + class ChangePointersOopClosure : public BasicOopIterateClosure { + // import java_lang_invoke_MemberName.* +@@ -242,13 +238,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK, + }; + +- + bool update_member_name(oop obj) { + int flags = java_lang_invoke_MemberName::flags(obj); + int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; + if (MethodHandles::ref_kind_is_method(ref_kind)) { + Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj); +- if (m != NULL && m->method_holder()->new_version() != NULL) { ++ if (m != NULL && m->method_holder()->is_redefining()) { + // Let's try to re-resolve method + InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version()); + Method* new_method = newest->find_method(m->name(), m->signature()); +@@ -257,29 +252,34 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + // Note: we might set NULL at this point, which should force AbstractMethodError at runtime + Thread *thread = Thread::current(); + CallInfo info(new_method, newest, thread); +- Handle objHandle(thread, obj); // TODO : review thread ++ Handle objHandle(thread, obj); + MethodHandles::init_method_MemberName(objHandle, info); + } else { + java_lang_invoke_MemberName::set_method(obj, NULL); + } + } + } else if (MethodHandles::ref_kind_is_field(ref_kind)) { +- Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj); ++ oop clazz = java_lang_invoke_MemberName::clazz(obj); ++ if (clazz == NULL) { ++ return false; ++ } ++ Klass* k = java_lang_Class::as_Klass(clazz); + if (k == NULL) { + return false; // Was cleared before, this MemberName is invalid. + } + +- if (k != NULL && k->new_version() != NULL) { ++ if (k->is_redefining()) { + // Let's try to re-resolve field ++ InstanceKlass* old = InstanceKlass::cast(k->old_version()); + fieldDescriptor fd; + int offset = java_lang_invoke_MemberName::vmindex(obj); + bool is_static = MethodHandles::ref_kind_is_static(ref_kind); +- InstanceKlass* ik = InstanceKlass::cast(k); +- if (ik->find_local_field_from_offset(offset, is_static, &fd)) { +- InstanceKlass* newest = InstanceKlass::cast(k->newest_version()); ++ InstanceKlass* ik_old = InstanceKlass::cast(old); ++ if (ik_old->find_local_field_from_offset(offset, is_static, &fd)) { ++ InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version()); + fieldDescriptor fd_new; +- if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) { +- Handle objHandle(Thread::current(), obj); // TODO : review thread ++ if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) { ++ Handle objHandle(Thread::current(), obj); + MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind)); + } else { + // Matching field is not found in new version, not much we can do here. +@@ -288,7 +288,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + // Eventually, we probably want to replace them with something more meaningful, + // like instance throwing NoSuchFieldError or DMH that will resort to dynamic + // field resolution (with possibility of type conversion) +- java_lang_invoke_MemberName::set_method(obj, NULL); ++ java_lang_invoke_MemberName::set_clazz(obj, NULL); + java_lang_invoke_MemberName::set_vmindex(obj, 0); + return false; + } +@@ -301,6 +301,9 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + bool update_direct_method_handle(oop obj) { + // Always update member name first. + oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj); ++ if (mem_name == NULL) { ++ return true; ++ } + if (!update_member_name(mem_name)) { + return false; + } +@@ -332,25 +335,30 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + if (obj == NULL) { + return; + } ++ bool oop_updated = false; + if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { + Klass* klass = java_lang_Class::as_Klass(obj); + if (klass != NULL && klass->is_instance_klass()) { + assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking"); + if (klass->new_version() != NULL) { + obj = InstanceKlass::cast(klass->new_version())->java_mirror(); +- S::oop_store(p, obj); ++ S::oop_store_not_null(p, obj); ++ oop_updated = true; + } + } + } + ++ + // JSR 292 support, uptade java.lang.invoke.MemberName instances + if (java_lang_invoke_MemberName::is_instance(obj)) { +- update_member_name(obj); ++ if (oop_updated) { ++ update_member_name(obj); ++ } + } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) { + if (!update_direct_method_handle(obj)) { + // DMH is no longer valid, replace it with null reference. + // See note above. We probably want to replace this with something more meaningful. +- S::oop_store(p, NULL); ++ S::oop_store(p); + } + } + } +@@ -364,14 +372,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { + } + }; + +-/** +- * Closure to scan all objects on heap for objects of changed classes +- * - if the fields are compatible, only update class definition reference +- * - otherwise if the new object size is smaller then old size, reshufle +- * the fields and fill the gap with "dead_space" +- * - otherwise set the _needs_instance_update flag, we need to do full GC +- * and reshuffle object positions durring mark&sweep +- */ ++// Closure to scan all objects on heap for objects of changed classes ++// - if the fields are compatible, only update class definition reference ++// - otherwise if the new object size is smaller then old size, reshufle ++// the fields and fill the gap with "dead_space" ++// - otherwise set the _needs_instance_update flag, we need to do full GC ++// and reshuffle object positions durring mark&sweep + class ChangePointersObjectClosure : public ObjectClosure { + private: + +@@ -440,22 +446,19 @@ public: + }; + + +-/** +- Main transformation method - runs in VM thread. +- +- - UseSharedSpaces - TODO what does it mean? +- - for each sratch class call redefine_single_class +- - clear code cache (flush_dependent_code) +- - iterate the heap and update object defintions, check it old/new class fields +- are compatible. If new class size is smaller then old, it can be solved directly here. +- - iterate the heap and update method handles to new version +- - Swap marks to have same hashcodes +- - copy static fields +- - notify JVM of the modification +-*/ ++// Main transformation method - runs in VM thread. ++// - for each scratch class call redefine_single_class ++// - clear code cache (flush_dependent_code) ++// - iterate the heap and update object definitions, check it old/new class fields ++// are compatible. If new class size is smaller then old, it can be solved directly here. ++// - iterate the heap and update method handles to new version ++// - Swap marks to have same hashcodes ++// - copy static fields ++// - notify JVM of the modification + void VM_EnhancedRedefineClasses::doit() { + Thread *thread = Thread::current(); + ++#if INCLUDE_CDS + if (UseSharedSpaces) { + // Sharing is enabled so we remap the shared readonly space to + // shared readwrite, private just in case we need to redefine +@@ -467,10 +470,13 @@ void VM_EnhancedRedefineClasses::doit() { + return; + } + } ++#endif + + // Mark methods seen on stack and everywhere else so old methods are not + // cleaned up if they're on the stack. +- MetadataOnStackMark md_on_stack(true); ++ ++ // FIXME: fails in enhanced redefinition ++ // MetadataOnStackMark md_on_stack(true); + HandleMark hm(thread); // make sure any handles created are deleted + // before the stack walk again. + +@@ -479,12 +485,19 @@ void VM_EnhancedRedefineClasses::doit() { + } + + // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) +- flush_dependent_code(NULL, thread); ++ // if (_max_redefinition_flags > Klass::ModifyClass) { ++ flush_dependent_code(NULL, thread); ++ // } ++ ++ // Adjust constantpool caches for all classes that reference methods of the evolved class. ++ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); ++ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); ++ + + // JSR-292 support + if (_any_class_has_resolved_methods) { + bool trace_name_printed = false; +- ResolvedMethodTable::adjust_method_entries(&trace_name_printed); ++ ResolvedMethodTable::adjust_method_entries_dcevm(&trace_name_printed); + } + + ChangePointersOopClosure oopClosureNoBarrier; +@@ -554,14 +567,14 @@ void VM_EnhancedRedefineClasses::doit() { + } + } + +-// if (objectClosure.needs_instance_update()) { ++ if (objectClosure.needs_instance_update()) { + // Do a full garbage collection to update the instance sizes accordingly + Universe::set_redefining_gc_run(true); + notify_gc_begin(true); + Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); + notify_gc_end(); + Universe::set_redefining_gc_run(false); +-// } ++ } + + // Unmark Klass*s as "redefining" + for (int i = 0; i < _new_classes->length(); i++) { +@@ -587,24 +600,32 @@ void VM_EnhancedRedefineClasses::doit() { + // See jvmtiExport.hpp for detailed explanation. + JvmtiExport::set_has_redefined_a_class(); + +- // check_class() is optionally called for product bits, but is +- // always called for non-product bits. + #ifdef PRODUCT + if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { + #endif +- log_trace(redefine, class, obsolete, metadata)("calling check_class"); +- CheckClass check_class(thread); +- ClassLoaderDataGraph::classes_do(&check_class); ++ for (int i=0; i<_affected_klasses->length(); i++) { ++ Klass* the_class = _affected_klasses->at(i); ++ assert(the_class->new_version() != NULL, "Must have been redefined"); ++ Klass* new_version = the_class->new_version(); ++ assert(new_version->new_version() == NULL, "Must be newest version"); ++ ++ if (!(new_version->super() == NULL || new_version->super()->new_version() == NULL)) { ++ new_version->print(); ++ new_version->super()->print(); ++ } ++ assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version"); ++ } ++ log_trace(redefine, class, obsolete, metadata)("calling check_class"); ++ ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do(check_class, thread); + #ifdef PRODUCT + } + #endif ++ + } + +-/** +- * Cleanup - runs in JVM thread +- * - free used memory +- * - end GC +- */ ++// Cleanup - runs in JVM thread ++// - free used memory ++// - end GC + void VM_EnhancedRedefineClasses::doit_epilogue() { + VM_GC_Operation::doit_epilogue(); + +@@ -636,11 +657,9 @@ void VM_EnhancedRedefineClasses::doit_epilogue() { + } + } + +-/** +- * Exclude java primitives and arrays from redefinition +- * @param klass_mirror pointer to the klass +- * @return true if is modifiable +- */ ++// Exclude java primitives and arrays from redefinition ++// - klass_mirror pointer to the klass ++// - true if is modifiable + bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { + // classes for primitives cannot be redefined + if (java_lang_Class::is_primitive(klass_mirror)) { +@@ -659,17 +678,12 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { + return true; + } + +-/** +- Load and link new classes (either redefined or affected by redefinition - subclass, ...) +- +- - find sorted affected classes +- - resolve new class +- - calculate redefine flags (field change, method change, supertype change, ...) +- - calculate modified fields and mapping to old fields +- - link new classes +- +- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. +-*/ ++// Load and link new classes (either redefined or affected by redefinition - subclass, ...) ++// - find sorted affected classes ++// - resolve new class ++// - calculate redefine flags (field change, method change, supertype change, ...) ++// - calculate modified fields and mapping to old fields ++// - link new classes + jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + + _affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); +@@ -842,9 +856,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + return JVMTI_ERROR_NONE; + } + +-/** +- Calculated the difference between new and old class (field change, method change, supertype change, ...). +-*/ ++ // Calculated the difference between new and old class (field change, method change, supertype change, ...). + int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { + int result = Klass::NoRedefinition; + log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); +@@ -1127,14 +1139,11 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ + } + + +-/** +- Searches for the class bytecode of the given class and returns it as a byte array. +- +- @param the_class definition of a class, either existing class or new_class +- @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. +- @param class_byte_count - size of class_bytes +- @param not_changed - new_class not available or same as current class +-*/ ++// Searches for the class bytecode of the given class and returns it as a byte array. ++// - the_class definition of a class, either existing class or new_class ++// - class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. ++// - class_byte_count - size of class_bytes ++// - not_changed - new_class not available or same as current class + jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) { + + *not_changed = false; +@@ -1177,11 +1186,9 @@ jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class + return JVMTI_ERROR_NONE; + } + +-/** +- Calculate difference between non static fields of old and new class and store the info into new class: +- instanceKlass->store_update_information +- instanceKlass->copy_backwards +-*/ ++// Calculate difference between non static fields of old and new class and store the info into new class: ++// instanceKlass->store_update_information ++// instanceKlass->copy_backwards + void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) { + + class CalculateFieldUpdates : public FieldClosure { +@@ -1273,29 +1280,26 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne + GrowableArray result = cl.finish(); + ik->store_update_information(result); + ik->set_copying_backwards(cl.does_copy_backwards()); +-/* TODO logging +- if (RC_TRACE_ENABLED(0x00000001)) { +- RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string())); ++ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { ++ log_trace(redefine, class, obsolete, metadata)("Instance update information for %s:", new_version->name()->as_C_string()); + if (cl.does_copy_backwards()) { +- RC_TRACE(0x00000001, ("\tDoes copy backwards!")); ++ log_trace(redefine, class, obsolete, metadata)("\tDoes copy backwards!"); + } + for (int i=0; i 0) { +- RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1))); ++ log_trace(redefine, class, obsolete, metadata)("\t%d COPY from %d", curNum, result.at(i + 1)); + i++; + } else { +- RC_TRACE(0x00000001, ("\tEND")); ++ log_trace(redefine, class, obsolete, metadata)("\tEND"); + } + } +- }*/ ++ } + } + +-/** +- Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. +-*/ ++// Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. + void VM_EnhancedRedefineClasses::rollback() { + log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); + ClassLoaderDataGraph::rollback_redefinition(); +@@ -1364,92 +1368,41 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { + } + } + +-// Unevolving classes may point to methods of the_class directly ++// Unevolving classes may point to old methods directly + // from their constant pool caches, itables, and/or vtables. We +-// use the ClassLoaderDataGraph::classes_do() facility and this helper +-// to fix up these pointers. +-// Adjust cpools and vtables closure ++// use the SystemDictionary::classes_do() facility and this helper ++// to fix up these pointers. Additional field offsets and vtable indices ++// in the constant pool cache entries are fixed. ++// ++// Note: We currently don't support updating the vtable in ++// arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. + void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { +- // This is a very busy routine. We don't want too much tracing +- // printed out. +- bool trace_name_printed = false; +- InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop); +- +- // If the class being redefined is java.lang.Object, we need to fix all +- // array class vtables also +- if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { +- k->vtable().adjust_method_entries(the_class, &trace_name_printed); +- } else if (k->is_instance_klass()) { +- HandleMark hm(_thread); +- InstanceKlass *ik = InstanceKlass::cast(k); ++ if (!k->is_instance_klass()) { ++ return; ++ } + +- // HotSpot specific optimization! HotSpot does not currently +- // support delegation from the bootstrap class loader to a +- // user-defined class loader. This means that if the bootstrap +- // class loader is the initiating class loader, then it will also +- // be the defining class loader. This also means that classes +- // loaded by the bootstrap class loader cannot refer to classes +- // loaded by a user-defined class loader. Note: a user-defined +- // class loader can delegate to the bootstrap class loader. +- // +- // If the current class being redefined has a user-defined class +- // loader as its defining class loader, then we can skip all +- // classes loaded by the bootstrap class loader. +- bool is_user_defined = +- InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; +- if (is_user_defined && ik->class_loader() == NULL) { +- return; +- } +- +- // Fix the vtable embedded in the_class and subclasses of the_class, +- // if one exists. We discard scratch_class and we don't keep an +- // InstanceKlass around to hold obsolete methods so we don't have +- // any other InstanceKlass embedded vtables to update. The vtable +- // holds the Method*s for virtual (but not final) methods. +- // Default methods, or concrete methods in interfaces are stored +- // in the vtable, so if an interface changes we need to check +- // adjust_method_entries() for every InstanceKlass, which will also +- // adjust the default method vtable indices. +- // We also need to adjust any default method entries that are +- // not yet in the vtable, because the vtable setup is in progress. +- // This must be done after we adjust the default_methods and +- // default_vtable_indices for methods already in the vtable. +- // If redefining Unsafe, walk all the vtables looking for entries. +-// FIXME - code from standard redefine - if needed, it should switch to new_class +-// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() +-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() +-// || ik->is_subtype_of(_the_class_oop))) { +-// // ik->vtable() creates a wrapper object; rm cleans it up +-// ResourceMark rm(_thread); +-// +-// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed); +-// ik->adjust_default_methods(the_class, &trace_name_printed); +-// } +- +- // If the current class has an itable and we are either redefining an +- // interface or if the current class is a subclass of the_class, then +- // we potentially have to fix the itable. If we are redefining an +- // interface, then we have to call adjust_method_entries() for +- // every InstanceKlass that has an itable since there isn't a +- // subclass relationship between an interface and an InstanceKlass. +- // If redefining Unsafe, walk all the itables looking for entries. +-// FIXME - code from standard redefine - if needed, it should switch to new_class +-// if (ik->itable_length() > 0 && (_the_class_oop->is_interface() +-// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() +-// || ik->is_subclass_of(_the_class_oop))) { +-// // ik->itable() creates a wrapper object; rm cleans it up +-// ResourceMark rm(_thread); +-// +-// ik->itable()->adjust_method_entries(the_class, &trace_name_printed); +-// } +- +- constantPoolHandle other_cp = constantPoolHandle(ik->constants()); ++ HandleMark hm(_thread); ++ InstanceKlass *ik = InstanceKlass::cast(k); ++ ++ constantPoolHandle other_cp = constantPoolHandle(ik->constants()); + + // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. + if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { + ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); + } + ++ // Update implementor if there is only one, in this case implementor() can reference old class ++ if (ik->is_interface()) { ++ Klass* implKlass = ik->implementor(); ++ if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) { ++ InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version()); ++ ik->init_implementor_from_redefine(); ++ if (newest_impl->implements_interface(ik)) { ++ ik->add_implementor(newest_impl); ++ } ++ } ++ } ++ + for (int i = 0; i < other_cp->length(); i++) { + if (other_cp->tag_at(i).is_klass()) { + Klass* klass = other_cp->resolved_klass_at(i); +@@ -1457,8 +1410,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + // Constant pool entry points to redefined class -- update to the new version + other_cp->klass_at_put(i, klass->newest_version()); + } +- klass = other_cp->resolved_klass_at(i); +- assert(klass->new_version() == NULL, "Must be new klass!"); ++ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); + } + } + +@@ -1472,7 +1424,6 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + if (RewriteBytecodes) { + ik->methods_do(unpatch_bytecode); + } +- } + } + + // Clean method data for this class +@@ -1519,9 +1470,7 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() { + } + } + +-/** +- Set method as obsolete / old / deleted. +-*/ ++// Set method as obsolete / old / deleted. + void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() { + for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) { + Method* old_method = _matching_old_methods[j]; +@@ -1718,8 +1667,14 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) + // All dependencies have been recorded from startup or this is a second or + // subsequent use of RedefineClasses + // FIXME: for now, deoptimize all! +- if (0 && JvmtiExport::all_dependencies_are_recorded()) { ++ if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) { + CodeCache::flush_evol_dependents_on(k_h); ++ Klass* superCl = k_h->super(); ++ // Deoptimize super classes since redefined class can has a new method override ++ while (superCl != NULL && !superCl->is_redefining()) { ++ CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl)); ++ superCl = superCl->super(); ++ } + } else { + CodeCache::mark_all_nmethods_for_deoptimization(); + +@@ -1737,12 +1692,9 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) + } + } + +-/** +- Compare _old_methods and _new_methods arrays and store the result into +- _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods +- +- Setup _old_methods and _new_methods before the call - it should be called for one class only! +-*/ ++// Compare _old_methods and _new_methods arrays and store the result into ++// _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods ++// Setup _old_methods and _new_methods before the call - it should be called for one class only! + void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { + Method* old_method; + Method* new_method; +@@ -1804,19 +1756,6 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { + assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity"); + } + +-/** +- FIXME - swap_annotations is never called, check that annotations work +-*/ +-void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class, +- InstanceKlass* new_class) { +- // FIXME - probably original implementation only +- // Swap annotation fields values +- Annotations* old_annotations = the_class->annotations(); +- the_class->set_annotations(new_class->annotations()); +- new_class->set_annotations(old_annotations); +-} +- +- + // Install the redefinition of a class: + // - house keeping (flushing breakpoints and caches, deoptimizing + // dependent compiled code) +@@ -1847,7 +1786,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + + // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined + // Deoptimize all compiled code that depends on this class +- // flush_dependent_code(the_class, THREAD); ++// if (_max_redefinition_flags <= Klass::ModifyClass) { ++// flush_dependent_code(the_class, THREAD); ++// } + + _old_methods = the_class->methods(); + _new_methods = new_class->methods(); +@@ -1877,22 +1818,17 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + } + */ + +- // Adjust constantpool caches for all classes that reference methods of the evolved class. +- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD); +- ClassLoaderDataGraph::classes_do(&clear_cpool_cache); +- + { + ResourceMark rm(THREAD); + // increment the classRedefinedCount field in the_class and in any + // direct and indirect subclasses of the_class +- increment_class_counter(the_class, THREAD); ++ increment_class_counter(new_class, THREAD); + log_info(redefine, class, load) + ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", +- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10); ++ new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), os::available_memory() >> 10); + Events::log_redefinition(THREAD, "redefined class name=%s, count=%d", +- the_class->external_name(), +- java_lang_Class::classRedefinedCount(the_class->java_mirror())); +- ++ new_class->external_name(), ++ java_lang_Class::classRedefinedCount(new_class->java_mirror())); + } + _timer_rsc_phase2.stop(); + } // end redefine_single_class() +@@ -1901,91 +1837,27 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + // Increment the classRedefinedCount field in the specific InstanceKlass + // and in all direct and indirect subclasses. + void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { +- oop class_mirror = ik->java_mirror(); ++ oop class_mirror = ik->old_version()->java_mirror(); + Klass* class_oop = java_lang_Class::as_Klass(class_mirror); + int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; +- java_lang_Class::set_classRedefinedCount(class_mirror, new_count); +- +- if (class_oop != _the_class_oop) { +- // _the_class_oop count is printed at end of redefine_single_class() +- log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count); +- } +- +- for (Klass *subk = ik->subklass(); subk != NULL; +- subk = subk->next_sibling()) { +- if (subk->is_instance_klass()) { +- // Only update instanceKlasses +- InstanceKlass *subik = InstanceKlass::cast(subk); +- // recursively do subclasses of the current subclass +- increment_class_counter(subik, THREAD); +- } +- } ++ java_lang_Class::set_classRedefinedCount(ik->java_mirror(), new_count); + } + +-// FIXME - class check is currently disabled +-void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) { +- return; +- bool no_old_methods = true; // be optimistic +- +- // Both array and instance classes have vtables. +- // a vtable should never contain old or obsolete methods +- ResourceMark rm(_thread); +- if (k->vtable_length() > 0 && +- !k->vtable().check_no_old_or_obsolete_entries()) { +- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { +- log_trace(redefine, class, obsolete, metadata) +- ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", +- k->signature_name()); +- k->vtable().dump_vtable(); +- } +- no_old_methods = false; +- } +- +- if (k->is_instance_klass()) { +- HandleMark hm(_thread); +- InstanceKlass *ik = InstanceKlass::cast(k); ++void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) { ++ if (ik->is_instance_klass() && ik->old_version() != NULL) { ++ HandleMark hm(THREAD); + +- // an itable should never contain old or obsolete methods +- if (ik->itable_length() > 0 && +- !ik->itable().check_no_old_or_obsolete_entries()) { +- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { +- log_trace(redefine, class, obsolete, metadata) +- ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", +- ik->signature_name()); +- ik->itable().dump_itable(); +- } +- no_old_methods = false; +- } +- +- // the constant pool cache should never contain non-deleted old or obsolete methods +- if (ik->constants() != NULL && +- ik->constants()->cache() != NULL && +- !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { +- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { +- log_trace(redefine, class, obsolete, metadata) +- ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", +- ik->signature_name()); +- ik->constants()->cache()->dump_cache(); +- } +- no_old_methods = false; +- } +- } ++ assert(ik->new_version() == NULL, "must be latest version in system dictionary"); + +- // print and fail guarantee if old methods are found. +- if (!no_old_methods) { +- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { +- dump_methods(); +- } else { +- log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option " +- "to see more info about the following guarantee() failure."); ++ if (ik->vtable_length() > 0) { ++ ResourceMark rm(THREAD); ++ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found"); ++ ik->vtable().verify(tty, true); + } +- guarantee(false, "OLD and/or OBSOLETE method(s) found"); + } + } + +-/** +- * Logging of all methods (old, new, changed, ...) +- */ ++// Logging of all methods (old, new, changed, ...) + void VM_EnhancedRedefineClasses::dump_methods() { + int j; + log_trace(redefine, class, dump)("_old_methods --"); +@@ -2045,18 +1917,7 @@ void VM_EnhancedRedefineClasses::dump_methods() { + } + } + +-// TODO - is it called anywhere? +-void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const { +- VM_Operation::print_on_error(st); +- if (_the_class_oop != NULL) { +- ResourceMark rm; +- st->print_cr(", redefining class %s", _the_class_oop->external_name()); +- } +-} +- +-/** +- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. +-*/ ++// Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. + class AffectedKlassClosure : public KlassClosure { + private: + GrowableArray* _affected_klasses; +@@ -2087,7 +1948,7 @@ class AffectedKlassClosure : public KlassClosure { + log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); + klass->set_redefinition_flag(Klass::MarkedAsAffected); + _affected_klasses->append(klass); +- return; ++ return; + } + } + +@@ -2104,10 +1965,8 @@ class AffectedKlassClosure : public KlassClosure { + } + }; + +-/** +- Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). +- Affected classes are stored in _affected_klasses and parent classes always precedes child class. +-*/ ++// Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). ++// Affected classes are stored in _affected_klasses and parent classes always precedes child class. + jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { + for (int i = 0; i < _class_count; i++) { + InstanceKlass* klass_handle = get_ik(_class_defs[i].klass); +@@ -2119,7 +1978,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { + + // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) + AffectedKlassClosure closure(_affected_klasses); +- // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure); ++ // Updated in j10, from original SystemDictionary::classes_do + ClassLoaderDataGraph::dictionary_classes_do(&closure); + log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); + +@@ -2135,9 +1994,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { + return JVMTI_ERROR_NONE; + } + +-/** +- Pairs of class dependencies (for topological sort) +-*/ ++// Pairs of class dependencies (for topological sort) + struct KlassPair { + const Klass* _left; + const Klass* _right; +@@ -2150,15 +2007,11 @@ static bool match_second(void* value, KlassPair elem) { + return elem._right == value; + } + +-/** +- For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. +- First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). +- Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) +- +- For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. +- +- TODO - the class file is potentionally parsed multiple times - introduce a cache? +-*/ ++// For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. ++// First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). ++// Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) ++// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. ++// TODO - the class file is potentionally parsed multiple times - introduce a cache? + jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { + ResourceMark mark(THREAD); + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index b712d69a193..60b62c3170a 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -16,6 +16,8 @@ + * 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. +@@ -30,21 +32,19 @@ + #include "memory/resourceArea.hpp" + #include "oops/objArrayKlass.hpp" + #include "oops/objArrayOop.hpp" +-#include "runtime/vm_operations.hpp" + #include "gc/shared/vmGCOperations.hpp" + #include "../../../java.base/unix/native/include/jni_md.h" + +-/** +- * Enhanced class redefiner. +- * +- * This class implements VM_GC_Operation - the usual usage should be: +- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); +- * VMThread::execute(&op); +- * Which in turn runs: +- * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions +- * - doit() - main redefition, adjust existing objects on the heap, clear caches +- * - doit_epilogue() - cleanup +-*/ ++// ++// Enhanced class redefiner. ++// ++// This class implements VM_GC_Operation - the usual usage should be: ++// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); ++// VMThread::execute(&op); ++// Which in turn runs: ++// - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions ++// - doit() - main redefition, adjust existing objects on the heap, clear caches ++// - doit_epilogue() - cleanup + class VM_EnhancedRedefineClasses: public VM_GC_Operation { + private: + // These static fields are needed by ClassLoaderDataGraph::classes_do() +@@ -69,17 +69,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // RetransformClasses. Indicate which. + JvmtiClassLoadKind _class_load_kind; + +- // _index_map_count is just an optimization for knowing if +- // _index_map_p contains any entries. +- int _index_map_count; +- intArray * _index_map_p; +- +- // _operands_index_map_count is just an optimization for knowing if +- // _operands_index_map_p contains any entries. +- int _operands_cur_length; +- int _operands_index_map_count; +- intArray * _operands_index_map_p; +- + GrowableArray* _new_classes; + jvmtiError _res; + +@@ -103,17 +92,15 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + + // These routines are roughly in call order unless otherwise noted. + +- /** +- Load and link new classes (either redefined or affected by redefinition - subclass, ...) +- +- - find sorted affected classes +- - resolve new class +- - calculate redefine flags (field change, method change, supertype change, ...) +- - calculate modified fields and mapping to old fields +- - link new classes +- +- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. +- */ ++ // Load and link new classes (either redefined or affected by redefinition - subclass, ...) ++ // ++ // - find sorted affected classes ++ // - resolve new class ++ // - calculate redefine flags (field change, method change, supertype change, ...) ++ // - calculate modified fields and mapping to old fields ++ // - link new classes ++ // ++ // The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. + jvmtiError load_new_class_versions(TRAPS); + + // Searches for all affected classes and performs a sorting such tha +@@ -144,15 +131,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // Install the redefinition of a class + void redefine_single_class(InstanceKlass* new_class_oop, TRAPS); + +- void swap_annotations(InstanceKlass* new_class, +- InstanceKlass* scratch_class); +- + // Increment the classRedefinedCount field in the specific InstanceKlass + // and in all direct and indirect subclasses. + void increment_class_counter(InstanceKlass *ik, TRAPS); + + void flush_dependent_code(InstanceKlass* k_h, TRAPS); + ++ static void check_class(InstanceKlass* k_oop, TRAPS); ++ + static void dump_methods(); + + // Check that there are no old or obsolete methods +@@ -195,8 +181,5 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // Modifiable test must be shared between IsModifiableClass query + // and redefine implementation + static bool is_modifiable_class(oop klass_mirror); +- +- // Error printing +- void print_on_error(outputStream* st) const; + }; + #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP +diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp +index a1ea25de1ea..6ea6f2fa902 100644 +--- a/src/hotspot/share/prims/jvmtiImpl.cpp ++++ b/src/hotspot/share/prims/jvmtiImpl.cpp +@@ -248,8 +248,10 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { + Symbol* m_signature = _method->signature(); + + // (DCEVM) Go through old versions of method +- for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { +- (m->*meth_act)(_bci); ++ if (AllowEnhancedClassRedefinition) { ++ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { ++ (m->*meth_act)(_bci); ++ } + } + + // search previous versions if they exist +diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp +index 91d6d80e75b..122bb8c186b 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.cpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.cpp +@@ -384,6 +384,69 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { + } + #endif // INCLUDE_JVMTI + ++// (DCEVM) It is called at safepoint only for RedefineClasses ++void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) { ++ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); ++ // For each entry in RMT, change to new method ++ GrowableArray* oops_to_add = new GrowableArray(); ++ ++ for (int i = 0; i < _the_table->table_size(); ++i) { ++ for (ResolvedMethodEntry* entry = _the_table->bucket(i); ++ entry != NULL; ++ entry = entry->next()) { ++ ++ oop mem_name = entry->object_no_keepalive(); ++ // except ones removed ++ if (mem_name == NULL) { ++ continue; ++ } ++ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); ++ ++ if (old_method->is_old()) { ++ ++ // Method* new_method; ++ if (old_method->is_deleted()) { ++ // FIXME:(DCEVM) - check if exception can be thrown ++ // new_method = Universe::throw_no_such_method_error(); ++ continue; ++ } ++ ++ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); ++ Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); ++ ++ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); ++ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); ++ assert(old_method != newer_method, "sanity check"); ++ ++ if (_the_table->lookup(newer_method) != NULL) { ++ // old method was already adjusted if new method exists in _the_table ++ continue; ++ } ++ ++ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); ++ java_lang_invoke_ResolvedMethodName::set_vmholder_offset(mem_name, newer_method); ++ ++ newer_klass->set_has_resolved_methods(); ++ oops_to_add->append(mem_name); ++ ++ ResourceMark rm; ++ if (!(*trace_name_printed)) { ++ log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); ++ *trace_name_printed = true; ++ } ++ log_debug(redefine, class, update, constantpool) ++ ("ResolvedMethod method update: %s(%s)", ++ newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); ++ } ++ } ++ for (int i = 0; i < oops_to_add->length(); i++) { ++ oop mem_name = oops_to_add->at(i); ++ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); ++ _the_table->basic_add(method, Handle(Thread::current(), mem_name)); ++ } ++ } ++} ++ + // Verification + class VerifyResolvedMethod : StackObj { + public: +diff --git a/src/hotspot/share/prims/resolvedMethodTable.hpp b/src/hotspot/share/prims/resolvedMethodTable.hpp +index 794a8651804..143922b50b8 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.hpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.hpp +@@ -77,6 +77,7 @@ public: + + // JVMTI Support - It is called at safepoint only for RedefineClasses + JVMTI_ONLY(static void adjust_method_entries(bool * trace_name_printed);) ++ JVMTI_ONLY(static void adjust_method_entries_dcevm(bool * trace_name_printed);) + + // Debugging + static size_t items_count(); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch b/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch new file mode 100644 index 000000000000..4fd2678b21df --- /dev/null +++ b/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch @@ -0,0 +1,29 @@ +From 960dafbeeba190911955c208b611fecc15d66738 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Wed, 11 Mar 2020 14:19:34 +0100 +Subject: [PATCH 03/34] Fix class cast exception on redefinition of class A, + that is superclass of B that has anonymous class C + +--- + src/hotspot/share/oops/instanceKlass.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index 994fc8a3bc8..3be3a09ef8f 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -953,7 +953,10 @@ bool InstanceKlass::link_class_impl(TRAPS) { + + if (!is_linked()) { + if (!is_rewritten()) { +- { ++ // (DCEVM): If class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C ++ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification ++ // on redefinition. ++ if (!AllowEnhancedClassRedefinition || !newest_version()->is_redefining()) { + bool verify_ok = verify_code(THREAD); + if (!verify_ok) { + return false; +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch b/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch new file mode 100644 index 000000000000..cafc41d1babc --- /dev/null +++ b/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch @@ -0,0 +1,1086 @@ +From 68dcf3c0d26d717ee9d2d2404848dffb69fee8d4 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Wed, 14 Nov 2018 21:20:08 +0100 +Subject: [PATCH 04/34] HotswapAgent integration + +It include: + +- option to compile DCEVM only version with -DDCEVM_ONLY added +to CFLAGS (bash configure --with-extra-cflags="-DDCEVM_ONLY"), by +default compilation goes with HotswapAgent + +Allow ha class initializer calls + +Add --add-opens for necessary modules/packages +- java.base/java.lang - for reflection access to Proxy.proxyCache +- java.base/jdk.internal.loader - for access proxyCache class +- java.desktop/java.beans - for reflection access to Introspector +- java.desktop/com.sun.beans +- java.base/java.io +- com.sun.beans.util + +Open jdk module to access ClassInfo.CACHE + +- be quiet if HotswapAgent is not found in lib/, it is compatible with +old DCEVM +- disable HotswapAgent for -Xshare:dump +- disable HotswapAgent in jvm tools +- disable HotswapAgent in keytool +--- + make/launcher/Launcher-java.base.gmk | 93 ++++++++++++++++ + make/launcher/Launcher-java.security.jgss.gmk | 43 ++++++++ + make/launcher/Launcher-jdk.aot.gmk | 58 ++++++++++ + make/launcher/Launcher-jdk.compiler.gmk | 50 +++++++++ + make/launcher/Launcher-jdk.jcmd.gmk | 74 +++++++++++++ + make/launcher/Launcher-jdk.jconsole.gmk | 35 ++++++ + make/launcher/Launcher-jdk.jstatd.gmk | 34 ++++++ + make/launcher/Launcher-jdk.pack.gmk | 101 ++++++++++++++++++ + make/launcher/Launcher-jdk.rmic.gmk | 32 ++++++ + .../Launcher-jdk.scripting.nashorn.shell.gmk | 33 ++++++ + make/modules/java.rmi/Launcher.gmk | 2 + + make/modules/java.scripting/Launcher.gmk | 3 +- + make/modules/jdk.hotspot.agent/Launcher.gmk | 1 + + make/modules/jdk.jartool/Launcher.gmk | 2 + + make/modules/jdk.javadoc/Launcher.gmk | 3 +- + make/modules/jdk.jdeps/Launcher.gmk | 3 + + make/modules/jdk.jdi/Launcher.gmk | 1 + + make/modules/jdk.jlink/Launcher.gmk | 5 +- + make/modules/jdk.jshell/Launcher.gmk | 1 + + src/hotspot/share/classfile/vmSymbols.hpp | 1 + + .../share/interpreter/linkResolver.cpp | 2 +- + src/hotspot/share/runtime/arguments.cpp | 67 ++++++++++++ + src/hotspot/share/runtime/arguments.hpp | 3 + + src/hotspot/share/runtime/globals.hpp | 12 ++- + .../sun/beans/introspect/package-info.java | 26 +++++ + .../classes/com/sun/beans/package-info.java | 26 +++++ + .../com/sun/beans/util/package-info.java | 26 +++++ + .../share/classes/module-info.java | 3 + + 28 files changed, 735 insertions(+), 5 deletions(-) + create mode 100644 make/launcher/Launcher-java.base.gmk + create mode 100644 make/launcher/Launcher-java.security.jgss.gmk + create mode 100644 make/launcher/Launcher-jdk.aot.gmk + create mode 100644 make/launcher/Launcher-jdk.compiler.gmk + create mode 100644 make/launcher/Launcher-jdk.jcmd.gmk + create mode 100644 make/launcher/Launcher-jdk.jconsole.gmk + create mode 100644 make/launcher/Launcher-jdk.jstatd.gmk + create mode 100644 make/launcher/Launcher-jdk.pack.gmk + create mode 100644 make/launcher/Launcher-jdk.rmic.gmk + create mode 100644 make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk + create mode 100644 src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java + create mode 100644 src/java.desktop/share/classes/com/sun/beans/package-info.java + create mode 100644 src/java.desktop/share/classes/com/sun/beans/util/package-info.java + +diff --git a/make/launcher/Launcher-java.base.gmk b/make/launcher/Launcher-java.base.gmk +new file mode 100644 +index 00000000000..38ba29530d8 +--- /dev/null ++++ b/make/launcher/Launcher-java.base.gmk +@@ -0,0 +1,93 @@ ++# ++# Copyright (c) 2011, 2020, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call IncludeCustomExtension, launcher/Launcher-java.base.gmk)) ++ ++JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/common ++JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/launcher/icons ++ ++################################################################################ ++ ++$(eval $(call SetupBuildLauncher, java, \ ++ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ ++ LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \ ++ LIBS_windows := user32.lib comctl32.lib, \ ++ EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ ++ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ ++ OPTIMIZATION := HIGH, \ ++)) ++ ++ifeq ($(OPENJDK_TARGET_OS), windows) ++ $(eval $(call SetupBuildLauncher, javaw, \ ++ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ ++ LIBS_windows := user32.lib comctl32.lib, \ ++ EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ ++ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ ++ )) ++endif ++ ++$(eval $(call SetupBuildLauncher, keytool, \ ++ MAIN_CLASS := sun.security.tools.keytool.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++)) ++ ++################################################################################ ++ ++ifeq ($(OPENJDK_TARGET_OS), linux) ++ $(eval $(call SetupJdkExecutable, BUILD_JEXEC, \ ++ NAME := jexec, \ ++ SRC := $(TOPDIR)/src/$(MODULE)/unix/native/launcher, \ ++ INCLUDE_FILES := jexec.c, \ ++ OPTIMIZATION := LOW, \ ++ CFLAGS := $(CFLAGS_JDKEXE) \ ++ -I$(TOPDIR)/src/$(MODULE)/share/native/libjli, \ ++ CFLAGS_linux := -fPIC, \ ++ CFLAGS_solaris := -KPIC, \ ++ LDFLAGS := $(LDFLAGS_JDKEXE), \ ++ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \ ++ )) ++ ++ TARGETS += $(BUILD_JEXEC) ++endif ++ ++################################################################################ ++ ++ifneq ($(findstring $(OPENJDK_TARGET_OS), macosx solaris aix linux), ) ++ $(eval $(call SetupJdkExecutable, BUILD_JSPAWNHELPER, \ ++ NAME := jspawnhelper, \ ++ SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \ ++ OPTIMIZATION := LOW, \ ++ CFLAGS := $(CFLAGS_JDKEXE) -I$(TOPDIR)/src/$(MODULE)/unix/native/libjava, \ ++ EXTRA_OBJECT_FILES := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc.o, \ ++ LDFLAGS := $(LDFLAGS_JDKEXE), \ ++ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \ ++ )) ++ ++ TARGETS += $(BUILD_JSPAWNHELPER) ++endif ++ ++################################################################################ +diff --git a/make/launcher/Launcher-java.security.jgss.gmk b/make/launcher/Launcher-java.security.jgss.gmk +new file mode 100644 +index 00000000000..2b856bfccb4 +--- /dev/null ++++ b/make/launcher/Launcher-java.security.jgss.gmk +@@ -0,0 +1,43 @@ ++# ++# Copyright (c) 2011, 2015, 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. ++# ++ ++include LauncherCommon.gmk ++ ++ifeq ($(OPENJDK_TARGET_OS), windows) ++ $(eval $(call SetupBuildLauncher, kinit, \ ++ MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ )) ++ ++ $(eval $(call SetupBuildLauncher, klist, \ ++ MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ )) ++ ++ $(eval $(call SetupBuildLauncher, ktab, \ ++ MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ )) ++endif +diff --git a/make/launcher/Launcher-jdk.aot.gmk b/make/launcher/Launcher-jdk.aot.gmk +new file mode 100644 +index 00000000000..2c52c31a555 +--- /dev/null ++++ b/make/launcher/Launcher-jdk.aot.gmk +@@ -0,0 +1,58 @@ ++# ++# Copyright (c) 2016, 2019, 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. ++# ++ ++include LauncherCommon.gmk ++ ++# The JVMCI exports are needed since JVMCI is normally dynamically exported ++# (see jdk.vm.ci.services.internal.ReflectionAccessJDK::openJVMCITo). ++ ++$(eval $(call SetupBuildLauncher, jaotc, \ ++ MAIN_CLASS := jdk.tools.jaotc.Main, \ ++ EXTRA_JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \ ++ -XX:+DisableHotswapAgent \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.site=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.stack=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.common=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ , \ ++ JAVA_ARGS := --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ -XX:+DisableHotswapAgent \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ ++ -XX:+UnlockExperimentalVMOptions -XX:+UseAOT \ ++ -XX:+CalculateClassFingerprint \ ++ -Djvmci.UseProfilingInformation=false \ ++ -Dgraal.UseExceptionProbability=false \ ++ -Djvmci.Compiler=graal \ ++ --add-modules ALL-DEFAULT \ ++ , \ ++)) +diff --git a/make/launcher/Launcher-jdk.compiler.gmk b/make/launcher/Launcher-jdk.compiler.gmk +new file mode 100644 +index 00000000000..744969546de +--- /dev/null ++++ b/make/launcher/Launcher-jdk.compiler.gmk +@@ -0,0 +1,50 @@ ++# ++# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. ++# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++# ++# This code is free software; you can redistribute it and/or modify it ++# 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, javac, \ ++ MAIN_CLASS := com.sun.tools.javac.Main, \ ++ JAVA_ARGS := --add-modules ALL-DEFAULT \ ++ -XX:+DisableHotswapAgent, \ ++ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, serialver, \ ++ MAIN_CLASS := sun.tools.serialver.SerialVer, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ ++)) ++ ++ifeq ($(ENABLE_SJAVAC), yes) ++ # Build sjavac directly to the exploded image so that it does not get included ++ # into any real images ++ $(eval $(call SetupBuildLauncher, sjavac, \ ++ MAIN_CLASS := com.sun.tools.sjavac.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ ++ OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \ ++ )) ++endif +diff --git a/make/launcher/Launcher-jdk.jcmd.gmk b/make/launcher/Launcher-jdk.jcmd.gmk +new file mode 100644 +index 00000000000..761a52d8466 +--- /dev/null ++++ b/make/launcher/Launcher-jdk.jcmd.gmk +@@ -0,0 +1,74 @@ ++# ++# Copyright (c) 2011, 2019, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, jinfo, \ ++ MAIN_CLASS := sun.tools.jinfo.JInfo, \ ++ JAVA_ARGS := \ ++ -Dsun.jvm.hotspot.debugger.useProcDebugger \ ++ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ ++ -XX:+DisableHotswapAgent, \ ++ MACOSX_PRIVILEGED := true, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, jmap, \ ++ MAIN_CLASS := sun.tools.jmap.JMap, \ ++ JAVA_ARGS := \ ++ -Dsun.jvm.hotspot.debugger.useProcDebugger \ ++ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \ ++ -XX:+DisableHotswapAgent, \ ++ MACOSX_PRIVILEGED := true, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, jps, \ ++ MAIN_CLASS := sun.tools.jps.Jps, \ ++ JAVA_ARGS := \ ++ -XX:+DisableHotswapAgent, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, jstack, \ ++ MAIN_CLASS := sun.tools.jstack.JStack, \ ++ JAVA_ARGS := \ ++ -Dsun.jvm.hotspot.debugger.useProcDebugger \ ++ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \ ++ -XX:+DisableHotswapAgent, \ ++ MACOSX_PRIVILEGED := true, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, jstat, \ ++ MAIN_CLASS := sun.tools.jstat.Jstat, \ ++ JAVA_ARGS := \ ++ -XX:+DisableHotswapAgent, \ ++)) ++ ++$(eval $(call SetupBuildLauncher, jcmd, \ ++ MAIN_CLASS := sun.tools.jcmd.JCmd, \ ++ JAVA_ARGS := \ ++ -XX:+DisableHotswapAgent, \ ++)) ++ ++# Hook to include the corresponding custom file, if present. ++$(eval $(call IncludeCustomExtension, launcher/Launcher-jdk.jcmd-post.gmk)) +diff --git a/make/launcher/Launcher-jdk.jconsole.gmk b/make/launcher/Launcher-jdk.jconsole.gmk +new file mode 100644 +index 00000000000..5ca6a0c123b +--- /dev/null ++++ b/make/launcher/Launcher-jdk.jconsole.gmk +@@ -0,0 +1,35 @@ ++# ++# Copyright (c) 2011, 2015, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, jconsole, \ ++ MAIN_CLASS := sun.tools.jconsole.JConsole, \ ++ JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \ ++ -Djconsole.showOutputViewer \ ++ -XX:+DisableHotswapAgent, \ ++ CFLAGS_windows := -DJAVAW, \ ++ LIBS_windows := user32.lib, \ ++)) +diff --git a/make/launcher/Launcher-jdk.jstatd.gmk b/make/launcher/Launcher-jdk.jstatd.gmk +new file mode 100644 +index 00000000000..e1657910c67 +--- /dev/null ++++ b/make/launcher/Launcher-jdk.jstatd.gmk +@@ -0,0 +1,34 @@ ++# ++# Copyright (c) 2011, 2018, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, jstatd, \ ++ MAIN_CLASS := sun.tools.jstatd.Jstatd, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++)) ++ ++# Hook to include the corresponding custom file, if present. ++$(eval $(call IncludeCustomExtension, launcher/Launcher-jdk.jstatd-post.gmk)) +diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk +new file mode 100644 +index 00000000000..64bbbb7c949 +--- /dev/null ++++ b/make/launcher/Launcher-jdk.pack.gmk +@@ -0,0 +1,101 @@ ++# ++# Copyright (c) 2011, 2018, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, pack200, \ ++ MAIN_MODULE := java.base, \ ++ MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++)) ++ ++################################################################################ ++# The order of the object files on the link command line affects the size of the resulting ++# binary (at least on linux) which causes the size to differ between old and new build. ++ ++# Tell the compiler not to export any functions unless declared so in ++# the source code. On Windows, this is the default and cannot be changed. ++# On Mac, we have always exported all symbols, probably due to oversight ++# and/or misunderstanding. To emulate this, don't hide any symbols ++# by default. ++# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063) ++# Also provide an override for non-conformant libraries. ++ifeq ($(TOOLCHAIN_TYPE), gcc) ++ CXXFLAGS_JDKEXE += -fvisibility=hidden ++ LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL ++else ifeq ($(TOOLCHAIN_TYPE), clang) ++ ifneq ($(OPENJDK_TARGET_OS), macosx) ++ CXXFLAGS_JDKEXE += -fvisibility=hidden ++ endif ++else ifeq ($(TOOLCHAIN_TYPE), solstudio) ++ CXXFLAGS_JDKEXE += -xldscope=hidden ++endif ++ ++UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \ ++ $(TOPDIR)/src/jdk.pack/share/native/unpack200 ++UNPACKEXE_CFLAGS := -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \ ++ -I$(TOPDIR)/src/java.base/share/native/libjava \ ++ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava ++ ++ifeq ($(USE_EXTERNAL_LIBZ), true) ++ UNPACKEXE_CFLAGS += -DSYSTEM_ZLIB ++ UNPACKEXE_LIBS := -lz ++else ++ UNPACKEXE_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/libzip/zlib ++ UNPACKEXE_ZIPOBJS := $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zcrc32$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/deflate$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/trees$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zadler32$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/compress$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zutil$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inflate$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/infback$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inftrees$(OBJ_SUFFIX) \ ++ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inffast$(OBJ_SUFFIX) ++ ++endif ++ ++$(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \ ++ NAME := unpack200, \ ++ SRC := $(UNPACKEXE_SRC), \ ++ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ ++ OPTIMIZATION := LOW, \ ++ CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \ ++ CFLAGS_release := -DPRODUCT, \ ++ CFLAGS_linux := -fPIC, \ ++ CFLAGS_solaris := -KPIC, \ ++ CFLAGS_macosx := -fPIC, \ ++ LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ ++ $(call SET_SHARED_LIBRARY_ORIGIN), \ ++ LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \ ++ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \ ++ MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \ ++ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ ++ EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \ ++)) ++ ++TARGETS += $(BUILD_UNPACKEXE) ++ ++################################################################################ +diff --git a/make/launcher/Launcher-jdk.rmic.gmk b/make/launcher/Launcher-jdk.rmic.gmk +new file mode 100644 +index 00000000000..b8a55900b0e +--- /dev/null ++++ b/make/launcher/Launcher-jdk.rmic.gmk +@@ -0,0 +1,32 @@ ++# ++# Copyright (c) 2011, 2015, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, rmic, \ ++ MAIN_CLASS := sun.rmi.rmic.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ ++ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ ++)) +diff --git a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk +new file mode 100644 +index 00000000000..bd39f8595b2 +--- /dev/null ++++ b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk +@@ -0,0 +1,33 @@ ++# ++# Copyright (c) 2011, 2016, 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. ++# ++ ++include LauncherCommon.gmk ++ ++$(eval $(call SetupBuildLauncher, jjs, \ ++ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ ++ JAVA_ARGS := --add-modules ALL-DEFAULT \ ++ -XX:+DisableHotswapAgent, \ ++ CFLAGS := -DENABLE_ARG_FILES, \ ++)) +diff --git a/make/modules/java.rmi/Launcher.gmk b/make/modules/java.rmi/Launcher.gmk +index a69a90bcc81..07046232275 100644 +--- a/make/modules/java.rmi/Launcher.gmk ++++ b/make/modules/java.rmi/Launcher.gmk +@@ -27,8 +27,10 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, rmid, \ + MAIN_CLASS := sun.rmi.server.Activation, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + )) + + $(eval $(call SetupBuildLauncher, rmiregistry, \ + MAIN_CLASS := sun.rmi.registry.RegistryImpl, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + )) +diff --git a/make/modules/java.scripting/Launcher.gmk b/make/modules/java.scripting/Launcher.gmk +index 057d2bf3aca..cf100e20789 100644 +--- a/make/modules/java.scripting/Launcher.gmk ++++ b/make/modules/java.scripting/Launcher.gmk +@@ -27,5 +27,6 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jrunscript, \ + MAIN_CLASS := com.sun.tools.script.shell.Main, \ +- JAVA_ARGS := --add-modules ALL-DEFAULT, \ ++ JAVA_ARGS := --add-modules ALL-DEFAULT \ ++ -XX:+DisableHotswapAgent, \ + )) +diff --git a/make/modules/jdk.hotspot.agent/Launcher.gmk b/make/modules/jdk.hotspot.agent/Launcher.gmk +index 76da3600368..9f12b05b172 100644 +--- a/make/modules/jdk.hotspot.agent/Launcher.gmk ++++ b/make/modules/jdk.hotspot.agent/Launcher.gmk +@@ -27,5 +27,6 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jhsdb, \ + MAIN_CLASS := sun.jvm.hotspot.SALauncher, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + MACOSX_PRIVILEGED := true, \ + )) +diff --git a/make/modules/jdk.jartool/Launcher.gmk b/make/modules/jdk.jartool/Launcher.gmk +index f74e82bfdae..647d82b65b1 100644 +--- a/make/modules/jdk.jartool/Launcher.gmk ++++ b/make/modules/jdk.jartool/Launcher.gmk +@@ -27,8 +27,10 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jar, \ + MAIN_CLASS := sun.tools.jar.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + )) + + $(eval $(call SetupBuildLauncher, jarsigner, \ + MAIN_CLASS := sun.security.tools.jarsigner.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + )) +diff --git a/make/modules/jdk.javadoc/Launcher.gmk b/make/modules/jdk.javadoc/Launcher.gmk +index 889028a2b17..c3d2093be04 100644 +--- a/make/modules/jdk.javadoc/Launcher.gmk ++++ b/make/modules/jdk.javadoc/Launcher.gmk +@@ -27,6 +27,7 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, javadoc, \ + MAIN_CLASS := jdk.javadoc.internal.tool.Main, \ +- JAVA_ARGS := --add-modules ALL-DEFAULT, \ ++ JAVA_ARGS := --add-modules ALL-DEFAULT \ ++ -XX:+DisableHotswapAgent, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ + )) +diff --git a/make/modules/jdk.jdeps/Launcher.gmk b/make/modules/jdk.jdeps/Launcher.gmk +index 217523c48cc..5448278dae7 100644 +--- a/make/modules/jdk.jdeps/Launcher.gmk ++++ b/make/modules/jdk.jdeps/Launcher.gmk +@@ -27,15 +27,18 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, javap, \ + MAIN_CLASS := com.sun.tools.javap.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ + )) + + $(eval $(call SetupBuildLauncher, jdeps, \ + MAIN_CLASS := com.sun.tools.jdeps.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ + )) + + $(eval $(call SetupBuildLauncher, jdeprscan, \ + MAIN_CLASS := com.sun.tools.jdeprscan.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ + )) +diff --git a/make/modules/jdk.jdi/Launcher.gmk b/make/modules/jdk.jdi/Launcher.gmk +index fcce98cf430..27bd448e3ae 100644 +--- a/make/modules/jdk.jdi/Launcher.gmk ++++ b/make/modules/jdk.jdi/Launcher.gmk +@@ -27,4 +27,5 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jdb, \ + MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + )) +diff --git a/make/modules/jdk.jlink/Launcher.gmk b/make/modules/jdk.jlink/Launcher.gmk +index df2173996d7..9e61edeb2c8 100644 +--- a/make/modules/jdk.jlink/Launcher.gmk ++++ b/make/modules/jdk.jlink/Launcher.gmk +@@ -27,18 +27,21 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jimage,\ + MAIN_CLASS := jdk.tools.jimage.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DENABLE_ARG_FILES, \ + )) + + $(eval $(call SetupBuildLauncher, jlink,\ + MAIN_CLASS := jdk.tools.jlink.internal.Main, \ +- JAVA_ARGS := --add-modules ALL-DEFAULT, \ ++ JAVA_ARGS := --add-modules ALL-DEFAULT \ ++ -XX:+DisableHotswapAgent, \ + CFLAGS := -DENABLE_ARG_FILES \ + -DEXPAND_CLASSPATH_WILDCARDS, \ + )) + + $(eval $(call SetupBuildLauncher, jmod,\ + MAIN_CLASS := jdk.tools.jmod.Main, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DENABLE_ARG_FILES \ + -DEXPAND_CLASSPATH_WILDCARDS, \ + )) +diff --git a/make/modules/jdk.jshell/Launcher.gmk b/make/modules/jdk.jshell/Launcher.gmk +index 349eb88e9eb..7287f8f998a 100644 +--- a/make/modules/jdk.jshell/Launcher.gmk ++++ b/make/modules/jdk.jshell/Launcher.gmk +@@ -27,5 +27,6 @@ include LauncherCommon.gmk + + $(eval $(call SetupBuildLauncher, jshell, \ + MAIN_CLASS := jdk.internal.jshell.tool.JShellToolProvider, \ ++ JAVA_ARGS := -XX:+DisableHotswapAgent, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ + )) +diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp +index 99c5ac98995..6a3b234b222 100644 +--- a/src/hotspot/share/classfile/vmSymbols.hpp ++++ b/src/hotspot/share/classfile/vmSymbols.hpp +@@ -347,6 +347,7 @@ + /* common method and field names */ \ + template(object_initializer_name, "") \ + template(class_initializer_name, "") \ ++ template(ha_class_initializer_name, "$$ha$clinit") \ + template(println_name, "println") \ + template(printStackTrace_name, "printStackTrace") \ + template(main_name, "main") \ +diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp +index 3425e3f893d..b6e9e0a308d 100644 +--- a/src/hotspot/share/interpreter/linkResolver.cpp ++++ b/src/hotspot/share/interpreter/linkResolver.cpp +@@ -1025,7 +1025,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, + assert(m != NULL, "information about the current method must be available for 'put' bytecodes"); + bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic && + fd.is_static() && +- !m->is_static_initializer()); ++ !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name())); + bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) && + !fd.is_static() && + !m->is_object_initializer()); +diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp +index 6148bce5b9b..2803a3c46eb 100644 +--- a/src/hotspot/share/runtime/arguments.cpp ++++ b/src/hotspot/share/runtime/arguments.cpp +@@ -4116,6 +4116,8 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { + // Set object alignment values. + set_object_alignment(); + ++ setup_hotswap_agent(); ++ + #if !INCLUDE_CDS + if (DumpSharedSpaces || RequireSharedSpaces) { + jio_fprintf(defaultStream::error_stream(), +@@ -4442,3 +4444,68 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen, + *b = '\0'; + return (p == src_end); // return false if not all of the source was copied + } ++ ++void Arguments::setup_hotswap_agent() { ++ ++ if (DumpSharedSpaces) ++ return; ++ ++ if (!AllowEnhancedClassRedefinition) ++ return; ++ ++ // Set HotswapAgent ++ if (!DisableHotswapAgent) { ++ ++ char ext_path_str[JVM_MAXPATHLEN]; ++ ++ os::jvm_path(ext_path_str, sizeof(ext_path_str)); ++ for (int i = 0; i < 3; i++) { ++ char *end = strrchr(ext_path_str, *os::file_separator()); ++ if (end != NULL) *end = '\0'; ++ } ++ size_t ext_path_length = strlen(ext_path_str); ++ if (ext_path_length >= 3) { ++ if (strcmp(ext_path_str + ext_path_length - 3, "lib") != 0) { ++ if (ext_path_length < JVM_MAXPATHLEN - 4) { ++ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, "%slib", os::file_separator()); ++ ext_path_length += 4; ++ } ++ } ++ } ++ if (ext_path_length < JVM_MAXPATHLEN - 10) { ++ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, ++ "%shotswap%shotswap-agent.jar", os::file_separator(), os::file_separator()); ++ } ++ ++ int fd = ::open(ext_path_str, O_RDONLY); ++ if (fd >= 0) { ++ os::close(fd); ++ size_t length = strlen(ext_path_str) + 1; ++ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments); ++ jio_snprintf(options, length, "%s", ext_path_str); ++ add_init_agent("instrument", ext_path_str, false); ++ jio_fprintf(defaultStream::output_stream(), "Starting HotswapAgent '%s'\n", ext_path_str); ++ } ++// else ++// { ++// jio_fprintf(defaultStream::error_stream(), "HotswapAgent not found on path:'%s'\n", ext_path_str); ++// } ++ } ++ ++ // TODO: open it only for org.hotswap.agent module ++ // Use to access java.lang.reflect.Proxy/proxyCache ++ create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); ++ // Class of field java.lang.reflect.Proxy/proxyCache ++ create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); ++ // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream ++ create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); ++ // java.beans.Introspector access ++ create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); ++ // java.beans.Introspector access ++ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); ++ // com.sun.beans.introspect.ClassInfo access ++ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); ++ // com.sun.beans.introspect.util.Cache access ++ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); ++ ++} +diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp +index 9c656124d5b..e5fed6345f7 100644 +--- a/src/hotspot/share/runtime/arguments.hpp ++++ b/src/hotspot/share/runtime/arguments.hpp +@@ -512,6 +512,9 @@ class Arguments : AllStatic { + + static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; } + ++ // Initialize HotswapAgent ++ static void setup_hotswap_agent(); ++ + // Return the maximum size a heap with compressed oops can take + static size_t max_heap_for_compressed_oops(); + +diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp +index de9193ca447..5b367704800 100644 +--- a/src/hotspot/share/runtime/globals.hpp ++++ b/src/hotspot/share/runtime/globals.hpp +@@ -31,6 +31,13 @@ + #include "utilities/align.hpp" + #include "utilities/globalDefinitions.hpp" + #include "utilities/macros.hpp" ++ ++#ifdef DCEVM_ONLY ++#define DISABLED_HOTSWAP_AGENT true ++#else ++#define DISABLED_HOTSWAP_AGENT false ++#endif ++ + #include CPU_HEADER(globals) + #include OS_HEADER(globals) + #include OS_CPU_HEADER(globals) +@@ -2461,7 +2468,10 @@ const size_t minimumSymbolTableSize = 1024; + \ + product(bool, AllowEnhancedClassRedefinition, true, \ + "Allow enhanced class redefinition beyond swapping method " \ +- "bodies") ++ "bodies") \ ++ \ ++ product(bool, DisableHotswapAgent, DISABLED_HOTSWAP_AGENT, \ ++ "Disable integrated Hotswap Agent (HotswapVM only)") + + + // Interface macros +diff --git a/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java +new file mode 100644 +index 00000000000..6636e4dd62a +--- /dev/null ++++ b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * 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. ++ */ ++ ++package com.sun.beans.introspect; +diff --git a/src/java.desktop/share/classes/com/sun/beans/package-info.java b/src/java.desktop/share/classes/com/sun/beans/package-info.java +new file mode 100644 +index 00000000000..5c097eeaa53 +--- /dev/null ++++ b/src/java.desktop/share/classes/com/sun/beans/package-info.java +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * 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. ++ */ ++ ++package com.sun.beans; +diff --git a/src/java.desktop/share/classes/com/sun/beans/util/package-info.java b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java +new file mode 100644 +index 00000000000..2d5d735ffa8 +--- /dev/null ++++ b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * 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. ++ */ ++ ++package com.sun.beans.util; +diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java +index 897647ee368..286304c775c 100644 +--- a/src/java.desktop/share/classes/module-info.java ++++ b/src/java.desktop/share/classes/module-info.java +@@ -111,6 +111,9 @@ module java.desktop { + exports javax.swing.text.rtf; + exports javax.swing.tree; + exports javax.swing.undo; ++ exports com.sun.beans; ++ exports com.sun.beans.introspect; ++ exports com.sun.beans.util; + + // qualified exports may be inserted at build time + // see make/GensrcModuleInfo.gmk +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch b/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch new file mode 100644 index 000000000000..054fe81657a1 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch @@ -0,0 +1,240 @@ +From 39df5f163d4a0f1fd6b92313a5570808f19d5e20 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 4 Oct 2020 21:12:12 +0200 +Subject: [PATCH 05/34] Support for Lambda class redefinition + +--- + .../share/classfile/classLoaderData.cpp | 9 +++ + .../share/classfile/classLoaderData.hpp | 2 +- + .../share/classfile/systemDictionary.cpp | 12 +++- + .../share/classfile/systemDictionary.hpp | 1 + + .../prims/jvmtiEnhancedRedefineClasses.cpp | 65 +++++++++++++++++-- + .../prims/jvmtiEnhancedRedefineClasses.hpp | 1 + + .../share/prims/resolvedMethodTable.cpp | 2 + + src/hotspot/share/prims/unsafe.cpp | 1 + + 8 files changed, 83 insertions(+), 10 deletions(-) + +diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp +index 0cd90bb8c27..4d64c6b454a 100644 +--- a/src/hotspot/share/classfile/classLoaderData.cpp ++++ b/src/hotspot/share/classfile/classLoaderData.cpp +@@ -593,6 +593,15 @@ Dictionary* ClassLoaderData::create_dictionary() { + return new Dictionary(this, size, resizable); + } + ++void ClassLoaderData::exchange_holders(ClassLoaderData* cld) { ++ oop holder_oop = _holder.peek(); ++ _holder.replace(cld->_holder.peek()); ++ cld->_holder.replace(holder_oop); ++ WeakHandle exchange = _holder; ++ _holder = cld->_holder; ++ cld->_holder = exchange; ++} ++ + // Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph + oop ClassLoaderData::holder_phantom() const { + // A klass that was previously considered dead can be looked up in the +diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp +index ba2393f8dd0..e2ae0a77351 100644 +--- a/src/hotspot/share/classfile/classLoaderData.hpp ++++ b/src/hotspot/share/classfile/classLoaderData.hpp +@@ -181,7 +181,7 @@ class ClassLoaderData : public CHeapObj { + bool has_accumulated_modified_oops() { return _accumulated_modified_oops; } + oop holder_no_keepalive() const; + oop holder_phantom() const; +- ++ void exchange_holders(ClassLoaderData* cld); + private: + void unload(); + bool keep_alive() const { return _keep_alive > 0; } +diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp +index bd0cae7cb9b..8f2b46add4d 100644 +--- a/src/hotspot/share/classfile/systemDictionary.cpp ++++ b/src/hotspot/share/classfile/systemDictionary.cpp +@@ -1062,10 +1062,14 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, + Handle class_loader, + ClassFileStream* st, + const ClassLoadInfo& cl_info, ++ InstanceKlass* old_klass, + TRAPS) { + + EventClassLoad class_load_start_event; + ClassLoaderData* loader_data; ++ ++ bool is_redefining = (old_klass != NULL); ++ + bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL; + + // - for unsafe anonymous class: create a new CLD whith a class holder that uses +@@ -1094,8 +1098,12 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, + class_name, + loader_data, + cl_info, +- false, // pick_newest ++ is_redefining, // pick_newest + CHECK_NULL); ++ if (is_redefining && k != NULL) { ++ k->set_redefining(true); ++ k->set_old_version(old_klass); ++ } + + if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) { + // Hidden classes that are not strong and unsafe anonymous classes must update +@@ -1998,7 +2006,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { + k->remove_from_sibling_list(); + } + +-// (DCEVM) ++// (DCEVM) + void SystemDictionary::update_constraints_after_redefinition() { + constraints()->update_after_redefinition(); + } +diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp +index 4547449dbec..931e655d631 100644 +--- a/src/hotspot/share/classfile/systemDictionary.hpp ++++ b/src/hotspot/share/classfile/systemDictionary.hpp +@@ -329,6 +329,7 @@ public: + Handle class_loader, + ClassFileStream* st, + const ClassLoadInfo& cl_info, ++ InstanceKlass* old_klass, + TRAPS); + + // Resolve from stream (called by jni_DefineClass and JVM_DefineClass) +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 92ce6c27b8a..8b765623dcd 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -494,6 +494,8 @@ void VM_EnhancedRedefineClasses::doit() { + ClassLoaderDataGraph::classes_do(&clear_cpool_cache); + + ++ // SystemDictionary::methods_do(fix_invoke_method); ++ + // JSR-292 support + if (_any_class_has_resolved_methods) { + bool trace_name_printed = false; +@@ -756,12 +758,34 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + // load hook event. + state->set_class_being_redefined(the_class, _class_load_kind); + +- InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym, +- the_class_loader, +- protection_domain, +- &st, +- the_class, +- THREAD); ++ InstanceKlass* k; ++ ++ if (InstanceKlass::cast(the_class)->is_anonymous()) { ++ const InstanceKlass* host_class = the_class->host_klass(); ++ ++ // Make sure it's the real host class, not another anonymous class. ++ while (host_class != NULL && host_class->is_anonymous()) { ++ host_class = host_class->host_klass(); ++ } ++ ++ k = SystemDictionary::parse_stream(the_class_sym, ++ the_class_loader, ++ protection_domain, ++ &st, ++ host_class, ++ the_class, ++ NULL, ++ THREAD); ++ k->class_loader_data()->exchange_holders(the_class->class_loader_data()); ++ the_class->class_loader_data()->inc_keep_alive(); ++ } else { ++ k = SystemDictionary::resolve_from_stream(the_class_sym, ++ the_class_loader, ++ protection_domain, ++ &st, ++ the_class, ++ THREAD); ++ } + // Clear class_being_redefined just to be sure. + state->clear_class_being_redefined(); + +@@ -1442,6 +1466,30 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { + } + } + ++void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) { ++ ++ constantPoolHandle other_cp = constantPoolHandle(method->constants()); ++ ++ for (int i = 0; i < other_cp->length(); i++) { ++ if (other_cp->tag_at(i).is_klass()) { ++ Klass* klass = other_cp->resolved_klass_at(i); ++ if (klass->new_version() != NULL) { ++ // Constant pool entry points to redefined class -- update to the new version ++ other_cp->klass_at_put(i, klass->newest_version()); ++ } ++ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); ++ } ++ } ++ ++ ConstantPoolCache* cp_cache = other_cp->cache(); ++ if (cp_cache != NULL) { ++ cp_cache->clear_entries(); ++ } ++ ++} ++ ++ ++ + void VM_EnhancedRedefineClasses::update_jmethod_ids() { + for (int j = 0; j < _matching_methods_length; ++j) { + Method* old_method = _matching_old_methods[j]; +@@ -1979,7 +2027,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { + // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) + AffectedKlassClosure closure(_affected_klasses); + // Updated in j10, from original SystemDictionary::classes_do +- ClassLoaderDataGraph::dictionary_classes_do(&closure); ++ ++ ClassLoaderDataGraph::classes_do(&closure); ++ //ClassLoaderDataGraph::dictionary_classes_do(&closure); ++ + log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); + + // Sort the affected klasses such that a supertype is always on a smaller array index than its subtype. +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index 60b62c3170a..d8a11b51fe9 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -116,6 +116,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + void rollback(); + static void mark_as_scavengable(nmethod* nm); + static void unpatch_bytecode(Method* method); ++ static void fix_invoke_method(Method* method); + + // Figure out which new methods match old methods in name and signature, + // which methods have been added, and which are no longer present +diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp +index 122bb8c186b..81b3aa96564 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.cpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.cpp +@@ -414,6 +414,8 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) + InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); + Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); + ++ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); ++ + assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); + assert(newer_method != NULL, "method_with_idnum() should not be NULL"); + assert(old_method != newer_method, "sanity check"); +diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp +index 72d81ec9d6c..027afa3fabd 100644 +--- a/src/hotspot/share/prims/unsafe.cpp ++++ b/src/hotspot/share/prims/unsafe.cpp +@@ -865,6 +865,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, + host_loader, + &st, + cl_info, ++ NULL, + CHECK_NULL); + if (anonk == NULL) { + return NULL; +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch b/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch new file mode 100644 index 000000000000..418c656a3461 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch @@ -0,0 +1,135 @@ +From 5af1daedc86b5fec0f222cbdda3afbdf518985ea Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sat, 23 May 2020 10:02:15 +0200 +Subject: [PATCH 06/34] Fix "no original bytecode found" error if method with + bkp is missing + +Sometimes IDE can deploy class with erroneous method, such method has +n bytecode, but breakpoint position can still exist. +--- + src/hotspot/share/interpreter/bytecodes.cpp | 2 +- + .../share/interpreter/interpreterRuntime.cpp | 2 +- + src/hotspot/share/oops/method.cpp | 8 ++++---- + src/hotspot/share/oops/method.hpp | 4 ++-- + .../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++-------- + 5 files changed, 18 insertions(+), 16 deletions(-) + +diff --git a/src/hotspot/share/interpreter/bytecodes.cpp b/src/hotspot/share/interpreter/bytecodes.cpp +index e377e36b88c..262ecc021b2 100644 +--- a/src/hotspot/share/interpreter/bytecodes.cpp ++++ b/src/hotspot/share/interpreter/bytecodes.cpp +@@ -84,7 +84,7 @@ Bytecodes::Code Bytecodes::code_at(Method* method, int bci) { + Bytecodes::Code Bytecodes::non_breakpoint_code_at(const Method* method, address bcp) { + assert(method != NULL, "must have the method for breakpoint conversion"); + assert(method->contains(bcp), "must be valid bcp in method"); +- return method->orig_bytecode_at(method->bci_from(bcp)); ++ return method->orig_bytecode_at(method->bci_from(bcp), false); + } + + int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) { +diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp +index ed3cc3eb6a2..504e59caf51 100644 +--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp ++++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp +@@ -814,7 +814,7 @@ JRT_END + // Invokes + + JRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp)) +- return method->orig_bytecode_at(method->bci_from(bcp)); ++ return method->orig_bytecode_at(method->bci_from(bcp), false); + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code)) +diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp +index 516f2bb8f2f..1c88511a5fc 100644 +--- a/src/hotspot/share/oops/method.cpp ++++ b/src/hotspot/share/oops/method.cpp +@@ -1853,14 +1853,14 @@ bool CompressedLineNumberReadStream::read_pair() { + + #if INCLUDE_JVMTI + +-Bytecodes::Code Method::orig_bytecode_at(int bci) const { ++Bytecodes::Code Method::orig_bytecode_at(int bci, bool no_fatal) const { + BreakpointInfo* bp = method_holder()->breakpoints(); + for (; bp != NULL; bp = bp->next()) { + if (bp->match(this, bci)) { + return bp->orig_bytecode(); + } + } +- { ++ if (!no_fatal) { + ResourceMark rm; + fatal("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci); + } +@@ -2006,7 +2006,7 @@ BreakpointInfo::BreakpointInfo(Method* m, int bci) { + _signature_index = m->signature_index(); + _orig_bytecode = (Bytecodes::Code) *m->bcp_from(_bci); + if (_orig_bytecode == Bytecodes::_breakpoint) +- _orig_bytecode = m->orig_bytecode_at(_bci); ++ _orig_bytecode = m->orig_bytecode_at(_bci, false); + _next = NULL; + } + +@@ -2015,7 +2015,7 @@ void BreakpointInfo::set(Method* method) { + { + Bytecodes::Code code = (Bytecodes::Code) *method->bcp_from(_bci); + if (code == Bytecodes::_breakpoint) +- code = method->orig_bytecode_at(_bci); ++ code = method->orig_bytecode_at(_bci, false); + assert(orig_bytecode() == code, "original bytecode must be the same"); + } + #endif +diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp +index 83ed2d9c3c1..4d4cc6dc012 100644 +--- a/src/hotspot/share/oops/method.hpp ++++ b/src/hotspot/share/oops/method.hpp +@@ -230,7 +230,7 @@ class Method : public Metadata { + + // JVMTI breakpoints + #if !INCLUDE_JVMTI +- Bytecodes::Code orig_bytecode_at(int bci) const { ++ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const { + ShouldNotReachHere(); + return Bytecodes::_shouldnotreachhere; + } +@@ -239,7 +239,7 @@ class Method : public Metadata { + }; + u2 number_of_breakpoints() const {return 0;} + #else // !INCLUDE_JVMTI +- Bytecodes::Code orig_bytecode_at(int bci) const; ++ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const; + void set_orig_bytecode_at(int bci, Bytecodes::Code code); + void set_breakpoint(int bci); + void clear_breakpoint(int bci); +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 8b765623dcd..a859b8e1162 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -1362,14 +1362,16 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { + + if (code == Bytecodes::_breakpoint) { + int bci = method->bci_from(bcp); +- code = method->orig_bytecode_at(bci); +- java_code = Bytecodes::java_code(code); +- if (code != java_code && +- (java_code == Bytecodes::_getfield || +- java_code == Bytecodes::_putfield || +- java_code == Bytecodes::_aload_0)) { +- // Let breakpoint table handling unpatch bytecode +- method->set_orig_bytecode_at(bci, java_code); ++ code = method->orig_bytecode_at(bci, true); ++ if (code != Bytecodes::_shouldnotreachhere) { ++ java_code = Bytecodes::java_code(code); ++ if (code != java_code && ++ (java_code == Bytecodes::_getfield || ++ java_code == Bytecodes::_putfield || ++ java_code == Bytecodes::_aload_0)) { ++ // Let breakpoint table handling unpatch bytecode ++ method->set_orig_bytecode_at(bci, java_code); ++ } + } + } else { + java_code = Bytecodes::java_code(code); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch b/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch new file mode 100644 index 000000000000..a4c3f58b498e --- /dev/null +++ b/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch @@ -0,0 +1,57 @@ +From 19d2274a5dff6e6b31474252b45e5e7484f0180b Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 24 May 2020 12:07:42 +0200 +Subject: [PATCH 07/34] Replace deleted method with + Universe::throw_no_such_method_error + +--- + .../share/prims/resolvedMethodTable.cpp | 28 +++++++++---------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp +index 81b3aa96564..caf03ffe56d 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.cpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.cpp +@@ -404,25 +404,25 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) + + if (old_method->is_old()) { + ++ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); ++ Method* newer_method; ++ + // Method* new_method; + if (old_method->is_deleted()) { +- // FIXME:(DCEVM) - check if exception can be thrown +- // new_method = Universe::throw_no_such_method_error(); +- continue; +- } +- +- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); +- Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); ++ newer_method = Universe::throw_no_such_method_error(); ++ } else { ++ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); + +- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); ++ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); + +- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); +- assert(newer_method != NULL, "method_with_idnum() should not be NULL"); +- assert(old_method != newer_method, "sanity check"); ++ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); ++ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); ++ assert(old_method != newer_method, "sanity check"); + +- if (_the_table->lookup(newer_method) != NULL) { +- // old method was already adjusted if new method exists in _the_table +- continue; ++ if (_the_table->lookup(newer_method) != NULL) { ++ // old method was already adjusted if new method exists in _the_table ++ continue; ++ } + } + + java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch b/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch new file mode 100644 index 000000000000..d28e787ffdf8 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch @@ -0,0 +1,1310 @@ +From a597c7248c92aad292e681564300dc98eb72e216 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Fri, 12 Jun 2020 17:43:52 +0200 +Subject: [PATCH 08/34] Support for G1 gc + +--- + src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 20 +++ + src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 3 + + src/hotspot/share/gc/g1/g1FullCollector.cpp | 16 +- + .../share/gc/g1/g1FullGCCompactTask.cpp | 92 +++++++++- + .../share/gc/g1/g1FullGCCompactTask.hpp | 19 +++ + .../share/gc/g1/g1FullGCCompactionPoint.cpp | 85 +++++++++- + .../share/gc/g1/g1FullGCCompactionPoint.hpp | 11 ++ + .../share/gc/g1/g1FullGCPrepareTask.cpp | 90 +++++++++- + .../share/gc/g1/g1FullGCPrepareTask.hpp | 13 ++ + src/hotspot/share/gc/g1/heapRegion.hpp | 10 ++ + src/hotspot/share/gc/serial/genMarkSweep.cpp | 4 +- + src/hotspot/share/gc/serial/markSweep.cpp | 97 ----------- + src/hotspot/share/gc/serial/markSweep.hpp | 3 - + src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 159 ++++++++++++++++++ + src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 49 ++++++ + src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- + src/hotspot/share/gc/shared/space.inline.hpp | 3 +- + src/hotspot/share/memory/universe.cpp | 5 + + .../prims/jvmtiEnhancedRedefineClasses.cpp | 80 ++++++--- + .../prims/jvmtiEnhancedRedefineClasses.hpp | 6 +- + src/hotspot/share/runtime/arguments.cpp | 4 +- + src/hotspot/share/utilities/growableArray.hpp | 4 + + 22 files changed, 628 insertions(+), 147 deletions(-) + create mode 100644 src/hotspot/share/gc/shared/dcevmSharedGC.cpp + create mode 100644 src/hotspot/share/gc/shared/dcevmSharedGC.hpp + +diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +index e8cdd861cbb..a29d2dddc2d 100644 +--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp ++++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +@@ -2352,6 +2352,21 @@ public: + } + }; + ++class G1IterateObjectClosureTask : public AbstractGangTask { ++ private: ++ ObjectClosure* _cl; ++ G1CollectedHeap* _g1h; ++ HeapRegionClaimer _hrclaimer; ++ public: ++ G1IterateObjectClosureTask(ObjectClosure* cl, G1CollectedHeap* g1h) : AbstractGangTask("IterateObject Closure"), ++ _cl(cl), _g1h(g1h), _hrclaimer(g1h->workers()->active_workers()) { } ++ ++ virtual void work(uint worker_id) { ++ IterateObjectClosureRegionClosure blk(_cl); ++ _g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id); ++ } ++}; ++ + void G1CollectedHeap::object_iterate(ObjectClosure* cl) { + IterateObjectClosureRegionClosure blk(cl); + heap_region_iterate(&blk); +@@ -2365,6 +2380,11 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { + _hrm->iterate(cl); + } + ++void G1CollectedHeap::object_par_iterate(ObjectClosure* cl) { ++ G1IterateObjectClosureTask iocl_task(cl, this); ++ workers()->run_task(&iocl_task); ++} ++ + void G1CollectedHeap::heap_region_par_iterate_from_worker_offset(HeapRegionClosure* cl, + HeapRegionClaimer *hrclaimer, + uint worker_id) const { +diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +index 71f89d09184..adb97ee260a 100644 +--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp ++++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +@@ -146,6 +146,7 @@ class G1CollectedHeap : public CollectedHeap { + friend class G1ParScanThreadStateSet; + friend class G1EvacuateRegionsTask; + friend class G1PLABAllocator; ++ friend class G1FullGCPrepareTask; + + // Other related classes. + friend class HeapRegionClaimer; +@@ -1168,6 +1169,8 @@ public: + + // Iteration functions. + ++ void object_par_iterate(ObjectClosure* cl); ++ + // Iterate over all objects, calling "cl.do_object" on each. + virtual void object_iterate(ObjectClosure* cl); + +diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp +index 0242e45eef5..707fe8844d0 100644 +--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp ++++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp +@@ -237,8 +237,12 @@ void G1FullCollector::phase2_prepare_compaction() { + run_task(&task); + + // To avoid OOM when there is memory left. +- if (!task.has_freed_regions()) { +- task.prepare_serial_compaction(); ++ if (!Universe::is_redefining_gc_run()) { ++ if (!task.has_freed_regions()) { ++ task.prepare_serial_compaction(); ++ } ++ } else { ++ task.prepare_serial_compaction_dcevm(); + } + } + +@@ -257,8 +261,12 @@ void G1FullCollector::phase4_do_compaction() { + run_task(&task); + + // Serial compact to avoid OOM when very few free regions. +- if (serial_compaction_point()->has_regions()) { +- task.serial_compaction(); ++ if (!Universe::is_redefining_gc_run()) { ++ if (serial_compaction_point()->has_regions()) { ++ task.serial_compaction(); ++ } ++ } else { ++ task.serial_compaction_dcevm(); + } + } + +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +index 97742d26ee9..f70f4606dc8 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +@@ -30,6 +30,7 @@ + #include "gc/g1/g1FullGCCompactTask.hpp" + #include "gc/g1/heapRegion.inline.hpp" + #include "gc/shared/gcTraceTime.inline.hpp" ++#include "gc/shared/dcevmSharedGC.hpp" + #include "logging/log.hpp" + #include "oops/oop.inline.hpp" + #include "utilities/ticks.hpp" +@@ -90,12 +91,30 @@ void G1FullGCCompactTask::compact_region(HeapRegion* hr) { + void G1FullGCCompactTask::work(uint worker_id) { + Ticks start = Ticks::now(); + GrowableArray* compaction_queue = collector()->compaction_point(worker_id)->regions(); +- for (GrowableArrayIterator it = compaction_queue->begin(); +- it != compaction_queue->end(); +- ++it) { +- compact_region(*it); ++ ++ if (!Universe::is_redefining_gc_run()) { ++ for (GrowableArrayIterator it = compaction_queue->begin(); ++ it != compaction_queue->end(); ++ ++it) { ++ compact_region(*it); ++ } ++ } else { ++ GrowableArrayIterator rescue_oops_it = collector()->compaction_point(worker_id)->rescued_oops()->begin(); ++ GrowableArray* rescued_oops_values = collector()->compaction_point(worker_id)->rescued_oops_values(); ++ ++ for (GrowableArrayIterator it = compaction_queue->begin(); ++ it != compaction_queue->end(); ++ ++it) { ++ compact_region_dcevm(*it, rescued_oops_values, &rescue_oops_it); ++ } ++ assert(rescue_oops_it.at_end(), "Must be at end"); ++ G1FullGCCompactionPoint* cp = collector()->compaction_point(worker_id); ++ if (cp->last_rescued_oop() > 0) { ++ DcevmSharedGC::copy_rescued_objects_back(rescued_oops_values, 0, cp->last_rescued_oop(), false); ++ } + } + ++ // TODO: (DCEV) check it + G1ResetHumongousClosure hc(collector()->mark_bitmap()); + G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&hc, &_claimer, worker_id); + log_task("Compaction task", worker_id, start); +@@ -110,3 +129,68 @@ void G1FullGCCompactTask::serial_compaction() { + compact_region(*it); + } + } ++ ++void G1FullGCCompactTask::compact_region_dcevm(HeapRegion* hr, GrowableArray* rescued_oops_values, ++ GrowableArrayIterator* rescue_oops_it) { ++ assert(!hr->is_humongous(), "Should be no humongous regions in compaction queue"); ++ ResourceMark rm; // ++ ++ G1CompactRegionClosureDcevm compact(collector()->mark_bitmap(), rescued_oops_values, rescue_oops_it); ++ hr->apply_to_marked_objects(collector()->mark_bitmap(), &compact); ++ // Once all objects have been moved the liveness information ++ // needs be cleared. ++ collector()->mark_bitmap()->clear_region(hr); ++ hr->complete_compaction(); ++} ++ ++void G1FullGCCompactTask::serial_compaction_dcevm() { ++ GCTraceTime(Debug, gc, phases) tm("Phase 4: Serial Compaction", collector()->scope()->timer()); ++ ++ // compact remaining, not parallel compacted rescued oops using serial compact point ++ ++ for (uint i = 0; i < collector()->workers(); i++) { ++ G1FullGCCompactionPoint* cp = collector()->compaction_point(i); ++ DcevmSharedGC::clear_rescued_objects_heap(cp->rescued_oops_values()); ++ } ++ ++} ++ ++size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) { ++ size_t size = obj->size(); ++ HeapWord* destination = (HeapWord*)obj->forwardee(); ++ if (destination == NULL) { ++ // Object not moving ++ return size; ++ } ++ ++ // copy object and reinit its mark ++ HeapWord* obj_addr = (HeapWord*) obj; ++ ++ if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) { ++ ++(*_rescue_oops_it); ++ HeapWord* rescued_obj = NEW_C_HEAP_ARRAY(HeapWord, size, mtInternal); ++ Copy::aligned_disjoint_words(obj_addr, rescued_obj, size); ++ _rescued_oops_values->append(rescued_obj); ++ debug_only(Copy::fill_to_words(obj_addr, size, 0)); ++ return size; ++ } ++ ++ if (obj->klass()->new_version() != NULL) { ++ Klass* new_version = obj->klass()->new_version(); ++ if (new_version->update_information() == NULL) { ++ Copy::aligned_conjoint_words(obj_addr, destination, size); ++ oop(destination)->set_klass(new_version); ++ } else { ++ DcevmSharedGC::update_fields(obj, oop(destination)); ++ } ++ oop(destination)->init_mark_raw(); ++ assert(oop(destination)->klass() != NULL, "should have a class"); ++ return size; ++ } ++ ++ Copy::aligned_conjoint_words(obj_addr, destination, size); ++ oop(destination)->init_mark_raw(); ++ assert(oop(destination)->klass() != NULL, "should have a class"); ++ ++ return size; ++} +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp +index 6c8eaf5967e..ea52a2db8cc 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp +@@ -41,6 +41,8 @@ protected: + + private: + void compact_region(HeapRegion* hr); ++ void compact_region_dcevm(HeapRegion* hr, GrowableArray* rescued_oops_values, ++ GrowableArrayIterator* rescue_oops_it); + + public: + G1FullGCCompactTask(G1FullCollector* collector) : +@@ -48,6 +50,7 @@ public: + _claimer(collector->workers()) { } + void work(uint worker_id); + void serial_compaction(); ++ void serial_compaction_dcevm(); + + class G1CompactRegionClosure : public StackObj { + G1CMBitMap* _bitmap; +@@ -56,6 +59,22 @@ public: + G1CompactRegionClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { } + size_t apply(oop object); + }; ++ ++ class G1CompactRegionClosureDcevm : public StackObj { ++ G1CMBitMap* _bitmap; ++ GrowableArray* _rescued_oops_values; ++ GrowableArrayIterator* _rescue_oops_it; ++ ++ public: ++ G1CompactRegionClosureDcevm(G1CMBitMap* bitmap, ++ GrowableArray* rescued_oops_values, ++ GrowableArrayIterator* rescue_oops_it) : ++ _bitmap(bitmap), ++ _rescued_oops_values(rescued_oops_values), ++ _rescue_oops_it(rescue_oops_it) ++ { } ++ size_t apply(oop object); ++ }; + }; + + #endif // SHARE_GC_G1_G1FULLGCCOMPACTTASK_HPP +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +index 269d14d8b73..1e49571c999 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +@@ -31,13 +31,19 @@ + G1FullGCCompactionPoint::G1FullGCCompactionPoint() : + _current_region(NULL), + _threshold(NULL), +- _compaction_top(NULL) { ++ _compaction_top(NULL), ++ _last_rescued_oop(0) ++{ + _compaction_regions = new (ResourceObj::C_HEAP, mtGC) GrowableArray(32, true, mtGC); + _compaction_region_iterator = _compaction_regions->begin(); ++ _rescued_oops = new (ResourceObj::C_HEAP, mtGC) GrowableArray(128, true, mtGC); ++ _rescued_oops_values = new (ResourceObj::C_HEAP, mtGC) GrowableArray(128, true, mtGC); + } + + G1FullGCCompactionPoint::~G1FullGCCompactionPoint() { + delete _compaction_regions; ++ delete _rescued_oops; ++ delete _rescued_oops_values; + } + + void G1FullGCCompactionPoint::update() { +@@ -80,6 +86,14 @@ GrowableArray* G1FullGCCompactionPoint::regions() { + return _compaction_regions; + } + ++GrowableArray* G1FullGCCompactionPoint::rescued_oops() { ++ return _rescued_oops; ++} ++ ++GrowableArray* G1FullGCCompactionPoint::rescued_oops_values() { ++ return _rescued_oops_values; ++} ++ + bool G1FullGCCompactionPoint::object_will_fit(size_t size) { + size_t space_left = pointer_delta(_current_region->end(), _compaction_top); + return size <= space_left; +@@ -143,3 +157,72 @@ void G1FullGCCompactionPoint::merge(G1FullGCCompactionPoint* other) { + HeapRegion* G1FullGCCompactionPoint::remove_last() { + return _compaction_regions->pop(); + } ++ ++HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) { ++ assert(_current_region != NULL, "Must have been initialized"); ++ // Ensure the object fit in the current region. ++ while (!object_will_fit(size)) { ++ if (!_compaction_region_iterator.has_next()) { ++ return NULL; ++ } ++ switch_region(); ++ } ++ return _compaction_top; ++} ++ ++void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_forward) { ++ assert(_current_region != NULL, "Must have been initialized"); ++ ++ // Store a forwarding pointer if the object should be moved. ++ if ((HeapWord*)object != _compaction_top || force_forward) { ++ object->forward_to(oop(_compaction_top)); ++ } else { ++ if (object->forwardee() != NULL) { ++ // Object should not move but mark-word is used so it looks like the ++ // object is forwarded. Need to clear the mark and it's no problem ++ // since it will be restored by preserved marks. There is an exception ++ // with BiasedLocking, in this case forwardee() will return NULL ++ // even if the mark-word is used. This is no problem since ++ // forwardee() will return NULL in the compaction phase as well. ++ object->init_mark_raw(); ++ } else { ++ // Make sure object has the correct mark-word set or that it will be ++ // fixed when restoring the preserved marks. ++ assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark ++ object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet ++ (UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking ++ "should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT, ++ p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object))); ++ } ++ assert(object->forwardee() == NULL, "should be forwarded to NULL"); ++ } ++ ++ // Update compaction values. ++ _compaction_top += size; ++ if (_compaction_top > _threshold) { ++ _threshold = _current_region->cross_threshold(_compaction_top - size, _compaction_top); ++ } ++} ++ ++void G1FullGCCompactionPoint::forward_rescued() { ++ int i; ++ ++ i = _last_rescued_oop; ++ ++ for (;ilength(); i++) { ++ HeapWord* q = rescued_oops()->at(i); ++ ++ size_t size = oop(q)->size(); ++ ++ // (DCEVM) There is a new version of the class of q => different size ++ if (oop(q)->klass()->new_version() != NULL) { ++ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); ++ size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); ++ } ++ if (forward_compact_top(size) == NULL) { ++ break; ++ } ++ forward_dcevm(oop(q), size, true); ++ } ++ _last_rescued_oop = i; ++} +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp +index 0ec0b324aab..a55a37f96c0 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp +@@ -37,6 +37,9 @@ class G1FullGCCompactionPoint : public CHeapObj { + HeapWord* _compaction_top; + GrowableArray* _compaction_regions; + GrowableArrayIterator _compaction_region_iterator; ++ GrowableArray* _rescued_oops; ++ GrowableArray* _rescued_oops_values; ++ int _last_rescued_oop; + + bool object_will_fit(size_t size); + void initialize_values(bool init_threshold); +@@ -52,6 +55,8 @@ public: + void initialize(HeapRegion* hr, bool init_threshold); + void update(); + void forward(oop object, size_t size); ++ HeapWord* forward_compact_top(size_t size); ++ void forward_dcevm(oop object, size_t size, bool force_forward); + void add(HeapRegion* hr); + void merge(G1FullGCCompactionPoint* other); + +@@ -59,6 +64,12 @@ public: + HeapRegion* current_region(); + + GrowableArray* regions(); ++ ++ GrowableArray* rescued_oops(); ++ GrowableArray* rescued_oops_values(); ++ ++ void forward_rescued(); ++ int last_rescued_oop() { return _last_rescued_oop; } + }; + + #endif // SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP +diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +index 3658ae200d9..a45681b60cf 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +@@ -40,6 +40,7 @@ + #include "utilities/ticks.hpp" + + bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) { ++ hr->set_processing_order(_region_processing_order++); + if (hr->is_humongous()) { + oop obj = oop(hr->humongous_start_region()->bottom()); + if (_bitmap->is_marked(obj)) { +@@ -49,7 +50,7 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* + } else { + free_humongous_region(hr); + } +- } else if (!hr->is_pinned()) { ++ } else if (!hr->is_pinned()) { // TODO: (DCEVM) review pinned + prepare_for_compaction(hr); + } + +@@ -81,6 +82,10 @@ void G1FullGCPrepareTask::work(uint worker_id) { + G1CalculatePointersClosure closure(collector()->mark_bitmap(), compaction_point); + G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer); + ++ if (Universe::is_redefining_gc_run()) { ++ compaction_point->forward_rescued(); ++ } ++ + // Update humongous region sets + closure.update_sets(); + compaction_point->update(); +@@ -97,7 +102,8 @@ G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1CM + _g1h(G1CollectedHeap::heap()), + _bitmap(bitmap), + _cp(cp), +- _humongous_regions_removed(0) { } ++ _humongous_regions_removed(0), ++ _region_processing_order(0) { } + + void G1FullGCPrepareTask::G1CalculatePointersClosure::free_humongous_region(HeapRegion* hr) { + FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); +@@ -146,9 +152,15 @@ size_t G1FullGCPrepareTask::G1RePrepareClosure::apply(oop obj) { + + void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction_work(G1FullGCCompactionPoint* cp, + HeapRegion* hr) { +- G1PrepareCompactLiveClosure prepare_compact(cp); +- hr->set_compaction_top(hr->bottom()); +- hr->apply_to_marked_objects(_bitmap, &prepare_compact); ++ if (!Universe::is_redefining_gc_run()) { ++ G1PrepareCompactLiveClosure prepare_compact(cp); ++ hr->set_compaction_top(hr->bottom()); ++ hr->apply_to_marked_objects(_bitmap, &prepare_compact); ++ } else { ++ G1PrepareCompactLiveClosureDcevm prepare_compact(cp, hr->processing_order()); ++ hr->set_compaction_top(hr->bottom()); ++ hr->apply_to_marked_objects(_bitmap, &prepare_compact); ++ } + } + + void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) { +@@ -219,3 +231,71 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::freed_regions() { + // No free regions in the queue. + return false; + } ++ ++void G1FullGCPrepareTask::prepare_serial_compaction_dcevm() { ++ GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare Serial Compaction", collector()->scope()->timer()); ++ ++ for (uint i = 0; i < collector()->workers(); i++) { ++ G1FullGCCompactionPoint* cp = collector()->compaction_point(i); ++ ++ // collect remaining, not forwarded rescued oops using serial compact point ++ while (cp->last_rescued_oop() < cp->rescued_oops()->length()) { ++ HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, false, true); ++ if (hr == NULL) { ++ vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "G1 - not enough of free regions after redefinition."); ++ } ++ hr->set_compaction_top(hr->bottom()); ++ cp->add(hr); ++ cp->forward_rescued(); ++ cp->update(); ++ } ++ } ++} ++ ++G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::G1PrepareCompactLiveClosureDcevm(G1FullGCCompactionPoint* cp, ++ uint region_processing_order) : ++ _cp(cp), ++ _region_processing_order(region_processing_order) { } ++ ++size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object) { ++ size_t size = object->size(); ++ size_t forward_size = size; ++ ++ // (DCEVM) There is a new version of the class of q => different size ++ if (object->klass()->new_version() != NULL) { ++ forward_size = object->size_given_klass(object->klass()->new_version()); ++ } ++ ++ HeapWord* compact_top = _cp->forward_compact_top(forward_size); ++ ++ if (compact_top == NULL || must_rescue(object, oop(compact_top))) { ++ _cp->rescued_oops()->append((HeapWord*)object); ++ } else { ++ _cp->forward_dcevm(object, forward_size, (size != forward_size)); ++ } ++ ++ return size; ++} ++ ++bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_obj, oop new_obj) { ++ // Only redefined objects can have the need to be rescued. ++ if (oop(old_obj)->klass()->new_version() == NULL) { ++ return false; ++ } ++ ++ if (_region_processing_order > _cp->current_region()->processing_order()) { ++ return false; ++ } ++ ++ if (_region_processing_order < _cp->current_region()->processing_order()) { ++ return true; ++ } ++ ++ // old obj and new obj are within same region ++ int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); ++ int original_size = old_obj->size(); ++ ++ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); ++ ++ return overlap; ++} +diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp +index fcaf797a12f..98a8fa58bbc 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp ++++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp +@@ -46,6 +46,7 @@ public: + G1FullGCPrepareTask(G1FullCollector* collector); + void work(uint worker_id); + void prepare_serial_compaction(); ++ void prepare_serial_compaction_dcevm(); + bool has_freed_regions(); + + protected: +@@ -55,6 +56,7 @@ protected: + G1CMBitMap* _bitmap; + G1FullGCCompactionPoint* _cp; + uint _humongous_regions_removed; ++ uint _region_processing_order; + + virtual void prepare_for_compaction(HeapRegion* hr); + void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr); +@@ -78,6 +80,16 @@ protected: + size_t apply(oop object); + }; + ++ class G1PrepareCompactLiveClosureDcevm : public StackObj { ++ G1FullGCCompactionPoint* _cp; ++ uint _region_processing_order; ++ ++ bool must_rescue(oop old_obj, oop new_obj); ++ public: ++ G1PrepareCompactLiveClosureDcevm(G1FullGCCompactionPoint* cp, uint region_processing_order); ++ size_t apply(oop object); ++ }; ++ + class G1RePrepareClosure : public StackObj { + G1FullGCCompactionPoint* _cp; + HeapRegion* _current; +@@ -90,6 +102,7 @@ protected: + + size_t apply(oop object); + }; ++ + }; + + #endif // SHARE_GC_G1_G1FULLGCPREPARETASK_HPP +diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp +index 5bf94460540..ec6c5cf8751 100644 +--- a/src/hotspot/share/gc/g1/heapRegion.hpp ++++ b/src/hotspot/share/gc/g1/heapRegion.hpp +@@ -199,6 +199,8 @@ private: + // The remembered set for this region. + HeapRegionRemSet* _rem_set; + ++ uint _processing_order; ++ + // Cached index of this region in the heap region sequence. + const uint _hrm_index; + +@@ -452,6 +454,14 @@ public: + return _rem_set; + } + ++ uint processing_order() { ++ return _processing_order; ++ } ++ ++ void set_processing_order(uint processing_order) { ++ _processing_order = processing_order; ++ } ++ + inline bool in_collection_set() const; + + // Methods used by the HeapRegionSetBase class and subclasses. +diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp +index 72f571645a5..1d13c647452 100644 +--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp ++++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp +@@ -334,5 +334,7 @@ void GenMarkSweep::mark_sweep_phase4() { + + GenCompactClosure blk; + gch->generation_iterate(&blk, true); +- MarkSweep::copy_rescued_objects_back(); ++ DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); ++ DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); ++ MarkSweep::_rescued_oops = NULL; + } +diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp +index c7befd2f63d..c0108bad092 100644 +--- a/src/hotspot/share/gc/serial/markSweep.cpp ++++ b/src/hotspot/share/gc/serial/markSweep.cpp +@@ -224,100 +224,3 @@ void MarkSweep::initialize() { + MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); + MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); + } +- +-// (DCEVM) Copy the rescued objects to their destination address after compaction. +-void MarkSweep::copy_rescued_objects_back() { +- +- if (_rescued_oops != NULL) { +- +- for (int i=0; i<_rescued_oops->length(); i++) { +- HeapWord* rescued_ptr = _rescued_oops->at(i); +- oop rescued_obj = (oop) rescued_ptr; +- +- int size = rescued_obj->size(); +- oop new_obj = rescued_obj->forwardee(); +- +- assert(rescued_obj->klass()->new_version() != NULL, "just checking"); +- +- if (rescued_obj->klass()->new_version()->update_information() != NULL) { +- MarkSweep::update_fields(rescued_obj, new_obj); +- } else { +- rescued_obj->set_klass(rescued_obj->klass()->new_version()); +- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); +- } +- +- FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); +- +- new_obj->init_mark(); +- assert(oopDesc::is_oop(new_obj), "must be a valid oop"); +- } +- _rescued_oops->clear(); +- _rescued_oops = NULL; +- } +-} +- +-// (DCEVM) Update instances of a class whose fields changed. +-void MarkSweep::update_fields(oop q, oop new_location) { +- +- assert(q->klass()->new_version() != NULL, "class of old object must have new version"); +- +- Klass* old_klass_oop = q->klass(); +- Klass* new_klass_oop = q->klass()->new_version(); +- +- InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); +- InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); +- +- int size = q->size_given_klass(old_klass); +- int new_size = q->size_given_klass(new_klass); +- +- HeapWord* tmp = NULL; +- oop tmp_obj = q; +- +- // Save object somewhere, there is an overlap in fields +- if (new_klass_oop->is_copying_backwards()) { +- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || +- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { +- tmp = NEW_RESOURCE_ARRAY(HeapWord, size); +- q = (oop) tmp; +- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); +- } +- } +- +- q->set_klass(new_klass_oop); +- int *cur = new_klass_oop->update_information(); +- assert(cur != NULL, "just checking"); +- MarkSweep::update_fields(new_location, q, cur); +- +- if (tmp != NULL) { +- FREE_RESOURCE_ARRAY(HeapWord, tmp, size); +- } +-} +- +-void MarkSweep::update_fields(oop new_location, oop tmp_obj, int *cur) { +- assert(cur != NULL, "just checking"); +- char* to = (char*)(HeapWord*)new_location; +- while (*cur != 0) { +- int size = *cur; +- if (size > 0) { +- cur++; +- int offset = *cur; +- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); +- if (size == HeapWordSize) { +- *((HeapWord*)to) = *from; +- } else if (size == HeapWordSize * 2) { +- *((HeapWord*)to) = *from; +- *(((HeapWord*)to) + 1) = *(from + 1); +- } else { +- Copy::conjoint_jbytes(from, to, size); +- } +- to += size; +- cur++; +- } else { +- assert(size < 0, ""); +- int skip = -*cur; +- Copy::fill_to_bytes(to, skip, 0); +- to += skip; +- cur++; +- } +- } +-} +diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp +index e12ac327d90..92af0e36a1c 100644 +--- a/src/hotspot/share/gc/serial/markSweep.hpp ++++ b/src/hotspot/share/gc/serial/markSweep.hpp +@@ -148,9 +148,6 @@ class MarkSweep : AllStatic { + + static int adjust_pointers(oop obj); + +- static void copy_rescued_objects_back(); +- static void update_fields(oop q, oop new_location); +- static void update_fields(oop new_location, oop tmp_obj, int *cur); + static void follow_stack(); // Empty marking stack. + + static void follow_klass(Klass* klass); +diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp +new file mode 100644 +index 00000000000..803e645f843 +--- /dev/null ++++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (c) 1997, 2018, 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/shared/dcevmSharedGC.hpp" ++#include "memory/iterator.inline.hpp" ++#include "oops/access.inline.hpp" ++#include "oops/compressedOops.inline.hpp" ++#include "oops/instanceClassLoaderKlass.inline.hpp" ++#include "oops/instanceKlass.inline.hpp" ++#include "oops/instanceMirrorKlass.inline.hpp" ++#include "oops/instanceRefKlass.inline.hpp" ++#include "oops/oop.inline.hpp" ++#include "utilities/macros.hpp" ++ ++void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_oops, bool must_be_new) { ++ if (rescued_oops != NULL) { ++ copy_rescued_objects_back(rescued_oops, 0, rescued_oops->length(), must_be_new); ++ } ++} ++ ++// (DCEVM) Copy the rescued objects to their destination address after compaction. ++void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_oops, int from, int to, bool must_be_new) { ++ ++ if (rescued_oops != NULL) { ++ for (int i=from; i < to; i++) { ++ HeapWord* rescued_ptr = rescued_oops->at(i); ++ oop rescued_obj = (oop) rescued_ptr; ++ ++ int size = rescued_obj->size(); ++ oop new_obj = rescued_obj->forwardee(); ++ ++ assert(!must_be_new || rescued_obj->klass()->new_version() != NULL, "Just checking"); ++ Klass* new_klass = rescued_obj->klass()->new_version(); ++ if (new_klass!= NULL) { ++ if (new_klass->update_information() != NULL) { ++ DcevmSharedGC::update_fields(rescued_obj, new_obj); ++ } else { ++ rescued_obj->set_klass(new_klass); ++ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); ++ } ++ } else { ++ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); ++ } ++ ++ new_obj->init_mark_raw(); ++ assert(oopDesc::is_oop(new_obj), "must be a valid oop"); ++ } ++ } ++ ++} ++ ++void DcevmSharedGC::clear_rescued_objects_resource(GrowableArray* rescued_oops) { ++ if (rescued_oops != NULL) { ++ for (int i=0; i < rescued_oops->length(); i++) { ++ HeapWord* rescued_ptr = rescued_oops->at(i); ++ int size = ((oop) rescued_ptr)->size(); ++ FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); ++ } ++ rescued_oops->clear(); ++ } ++} ++ ++void DcevmSharedGC::clear_rescued_objects_heap(GrowableArray* rescued_oops) { ++ if (rescued_oops != NULL) { ++ for (int i=0; i < rescued_oops->length(); i++) { ++ HeapWord* rescued_ptr = rescued_oops->at(i); ++ FREE_C_HEAP_ARRAY(HeapWord, rescued_ptr); ++ } ++ rescued_oops->clear(); ++ } ++} ++ ++// (DCEVM) Update instances of a class whose fields changed. ++void DcevmSharedGC::update_fields(oop q, oop new_location) { ++ ++ assert(q->klass()->new_version() != NULL, "class of old object must have new version"); ++ ++ Klass* old_klass_oop = q->klass(); ++ Klass* new_klass_oop = q->klass()->new_version(); ++ ++ InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); ++ InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); ++ ++ int size = q->size_given_klass(old_klass); ++ int new_size = q->size_given_klass(new_klass); ++ ++ HeapWord* tmp = NULL; ++ oop tmp_obj = q; ++ ++ // Save object somewhere, there is an overlap in fields ++ if (new_klass_oop->is_copying_backwards()) { ++ if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || ++ ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { ++ tmp = NEW_RESOURCE_ARRAY(HeapWord, size); ++ q = (oop) tmp; ++ Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); ++ } ++ } ++ ++ q->set_klass(new_klass_oop); ++ int *cur = new_klass_oop->update_information(); ++ assert(cur != NULL, "just checking"); ++ DcevmSharedGC::update_fields(new_location, q, cur); ++ ++ if (tmp != NULL) { ++ FREE_RESOURCE_ARRAY(HeapWord, tmp, size); ++ } ++} ++ ++void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) { ++ assert(cur != NULL, "just checking"); ++ char* to = (char*)(HeapWord*)new_location; ++ while (*cur != 0) { ++ int size = *cur; ++ if (size > 0) { ++ cur++; ++ int offset = *cur; ++ HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); ++ if (size == HeapWordSize) { ++ *((HeapWord*)to) = *from; ++ } else if (size == HeapWordSize * 2) { ++ *((HeapWord*)to) = *from; ++ *(((HeapWord*)to) + 1) = *(from + 1); ++ } else { ++ Copy::conjoint_jbytes(from, to, size); ++ } ++ to += size; ++ cur++; ++ } else { ++ assert(size < 0, ""); ++ int skip = -*cur; ++ Copy::fill_to_bytes(to, skip, 0); ++ to += skip; ++ cur++; ++ } ++ } ++} +diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp +new file mode 100644 +index 00000000000..e2ef0171fb2 +--- /dev/null ++++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (c) 1997, 2018, 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_GC_DCEVM_SHARED_GC_HPP ++#define SHARE_GC_DCEVM_SHARED_GC_HPP ++ ++#include "gc/shared/collectedHeap.hpp" ++#include "gc/shared/genOopClosures.hpp" ++#include "gc/shared/taskqueue.hpp" ++#include "memory/iterator.hpp" ++#include "oops/markOop.hpp" ++#include "oops/oop.hpp" ++#include "runtime/timer.hpp" ++#include "utilities/growableArray.hpp" ++#include "utilities/stack.hpp" ++ ++// Shared GC code used from different GC (Serial, CMS, G1) on enhanced redefinition ++class DcevmSharedGC : AllStatic { ++ public: ++ static void copy_rescued_objects_back(GrowableArray* rescued_oops, bool must_be_new); ++ static void copy_rescued_objects_back(GrowableArray* rescued_oops, int from, int to, bool must_be_new); ++ static void clear_rescued_objects_resource(GrowableArray* rescued_oops); ++ static void clear_rescued_objects_heap(GrowableArray* rescued_oops); ++ static void update_fields(oop q, oop new_location); ++ static void update_fields(oop new_location, oop tmp_obj, int *cur); ++}; ++ ++#endif +diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp +index fdb1c806559..f01d64d1434 100644 +--- a/src/hotspot/share/gc/shared/gcConfig.cpp ++++ b/src/hotspot/share/gc/shared/gcConfig.cpp +@@ -98,7 +98,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { + } + + void GCConfig::select_gc_ergonomically() { +- if (AllowEnhancedClassRedefinition) { ++ if (AllowEnhancedClassRedefinition && !UseG1GC) { + // Enhanced class redefinition only supports serial GC at the moment + FLAG_SET_ERGO(bool, UseSerialGC, true); + } else if (os::is_server_class_machine()) { +diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp +index 875c3fdf319..5a93e93471b 100644 +--- a/src/hotspot/share/gc/shared/space.inline.hpp ++++ b/src/hotspot/share/gc/shared/space.inline.hpp +@@ -37,6 +37,7 @@ + #if INCLUDE_SERIALGC + #include "gc/serial/markSweep.inline.hpp" + #endif ++#include "gc/shared/dcevmSharedGC.hpp" + + inline HeapWord* Space::block_start(const void* p) { + return block_start_const(p); +@@ -369,7 +370,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti + Copy::aligned_conjoint_words(cur_obj, compaction_top, size); + oop(compaction_top)->set_klass(new_version); + } else { +- MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); ++ DcevmSharedGC::update_fields(oop(cur_obj), oop(compaction_top)); + } + oop(compaction_top)->init_mark_raw(); + assert(oop(compaction_top)->klass() != NULL, "should have a class"); +diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp +index d38cd348e1b..f6e4253b5a5 100644 +--- a/src/hotspot/share/memory/universe.cpp ++++ b/src/hotspot/share/memory/universe.cpp +@@ -212,6 +212,11 @@ void Universe::root_oops_do(OopClosure *oopClosure) { + //ref_processor()->weak_oops_do(&oopClosure); + //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); + ++#if INCLUDE_AOT ++ if (UseAOT) { ++ AOTLoader::oops_do(oopClosure); ++ } ++#endif + // SO_AllClasses + SystemDictionary::oops_do(oopClosure); + } +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index a859b8e1162..6c9eb40ecf5 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -36,7 +36,6 @@ + #include "memory/metaspaceShared.hpp" + #include "memory/resourceArea.hpp" + #include "memory/iterator.inline.hpp" +-#include "gc/serial/markSweep.hpp" + #include "oops/fieldStreams.hpp" + #include "oops/klassVtable.hpp" + #include "oops/oop.inline.hpp" +@@ -54,6 +53,8 @@ + #include "prims/jvmtiThreadState.inline.hpp" + #include "utilities/events.hpp" + #include "oops/constantPool.inline.hpp" ++#include "gc/g1/g1CollectedHeap.hpp" ++#include "gc/shared/dcevmSharedGC.hpp" + + Array* VM_EnhancedRedefineClasses::_old_methods = NULL; + Array* VM_EnhancedRedefineClasses::_new_methods = NULL; +@@ -77,7 +78,7 @@ Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; + // - class_defs class definition - either new class or redefined class + // note that this is not the final array of classes to be redefined + // we need to scan for all affected classes (e.g. subclasses) and +-// caculcate redefinition for them as well. ++// calculate redefinition for them as well. + // @param class_load_kind always jvmti_class_load_kind_redefine + VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : + VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { +@@ -215,6 +216,13 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { + } + } + ++void VM_EnhancedRedefineClasses::mark_as_scavengable_g1(nmethod* nm) { ++ // It should work not only for G1 but also for another GCs, but this way is safer now ++ if (!nm->is_zombie() && !nm->is_unloaded()) { ++ Universe::heap()->register_nmethod(nm); ++ } ++} ++ + // TODO comment + struct StoreBarrier { + // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store +@@ -431,12 +439,7 @@ public: + src->set_klass(obj->klass()->new_version()); + // FIXME: instance updates... + //guarantee(false, "instance updates!"); +- MarkSweep::update_fields(obj, src, new_klass->update_information()); +- +- if (size_diff > 0) { +- HeapWord* dead_space = ((HeapWord *)obj) + obj->size(); +- CollectedHeap::fill_with_object(dead_space, size_diff); +- } ++ DcevmSharedGC::update_fields(obj, src, new_klass->update_information()); + } + } else { + obj->set_klass(obj->klass()->new_version()); +@@ -458,6 +461,10 @@ public: + void VM_EnhancedRedefineClasses::doit() { + Thread *thread = Thread::current(); + ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_vm_op_doit.start(); ++ } ++ + #if INCLUDE_CDS + if (UseSharedSpaces) { + // Sharing is enabled so we remap the shared readonly space to +@@ -513,12 +520,31 @@ void VM_EnhancedRedefineClasses::doit() { + // mark such nmethod's as "scavengable". + // For now, mark all nmethod's as scavengable that are not scavengable already + if (ScavengeRootsInCode) { +- CodeCache::nmethods_do(mark_as_scavengable); ++ if (UseG1GC) { ++ // this should work also for other GCs ++ CodeCache::nmethods_do(mark_as_scavengable_g1); ++ } else { ++ CodeCache::nmethods_do(mark_as_scavengable); ++ } + } + + Universe::heap()->ensure_parsability(false); +- Universe::heap()->object_iterate(&objectClosure); ++ if (UseG1GC) { ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_heap_iterate.start(); ++ } ++ G1CollectedHeap::heap()->object_par_iterate(&objectClosure); ++ _timer_heap_iterate.stop(); ++ } else { ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_heap_iterate.start(); ++ } ++ Universe::heap()->object_iterate(&objectClosure); ++ _timer_heap_iterate.stop(); ++ } ++ + Universe::root_oops_do(&oopClosureNoBarrier); ++ + } + log_trace(redefine, class, obsolete, metadata)("After updating instances"); + +@@ -571,11 +597,19 @@ void VM_EnhancedRedefineClasses::doit() { + + if (objectClosure.needs_instance_update()) { + // Do a full garbage collection to update the instance sizes accordingly ++ ++ if (log_is_enabled(Info, redefine, class, timer)) { ++ _timer_heap_full_gc.start(); ++ } ++ + Universe::set_redefining_gc_run(true); + notify_gc_begin(true); ++ // TODO: check _metadata_GC_clear_soft_refs with ScavengeRootsInCode + Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); + notify_gc_end(); + Universe::set_redefining_gc_run(false); ++ ++ _timer_heap_full_gc.stop(); + } + + // Unmark Klass*s as "redefining" +@@ -623,6 +657,7 @@ void VM_EnhancedRedefineClasses::doit() { + } + #endif + ++ _timer_vm_op_doit.stop(); + } + + // Cleanup - runs in JVM thread +@@ -646,16 +681,14 @@ void VM_EnhancedRedefineClasses::doit_epilogue() { + if (log_is_enabled(Info, redefine, class, timer)) { + // Used to have separate timers for "doit" and "all", but the timer + // overhead skewed the measurements. +- jlong doit_time = _timer_rsc_phase1.milliseconds() + +- _timer_rsc_phase2.milliseconds(); +- jlong all_time = _timer_vm_op_prologue.milliseconds() + doit_time; ++ jlong all_time = _timer_vm_op_prologue.milliseconds() + _timer_vm_op_doit.milliseconds(); + + log_info(redefine, class, timer) + ("vm_op: all=" JLONG_FORMAT " prologue=" JLONG_FORMAT " doit=" JLONG_FORMAT, +- all_time, _timer_vm_op_prologue.milliseconds(), doit_time); ++ all_time, _timer_vm_op_prologue.milliseconds(), _timer_vm_op_doit.milliseconds()); + log_info(redefine, class, timer) +- ("redefine_single_class: phase1=" JLONG_FORMAT " phase2=" JLONG_FORMAT, +- _timer_rsc_phase1.milliseconds(), _timer_rsc_phase2.milliseconds()); ++ ("doit: heap iterate=" JLONG_FORMAT " fullgc=" JLONG_FORMAT, ++ _timer_heap_iterate.milliseconds(), _timer_heap_full_gc.milliseconds()); + } + } + +@@ -1404,7 +1437,7 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { + // arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. + void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + if (!k->is_instance_klass()) { +- return; ++ return; + } + + HandleMark hm(_thread); +@@ -1590,7 +1623,7 @@ class TransferNativeFunctionRegistration { + + // Recursively search the binary tree of possibly prefixed method names. + // Iteration could be used if all agents were well behaved. Full tree walk is +- // more resilent to agents not cleaning up intermediate methods. ++ // more resilient to agents not cleaning up intermediate methods. + // Branch at each depth in the binary tree is: + // (1) without the prefix. + // (2) with the prefix. +@@ -1695,7 +1728,7 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst + transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); + } + +-// DCEVM - it always deoptimases everything! (because it is very difficult to find only correct dependencies) ++// DCEVM - it always deoptimizes everything! (because it is very difficult to find only correct dependencies) + // Deoptimize all compiled code that depends on this class. + // + // If the can_redefine_classes capability is obtained in the onload +@@ -1822,10 +1855,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + + HandleMark hm(THREAD); // make sure handles from this call are freed + +- if (log_is_enabled(Info, redefine, class, timer)) { +- _timer_rsc_phase1.start(); +- } +- + InstanceKlass* new_class = new_class_oop; + InstanceKlass* the_class = InstanceKlass::cast(new_class_oop->old_version()); + assert(the_class != NULL, "must have old version"); +@@ -1880,7 +1909,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + new_class->external_name(), + java_lang_Class::classRedefinedCount(new_class->java_mirror())); + } +- _timer_rsc_phase2.stop(); + } // end redefine_single_class() + + +@@ -2063,8 +2091,8 @@ static bool match_second(void* value, KlassPair elem) { + // For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. + // First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). + // Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) +-// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. +-// TODO - the class file is potentionally parsed multiple times - introduce a cache? ++// For each dependency create a KlassPair instance. Finally, affected classes (_affected_klasses) are sorted according to pairs. ++// TODO - the class file is potentially parsed multiple times - introduce a cache? + jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { + ResourceMark mark(THREAD); + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index d8a11b51fe9..9755944d70b 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -86,9 +86,10 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // Performance measurement support. These timers do not cover all + // the work done for JVM/TI RedefineClasses() but they do cover + // the heavy lifting. +- elapsedTimer _timer_rsc_phase1; +- elapsedTimer _timer_rsc_phase2; ++ elapsedTimer _timer_vm_op_doit; + elapsedTimer _timer_vm_op_prologue; ++ elapsedTimer _timer_heap_iterate; ++ elapsedTimer _timer_heap_full_gc; + + // These routines are roughly in call order unless otherwise noted. + +@@ -115,6 +116,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + + void rollback(); + static void mark_as_scavengable(nmethod* nm); ++ static void mark_as_scavengable_g1(nmethod* nm); + static void unpatch_bytecode(Method* method); + static void fix_invoke_method(Method* method); + +diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp +index 2803a3c46eb..d05a2893498 100644 +--- a/src/hotspot/share/runtime/arguments.cpp ++++ b/src/hotspot/share/runtime/arguments.cpp +@@ -2134,9 +2134,9 @@ bool Arguments::check_gc_consistency() { + if (AllowEnhancedClassRedefinition) { + // Must use serial GC. This limitation applies because the instance size changing GC modifications + // are only built into the mark and compact algorithm. +- if (!UseSerialGC && i >= 1) { ++ if ((!UseSerialGC && !UseG1GC) && i >= 1) { + jio_fprintf(defaultStream::error_stream(), +- "Must use the serial GC with enhanced class redefinition\n"); ++ "Must use the Serial or G1 GC with enhanced class redefinition.\n"); + return false; + } + } +diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp +index 972b702b4cb..548440e06b6 100644 +--- a/src/hotspot/share/utilities/growableArray.hpp ++++ b/src/hotspot/share/utilities/growableArray.hpp +@@ -560,6 +560,10 @@ template class GrowableArrayIterator : public StackObj { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position != rhs._position; + } ++ ++ bool at_end() { return _position >= _array->length(); } ++ ++ bool has_next() { return _position < _array->length() - 1; } + }; + + // Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch b/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch new file mode 100644 index 000000000000..1e8c4416e343 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch @@ -0,0 +1,50 @@ +From ca47ab5a0a6ce8e2644736f323a335a957311af9 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sat, 13 Jun 2020 18:50:59 +0200 +Subject: [PATCH 09/34] Change log level in advanced redefinition + +- Change log level for "Comparing different class ver.." to debug +- Fix adjust_method_entries_dcevm logging levels and severity +--- + src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +- + src/hotspot/share/prims/resolvedMethodTable.cpp | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 6c9eb40ecf5..b09ba554e07 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -916,7 +916,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + // Calculated the difference between new and old class (field change, method change, supertype change, ...). + int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { + int result = Klass::NoRedefinition; +- log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); ++ log_debug(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); + + assert(new_class->old_version() != NULL, "must have old version"); + InstanceKlass* the_class = InstanceKlass::cast(new_class->old_version()); +diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp +index caf03ffe56d..eb9fcda44f3 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.cpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.cpp +@@ -413,7 +413,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) + } else { + newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); + +- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); ++ log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); + + assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); + assert(newer_method != NULL, "method_with_idnum() should not be NULL"); +@@ -433,7 +433,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) + + ResourceMark rm; + if (!(*trace_name_printed)) { +- log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); ++ log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); + *trace_name_printed = true; + } + log_debug(redefine, class, update, constantpool) +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch b/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch new file mode 100644 index 000000000000..a846a414e517 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch @@ -0,0 +1,26 @@ +From 7e236beee0375656d1955fc1168143c1639fb7f1 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Tue, 6 Oct 2020 22:15:31 +0200 +Subject: [PATCH 10/34] AllowEnhancedClassRedefinition is false (disabled) by + default + +--- + src/hotspot/share/runtime/globals.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp +index 5b367704800..2710c6ea0e5 100644 +--- a/src/hotspot/share/runtime/globals.hpp ++++ b/src/hotspot/share/runtime/globals.hpp +@@ -2466,7 +2466,7 @@ const size_t minimumSymbolTableSize = 1024; + diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \ + "Make nmethod barriers deoptimise a lot.") \ + \ +- product(bool, AllowEnhancedClassRedefinition, true, \ ++ product(bool, AllowEnhancedClassRedefinition, false, \ + "Allow enhanced class redefinition beyond swapping method " \ + "bodies") \ + \ +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch b/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch new file mode 100644 index 000000000000..d0853abe9db5 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch @@ -0,0 +1,2977 @@ +From ab2cfbfa4f5758d26b9e32f5e779a7e56eba1a90 Mon Sep 17 00:00:00 2001 +From: Artem Khvastunov +Date: Tue, 14 Apr 2020 19:11:35 +0200 +Subject: [PATCH 11/34] add jvmtiEnhancedRedefineClasses.* to CMakeLists.txt + +--- + jb/project/hotspot-cmake/CMakeLists.txt | 2958 +++++++++++++++++++++++ + 1 file changed, 2958 insertions(+) + create mode 100644 jb/project/hotspot-cmake/CMakeLists.txt + +diff --git a/jb/project/hotspot-cmake/CMakeLists.txt b/jb/project/hotspot-cmake/CMakeLists.txt +new file mode 100644 +index 00000000000..6516e39058f +--- /dev/null ++++ b/jb/project/hotspot-cmake/CMakeLists.txt +@@ -0,0 +1,2958 @@ ++cmake_minimum_required(VERSION 3.9) ++project(hotspot) ++ ++include(../java-common.cmake) ++ ++include_directories( ++../../../src/hotspot/cpu/aarch64 ++../../../src/hotspot/cpu/aarch64/gc/g1 ++../../../src/hotspot/cpu/aarch64/gc/shared ++../../../src/hotspot/cpu/arm ++../../../src/hotspot/cpu/arm/gc/g1 ++../../../src/hotspot/cpu/arm/gc/shared ++../../../src/hotspot/cpu/ppc ++../../../src/hotspot/cpu/ppc/gc/g1 ++../../../src/hotspot/cpu/ppc/gc/shared ++../../../src/hotspot/cpu/s390 ++../../../src/hotspot/cpu/s390/gc/g1 ++../../../src/hotspot/cpu/s390/gc/shared ++../../../src/hotspot/cpu/sparc ++../../../src/hotspot/cpu/sparc/gc/g1 ++../../../src/hotspot/cpu/sparc/gc/shared ++../../../src/hotspot/cpu/x86 ++../../../src/hotspot/cpu/x86/gc/g1 ++../../../src/hotspot/cpu/x86/gc/shared ++../../../src/hotspot/cpu/x86/gc/z ++../../../src/hotspot/cpu/zero ++../../../src/hotspot/cpu/zero/gc/g1 ++../../../src/hotspot/cpu/zero/gc/shared ++../../../src/hotspot/os/aix ++../../../src/hotspot/os/bsd ++../../../src/hotspot/os/linux ++../../../src/hotspot/os/posix ++../../../src/hotspot/os/solaris ++../../../src/hotspot/os/windows ++../../../src/hotspot/os_cpu/aix_ppc ++../../../src/hotspot/os_cpu/bsd_x86 ++../../../src/hotspot/os_cpu/bsd_zero ++../../../src/hotspot/os_cpu/linux_aarch64 ++../../../src/hotspot/os_cpu/linux_arm ++../../../src/hotspot/os_cpu/linux_ppc ++../../../src/hotspot/os_cpu/linux_s390 ++../../../src/hotspot/os_cpu/linux_sparc ++../../../src/hotspot/os_cpu/linux_x86 ++../../../src/hotspot/os_cpu/linux_x86/gc/z ++../../../src/hotspot/os_cpu/linux_zero ++../../../src/hotspot/os_cpu/solaris_sparc ++../../../src/hotspot/os_cpu/solaris_x86 ++../../../src/hotspot/os_cpu/windows_x86 ++../../../src/hotspot/share ++) ++ ++set(SOURCE_FILES ++../../../src/hotspot/cpu/ppc/depChecker_ppc.hpp ++../../../src/hotspot/cpu/ppc/assembler_ppc.inline.hpp ++../../../src/hotspot/cpu/ppc/icache_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/vmreg_ppc.cpp ++../../../src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp ++../../../src/hotspot/cpu/ppc/compiledIC_ppc.cpp ++../../../src/hotspot/cpu/ppc/frame_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_globals_ppc.hpp ++../../../src/hotspot/cpu/ppc/relocInfo_ppc.hpp ++../../../src/hotspot/cpu/ppc/icBuffer_ppc.cpp ++../../../src/hotspot/cpu/ppc/register_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_LinearScan_ppc.cpp ++../../../src/hotspot/cpu/ppc/jvmciCodeInstaller_ppc.cpp ++../../../src/hotspot/cpu/ppc/assembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/methodHandles_ppc.hpp ++../../../src/hotspot/cpu/ppc/codeBuffer_ppc.hpp ++../../../src/hotspot/cpu/ppc/templateTable_ppc_64.cpp ++../../../src/hotspot/cpu/ppc/interpreterRT_ppc.cpp ++../../../src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp ++../../../src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp ++../../../src/hotspot/cpu/ppc/stubRoutines_ppc.hpp ++../../../src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp ++../../../src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/macroAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/globals_ppc.hpp ++../../../src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp ++../../../src/hotspot/cpu/ppc/frame_ppc.inline.hpp ++../../../src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp ++../../../src/hotspot/cpu/ppc/macroAssembler_ppc_sha.cpp ++../../../src/hotspot/cpu/ppc/jniTypes_ppc.hpp ++../../../src/hotspot/cpu/ppc/nativeInst_ppc.hpp ++../../../src/hotspot/cpu/ppc/bytes_ppc.hpp ++../../../src/hotspot/cpu/ppc/vm_version_ext_ppc.cpp ++../../../src/hotspot/cpu/ppc/copy_ppc.hpp ++../../../src/hotspot/cpu/ppc/vm_version_ppc.hpp ++../../../src/hotspot/cpu/ppc/runtime_ppc.cpp ++../../../src/hotspot/cpu/ppc/macroAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/register_definitions_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp ++../../../src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp ++../../../src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp ++../../../src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp ++../../../src/hotspot/cpu/ppc/nativeInst_ppc.cpp ++../../../src/hotspot/cpu/ppc/templateTable_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_LIR_ppc.cpp ++../../../src/hotspot/cpu/ppc/vm_version_ext_ppc.hpp ++../../../src/hotspot/cpu/ppc/c2_globals_ppc.hpp ++../../../src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/c2_init_ppc.cpp ++../../../src/hotspot/cpu/ppc/vm_version_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp ++../../../src/hotspot/cpu/ppc/icache_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_Defs_ppc.hpp ++../../../src/hotspot/cpu/ppc/vmreg_ppc.hpp ++../../../src/hotspot/cpu/ppc/vmStructs_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_FpuStackSim_ppc.hpp ++../../../src/hotspot/cpu/ppc/frame_ppc.hpp ++../../../src/hotspot/cpu/ppc/registerMap_ppc.hpp ++../../../src/hotspot/cpu/ppc/relocInfo_ppc.cpp ++../../../src/hotspot/cpu/ppc/register_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_FrameMap_ppc.hpp ++../../../src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp ++../../../src/hotspot/cpu/ppc/c1_LinearScan_ppc.hpp ++../../../src/hotspot/cpu/ppc/assembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/methodHandles_ppc.cpp ++../../../src/hotspot/cpu/ppc/disassembler_ppc.hpp ++../../../src/hotspot/cpu/ppc/interp_masm_ppc.hpp ++../../../src/hotspot/cpu/ppc/interpreterRT_ppc.hpp ++../../../src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp ++../../../src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp ++../../../src/hotspot/cpu/ppc/stubGenerator_ppc.cpp ++../../../src/hotspot/cpu/s390/stubRoutines_s390.hpp ++../../../src/hotspot/cpu/s390/frame_s390.hpp ++../../../src/hotspot/cpu/s390/compiledIC_s390.cpp ++../../../src/hotspot/cpu/s390/interp_masm_s390.cpp ++../../../src/hotspot/cpu/s390/nativeInst_s390.cpp ++../../../src/hotspot/cpu/s390/interpreterRT_s390.hpp ++../../../src/hotspot/cpu/s390/c1_LinearScan_s390.hpp ++../../../src/hotspot/cpu/s390/c1_LIR_s390.cpp ++../../../src/hotspot/cpu/s390/relocInfo_s390.cpp ++../../../src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp ++../../../src/hotspot/cpu/s390/stubGenerator_s390.cpp ++../../../src/hotspot/cpu/s390/vmreg_s390.cpp ++../../../src/hotspot/cpu/s390/macroAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/c2_init_s390.cpp ++../../../src/hotspot/cpu/s390/runtime_s390.cpp ++../../../src/hotspot/cpu/s390/c1_FpuStackSim_s390.hpp ++../../../src/hotspot/cpu/s390/icBuffer_s390.cpp ++../../../src/hotspot/cpu/s390/vmreg_s390.inline.hpp ++../../../src/hotspot/cpu/s390/vm_version_ext_s390.hpp ++../../../src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp ++../../../src/hotspot/cpu/s390/c1_globals_s390.hpp ++../../../src/hotspot/cpu/s390/assembler_s390.hpp ++../../../src/hotspot/cpu/s390/vmStructs_s390.hpp ++../../../src/hotspot/cpu/s390/sharedRuntime_s390.cpp ++../../../src/hotspot/cpu/s390/templateTable_s390.hpp ++../../../src/hotspot/cpu/s390/methodHandles_s390.hpp ++../../../src/hotspot/cpu/s390/globals_s390.hpp ++../../../src/hotspot/cpu/s390/c1_FrameMap_s390.hpp ++../../../src/hotspot/cpu/s390/register_s390.hpp ++../../../src/hotspot/cpu/s390/register_definitions_s390.cpp ++../../../src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp ++../../../src/hotspot/cpu/s390/icache_s390.cpp ++../../../src/hotspot/cpu/s390/registerSaver_s390.hpp ++../../../src/hotspot/cpu/s390/codeBuffer_s390.hpp ++../../../src/hotspot/cpu/s390/vm_version_s390.hpp ++../../../src/hotspot/cpu/s390/c1_Defs_s390.hpp ++../../../src/hotspot/cpu/s390/templateTable_s390.cpp ++../../../src/hotspot/cpu/s390/globalDefinitions_s390.hpp ++../../../src/hotspot/cpu/s390/methodHandles_s390.cpp ++../../../src/hotspot/cpu/s390/register_s390.cpp ++../../../src/hotspot/cpu/s390/c1_FrameMap_s390.cpp ++../../../src/hotspot/cpu/s390/copy_s390.hpp ++../../../src/hotspot/cpu/s390/frame_s390.inline.hpp ++../../../src/hotspot/cpu/s390/abstractInterpreter_s390.cpp ++../../../src/hotspot/cpu/s390/icache_s390.hpp ++../../../src/hotspot/cpu/s390/jvmciCodeInstaller_s390.cpp ++../../../src/hotspot/cpu/s390/bytes_s390.hpp ++../../../src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp ++../../../src/hotspot/cpu/s390/jniTypes_s390.hpp ++../../../src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp ++../../../src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/vm_version_s390.cpp ++../../../src/hotspot/cpu/s390/frame_s390.cpp ++../../../src/hotspot/cpu/s390/stubRoutines_s390.cpp ++../../../src/hotspot/cpu/s390/interp_masm_s390.hpp ++../../../src/hotspot/cpu/s390/disassembler_s390.hpp ++../../../src/hotspot/cpu/s390/c1_LinearScan_s390.cpp ++../../../src/hotspot/cpu/s390/interpreterRT_s390.cpp ++../../../src/hotspot/cpu/s390/macroAssembler_s390.inline.hpp ++../../../src/hotspot/cpu/s390/nativeInst_s390.hpp ++../../../src/hotspot/cpu/s390/vtableStubs_s390.cpp ++../../../src/hotspot/cpu/s390/relocInfo_s390.hpp ++../../../src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/vmreg_s390.hpp ++../../../src/hotspot/cpu/s390/depChecker_s390.hpp ++../../../src/hotspot/cpu/s390/macroAssembler_s390.hpp ++../../../src/hotspot/cpu/s390/jniFastGetField_s390.cpp ++../../../src/hotspot/cpu/s390/c2_globals_s390.hpp ++../../../src/hotspot/cpu/s390/c1_Runtime1_s390.cpp ++../../../src/hotspot/cpu/s390/registerMap_s390.hpp ++../../../src/hotspot/cpu/s390/vm_version_ext_s390.cpp ++../../../src/hotspot/cpu/s390/assembler_s390.inline.hpp ++../../../src/hotspot/cpu/s390/assembler_s390.cpp ++../../../src/hotspot/cpu/zero/disassembler_zero.cpp ++../../../src/hotspot/cpu/zero/frame_zero.hpp ++../../../src/hotspot/cpu/zero/compiledIC_zero.cpp ++../../../src/hotspot/cpu/zero/stubRoutines_zero.hpp ++../../../src/hotspot/cpu/zero/vmreg_zero.cpp ++../../../src/hotspot/cpu/zero/stubGenerator_zero.cpp ++../../../src/hotspot/cpu/zero/interpreterRT_zero.hpp ++../../../src/hotspot/cpu/zero/nativeInst_zero.cpp ++../../../src/hotspot/cpu/zero/relocInfo_zero.cpp ++../../../src/hotspot/cpu/zero/icBuffer_zero.cpp ++../../../src/hotspot/cpu/zero/depChecker_zero.cpp ++../../../src/hotspot/cpu/zero/vmStructs_zero.hpp ++../../../src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp ++../../../src/hotspot/cpu/zero/stack_zero.hpp ++../../../src/hotspot/cpu/zero/assembler_zero.hpp ++../../../src/hotspot/cpu/zero/vm_version_ext_zero.hpp ++../../../src/hotspot/cpu/zero/frame_zero.inline.hpp ++../../../src/hotspot/cpu/zero/sharedRuntime_zero.cpp ++../../../src/hotspot/cpu/zero/cppInterpreter_zero.cpp ++../../../src/hotspot/cpu/zero/macroAssembler_zero.inline.hpp ++../../../src/hotspot/cpu/zero/globals_zero.hpp ++../../../src/hotspot/cpu/zero/methodHandles_zero.hpp ++../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.hpp ++../../../src/hotspot/cpu/zero/register_zero.hpp ++../../../src/hotspot/cpu/zero/assembler_zero.inline.hpp ++../../../src/hotspot/cpu/zero/icache_zero.cpp ++../../../src/hotspot/cpu/zero/vm_version_zero.hpp ++../../../src/hotspot/cpu/zero/codeBuffer_zero.hpp ++../../../src/hotspot/cpu/zero/stack_zero.inline.hpp ++../../../src/hotspot/cpu/zero/globalDefinitions_zero.hpp ++../../../src/hotspot/cpu/zero/cppInterpreter_zero.hpp ++../../../src/hotspot/cpu/zero/fakeStubFrame_zero.hpp ++../../../src/hotspot/cpu/zero/entry_zero.hpp ++../../../src/hotspot/cpu/zero/copy_zero.hpp ++../../../src/hotspot/cpu/zero/methodHandles_zero.cpp ++../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.cpp ++../../../src/hotspot/cpu/zero/register_zero.cpp ++../../../src/hotspot/cpu/zero/interpreterFrame_zero.hpp ++../../../src/hotspot/cpu/zero/icache_zero.hpp ++../../../src/hotspot/cpu/zero/abstractInterpreter_zero.cpp ++../../../src/hotspot/cpu/zero/vmreg_zero.inline.hpp ++../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.inline.hpp ++../../../src/hotspot/cpu/zero/vm_version_zero.cpp ++../../../src/hotspot/cpu/zero/bytes_zero.hpp ++../../../src/hotspot/cpu/zero/gc/g1/g1BarrierSetAssembler_zero.hpp ++../../../src/hotspot/cpu/zero/gc/shared/barrierSetAssembler_zero.hpp ++../../../src/hotspot/cpu/zero/gc/shared/cardTableBarrierSetAssembler_zero.hpp ++../../../src/hotspot/cpu/zero/gc/shared/modRefBarrierSetAssembler_zero.hpp ++../../../src/hotspot/cpu/zero/jniTypes_zero.hpp ++../../../src/hotspot/cpu/zero/disassembler_zero.hpp ++../../../src/hotspot/cpu/zero/stubRoutines_zero.cpp ++../../../src/hotspot/cpu/zero/frame_zero.cpp ++../../../src/hotspot/cpu/zero/interp_masm_zero.hpp ++../../../src/hotspot/cpu/zero/vmreg_zero.hpp ++../../../src/hotspot/cpu/zero/nativeInst_zero.hpp ++../../../src/hotspot/cpu/zero/vtableStubs_zero.cpp ++../../../src/hotspot/cpu/zero/interpreterRT_zero.cpp ++../../../src/hotspot/cpu/zero/relocInfo_zero.hpp ++../../../src/hotspot/cpu/zero/cppInterpreterGenerator_zero.cpp ++../../../src/hotspot/cpu/zero/jniFastGetField_zero.cpp ++../../../src/hotspot/cpu/zero/entryFrame_zero.hpp ++../../../src/hotspot/cpu/zero/macroAssembler_zero.hpp ++../../../src/hotspot/cpu/zero/depChecker_zero.hpp ++../../../src/hotspot/cpu/zero/stack_zero.cpp ++../../../src/hotspot/cpu/zero/assembler_zero.cpp ++../../../src/hotspot/cpu/zero/vm_version_ext_zero.cpp ++../../../src/hotspot/cpu/zero/registerMap_zero.hpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86.inline.hpp ++../../../src/hotspot/cpu/x86/stubRoutines_x86_64.cpp ++../../../src/hotspot/cpu/x86/assembler_x86.inline.hpp ++../../../src/hotspot/cpu/x86/stubGenerator_x86_64.cpp ++../../../src/hotspot/cpu/x86/stubRoutines_x86.cpp ++../../../src/hotspot/cpu/x86/sharedRuntime_x86.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_log10.cpp ++../../../src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/register_definitions_x86.cpp ++../../../src/hotspot/cpu/x86/c1_Runtime1_x86.cpp ++../../../src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp ++../../../src/hotspot/cpu/x86/templateTable_x86.hpp ++../../../src/hotspot/cpu/x86/nativeInst_x86.cpp ++../../../src/hotspot/cpu/x86/c2_globals_x86.hpp ++../../../src/hotspot/cpu/x86/vm_version_x86.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_cos.cpp ++../../../src/hotspot/cpu/x86/rdtsc_x86.hpp ++../../../src/hotspot/cpu/x86/c2_init_x86.cpp ++../../../src/hotspot/cpu/x86/c1_LIR_x86.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_sin.cpp ++../../../src/hotspot/cpu/x86/vm_version_ext_x86.hpp ++../../../src/hotspot/cpu/x86/vmreg_x86.hpp ++../../../src/hotspot/cpu/x86/depChecker_x86.cpp ++../../../src/hotspot/cpu/x86/c1_Defs_x86.hpp ++../../../src/hotspot/cpu/x86/icache_x86.hpp ++../../../src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/frame_x86.inline.hpp ++../../../src/hotspot/cpu/x86/register_x86.hpp ++../../../src/hotspot/cpu/x86/vmreg_x86.inline.hpp ++../../../src/hotspot/cpu/x86/c1_FpuStackSim_x86.hpp ++../../../src/hotspot/cpu/x86/frame_x86.hpp ++../../../src/hotspot/cpu/x86/vmStructs_x86.hpp ++../../../src/hotspot/cpu/x86/registerMap_x86.hpp ++../../../src/hotspot/cpu/x86/relocInfo_x86.cpp ++../../../src/hotspot/cpu/x86/assembler_x86.hpp ++../../../src/hotspot/cpu/x86/vtableStubs_x86_32.cpp ++../../../src/hotspot/cpu/x86/methodHandles_x86.cpp ++../../../src/hotspot/cpu/x86/interpreterRT_x86_32.cpp ++../../../src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp ++../../../src/hotspot/cpu/x86/c1_FrameMap_x86.hpp ++../../../src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp ++../../../src/hotspot/cpu/x86/c1_LinearScan_x86.hpp ++../../../src/hotspot/cpu/x86/interpreterRT_x86.hpp ++../../../src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp ++../../../src/hotspot/cpu/x86/runtime_x86_32.cpp ++../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp ++../../../src/hotspot/cpu/x86/disassembler_x86.hpp ++../../../src/hotspot/cpu/x86/interp_masm_x86.hpp ++../../../src/hotspot/cpu/x86/vmreg_x86.cpp ++../../../src/hotspot/cpu/x86/stubRoutines_x86_32.cpp ++../../../src/hotspot/cpu/x86/compiledIC_x86.cpp ++../../../src/hotspot/cpu/x86/depChecker_x86.hpp ++../../../src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/icache_x86.cpp ++../../../src/hotspot/cpu/x86/stubGenerator_x86_32.cpp ++../../../src/hotspot/cpu/x86/register_x86.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_log.cpp ++../../../src/hotspot/cpu/x86/c1_FpuStackSim_x86.cpp ++../../../src/hotspot/cpu/x86/frame_x86.cpp ++../../../src/hotspot/cpu/x86/icBuffer_x86.cpp ++../../../src/hotspot/cpu/x86/c1_globals_x86.hpp ++../../../src/hotspot/cpu/x86/relocInfo_x86.hpp ++../../../src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp ++../../../src/hotspot/cpu/x86/registerMap_x86.cpp ++../../../src/hotspot/cpu/x86/assembler_x86.cpp ++../../../src/hotspot/cpu/x86/methodHandles_x86.hpp ++../../../src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp ++../../../src/hotspot/cpu/x86/codeBuffer_x86.hpp ++../../../src/hotspot/cpu/x86/c1_FrameMap_x86.cpp ++../../../src/hotspot/cpu/x86/c1_LinearScan_x86.cpp ++../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp ++../../../src/hotspot/cpu/x86/interp_masm_x86.cpp ++../../../src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp ++../../../src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/crc32c.h ++../../../src/hotspot/cpu/x86/macroAssembler_x86_exp.cpp ++../../../src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_tan.cpp ++../../../src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp ++../../../src/hotspot/cpu/x86/abstractInterpreter_x86.cpp ++../../../src/hotspot/cpu/x86/stubRoutines_x86.hpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_pow.cpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/globals_x86.hpp ++../../../src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp ++../../../src/hotspot/cpu/x86/vtableStubs_x86_64.cpp ++../../../src/hotspot/cpu/x86/interpreterRT_x86_64.cpp ++../../../src/hotspot/cpu/x86/nativeInst_x86.hpp ++../../../src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp ++../../../src/hotspot/cpu/x86/bytes_x86.hpp ++../../../src/hotspot/cpu/x86/templateTable_x86.cpp ++../../../src/hotspot/cpu/x86/jniTypes_x86.hpp ++../../../src/hotspot/cpu/x86/globalDefinitions_x86.hpp ++../../../src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp ++../../../src/hotspot/cpu/x86/rdtsc_x86.cpp ++../../../src/hotspot/cpu/x86/vm_version_x86.hpp ++../../../src/hotspot/cpu/x86/runtime_x86_64.cpp ++../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp ++../../../src/hotspot/cpu/x86/vm_version_ext_x86.cpp ++../../../src/hotspot/cpu/x86/copy_x86.hpp ++../../../src/hotspot/cpu/arm/interpreterRT_arm.hpp ++../../../src/hotspot/cpu/arm/assembler_arm_32.cpp ++../../../src/hotspot/cpu/arm/jniFastGetField_arm.cpp ++../../../src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp ++../../../src/hotspot/cpu/arm/stubGenerator_arm.cpp ++../../../src/hotspot/cpu/arm/nativeInst_arm_64.hpp ++../../../src/hotspot/cpu/arm/disassembler_arm.hpp ++../../../src/hotspot/cpu/arm/interp_masm_arm.hpp ++../../../src/hotspot/cpu/arm/methodHandles_arm.cpp ++../../../src/hotspot/cpu/arm/assembler_arm.hpp ++../../../src/hotspot/cpu/arm/c1_FrameMap_arm.hpp ++../../../src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp ++../../../src/hotspot/cpu/arm/c1_LinearScan_arm.hpp ++../../../src/hotspot/cpu/arm/register_arm.hpp ++../../../src/hotspot/cpu/arm/vmStructs_arm.hpp ++../../../src/hotspot/cpu/arm/c1_FpuStackSim_arm.hpp ++../../../src/hotspot/cpu/arm/frame_arm.hpp ++../../../src/hotspot/cpu/arm/relocInfo_arm.cpp ++../../../src/hotspot/cpu/arm/registerMap_arm.hpp ++../../../src/hotspot/cpu/arm/vmreg_arm.hpp ++../../../src/hotspot/cpu/arm/vm_version_arm_32.cpp ++../../../src/hotspot/cpu/arm/depChecker_arm.cpp ++../../../src/hotspot/cpu/arm/icache_arm.hpp ++../../../src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/c1_Defs_arm.hpp ++../../../src/hotspot/cpu/arm/c2_globals_arm.hpp ++../../../src/hotspot/cpu/arm/assembler_arm_64.hpp ++../../../src/hotspot/cpu/arm/nativeInst_arm_32.cpp ++../../../src/hotspot/cpu/arm/vtableStubs_arm.cpp ++../../../src/hotspot/cpu/arm/c1_LIR_arm.cpp ++../../../src/hotspot/cpu/arm/vm_version_ext_arm.hpp ++../../../src/hotspot/cpu/arm/templateTable_arm.hpp ++../../../src/hotspot/cpu/arm/sharedRuntime_arm.cpp ++../../../src/hotspot/cpu/arm/register_definitions_arm.cpp ++../../../src/hotspot/cpu/arm/macroAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/c1_MacroAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp ++../../../src/hotspot/cpu/arm/c1_Runtime1_arm.cpp ++../../../src/hotspot/cpu/arm/c1_LIRGenerator_arm.hpp ++../../../src/hotspot/cpu/arm/stubRoutines_arm.cpp ++../../../src/hotspot/cpu/arm/runtime_arm.cpp ++../../../src/hotspot/cpu/arm/assembler_arm_64.cpp ++../../../src/hotspot/cpu/arm/vm_version_arm.hpp ++../../../src/hotspot/cpu/arm/nativeInst_arm_32.hpp ++../../../src/hotspot/cpu/arm/copy_arm.hpp ++../../../src/hotspot/cpu/arm/vm_version_ext_arm.cpp ++../../../src/hotspot/cpu/arm/macroAssembler_arm.inline.hpp ++../../../src/hotspot/cpu/arm/jniTypes_arm.hpp ++../../../src/hotspot/cpu/arm/templateTable_arm.cpp ++../../../src/hotspot/cpu/arm/bytes_arm.hpp ++../../../src/hotspot/cpu/arm/nativeInst_arm.hpp ++../../../src/hotspot/cpu/arm/globalDefinitions_arm.hpp ++../../../src/hotspot/cpu/arm/assembler_arm.inline.hpp ++../../../src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/globals_arm.hpp ++../../../src/hotspot/cpu/arm/macroAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/vm_version_arm_64.cpp ++../../../src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp ++../../../src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.cpp ++../../../src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/abstractInterpreter_arm.cpp ++../../../src/hotspot/cpu/arm/stubRoutines_arm.hpp ++../../../src/hotspot/cpu/arm/frame_arm.inline.hpp ++../../../src/hotspot/cpu/arm/interpreterRT_arm.cpp ++../../../src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp ++../../../src/hotspot/cpu/arm/assembler_arm_32.hpp ++../../../src/hotspot/cpu/arm/nativeInst_arm_64.cpp ++../../../src/hotspot/cpu/arm/vmreg_arm.inline.hpp ++../../../src/hotspot/cpu/arm/interp_masm_arm.cpp ++../../../src/hotspot/cpu/arm/jvmciCodeInstaller_arm.cpp ++../../../src/hotspot/cpu/arm/methodHandles_arm.hpp ++../../../src/hotspot/cpu/arm/assembler_arm.cpp ++../../../src/hotspot/cpu/arm/codeBuffer_arm.hpp ++../../../src/hotspot/cpu/arm/c1_FrameMap_arm.cpp ++../../../src/hotspot/cpu/arm/c1_LinearScan_arm.cpp ++../../../src/hotspot/cpu/arm/register_arm.cpp ++../../../src/hotspot/cpu/arm/c1_FpuStackSim_arm.cpp ++../../../src/hotspot/cpu/arm/frame_arm.cpp ++../../../src/hotspot/cpu/arm/c1_globals_arm.hpp ++../../../src/hotspot/cpu/arm/relocInfo_arm.hpp ++../../../src/hotspot/cpu/arm/icBuffer_arm.cpp ++../../../src/hotspot/cpu/arm/vmreg_arm.cpp ++../../../src/hotspot/cpu/arm/compiledIC_arm.cpp ++../../../src/hotspot/cpu/arm/depChecker_arm.hpp ++../../../src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp ++../../../src/hotspot/cpu/arm/icache_arm.cpp ++../../../src/hotspot/cpu/aarch64/copy_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp ++../../../src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/globals_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/bytes_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/icache_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/vm_version_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/immediate_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vmreg_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c2_init_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/register_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/assembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/depChecker_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/frame_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp ++../../../src/hotspot/cpu/aarch64/methodHandles_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_FpuStackSim_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/templateTable_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/codeBuffer_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_LinearScan_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vmreg_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/assembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/register_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/depChecker_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/frame_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp ++../../../src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/methodHandles_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp ++../../../src/hotspot/cpu/aarch64/c1_FpuStackSim_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/templateTable_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/runtime_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_LinearScan_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/disassembler_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/icache_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.inline.hpp ++../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp ++../../../src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/registerMap_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/aarch64Test.cpp ++../../../src/hotspot/cpu/aarch64/immediate_aarch64.hpp ++../../../src/hotspot/cpu/aarch64/vm_version_aarch64.cpp ++../../../src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp ++../../../src/hotspot/cpu/sparc/vmStructs_sparc.hpp ++../../../src/hotspot/cpu/sparc/nativeInst_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_LinearScan_sparc.hpp ++../../../src/hotspot/cpu/sparc/copy_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_globals_sparc.hpp ++../../../src/hotspot/cpu/sparc/codeBuffer_sparc.hpp ++../../../src/hotspot/cpu/sparc/stubGenerator_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_FpuStackSim_sparc.cpp ++../../../src/hotspot/cpu/sparc/disassembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp ++../../../src/hotspot/cpu/sparc/c2_init_sparc.cpp ++../../../src/hotspot/cpu/sparc/assembler_sparc.inline.hpp ++../../../src/hotspot/cpu/sparc/vmreg_sparc.hpp ++../../../src/hotspot/cpu/sparc/vm_version_sparc.cpp ++../../../src/hotspot/cpu/sparc/templateTable_sparc.hpp ++../../../src/hotspot/cpu/sparc/macroAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_Defs_sparc.hpp ++../../../src/hotspot/cpu/sparc/interp_masm_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp ++../../../src/hotspot/cpu/sparc/vm_version_ext_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/macroAssembler_sparc.inline.hpp ++../../../src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp ++../../../src/hotspot/cpu/sparc/assembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/frame_sparc.inline.hpp ++../../../src/hotspot/cpu/sparc/frame_sparc.hpp ++../../../src/hotspot/cpu/sparc/stubRoutines_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_LIR_sparc.cpp ++../../../src/hotspot/cpu/sparc/abstractInterpreter_sparc.cpp ++../../../src/hotspot/cpu/sparc/methodHandles_sparc.hpp ++../../../src/hotspot/cpu/sparc/register_definitions_sparc.cpp ++../../../src/hotspot/cpu/sparc/relocInfo_sparc.cpp ++../../../src/hotspot/cpu/sparc/icache_sparc.hpp ++../../../src/hotspot/cpu/sparc/interpreterRT_sparc.cpp ++../../../src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp ++../../../src/hotspot/cpu/sparc/depChecker_sparc.cpp ++../../../src/hotspot/cpu/sparc/runtime_sparc.cpp ++../../../src/hotspot/cpu/sparc/register_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/c2_globals_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_FrameMap_sparc.cpp ++../../../src/hotspot/cpu/sparc/bytes_sparc.hpp ++../../../src/hotspot/cpu/sparc/interp_masm_sparc.hpp ++../../../src/hotspot/cpu/sparc/vm_version_ext_sparc.hpp ++../../../src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/globalDefinitions_sparc.hpp ++../../../src/hotspot/cpu/sparc/stubRoutines_sparc.cpp ++../../../src/hotspot/cpu/sparc/frame_sparc.cpp ++../../../src/hotspot/cpu/sparc/assembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_CodeStubs_sparc.cpp ++../../../src/hotspot/cpu/sparc/methodHandles_sparc.cpp ++../../../src/hotspot/cpu/sparc/relocInfo_sparc.hpp ++../../../src/hotspot/cpu/sparc/icache_sparc.cpp ++../../../src/hotspot/cpu/sparc/interpreterRT_sparc.hpp ++../../../src/hotspot/cpu/sparc/globals_sparc.hpp ++../../../src/hotspot/cpu/sparc/vmreg_sparc.inline.hpp ++../../../src/hotspot/cpu/sparc/depChecker_sparc.hpp ++../../../src/hotspot/cpu/sparc/registerMap_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/register_sparc.hpp ++../../../src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.cpp ++../../../src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp ++../../../src/hotspot/cpu/sparc/c1_FrameMap_sparc.hpp ++../../../src/hotspot/cpu/sparc/compiledIC_sparc.cpp ++../../../src/hotspot/cpu/sparc/icBuffer_sparc.cpp ++../../../src/hotspot/cpu/sparc/nativeInst_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_LinearScan_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp ++../../../src/hotspot/cpu/sparc/c1_FpuStackSim_sparc.hpp ++../../../src/hotspot/cpu/sparc/jniTypes_sparc.hpp ++../../../src/hotspot/cpu/sparc/vtableStubs_sparc.cpp ++../../../src/hotspot/cpu/sparc/javaFrameAnchor_sparc.hpp ++../../../src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp ++../../../src/hotspot/cpu/sparc/vmreg_sparc.cpp ++../../../src/hotspot/cpu/sparc/vm_version_sparc.hpp ++../../../src/hotspot/cpu/sparc/templateTable_sparc.cpp ++../../../src/hotspot/cpu/sparc/macroAssembler_sparc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/os_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/vmStructs_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp ++../../../src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp ++../../../src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp ++../../../src/hotspot/os_cpu/aix_ppc/bytes_aix_ppc.inline.hpp ++../../../src/hotspot/os_cpu/aix_ppc/prefetch_aix_ppc.inline.hpp ++../../../src/hotspot/os_cpu/linux_arm/copy_linux_arm.inline.hpp ++../../../src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp ++../../../src/hotspot/os_cpu/linux_arm/thread_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_arm/vmStructs_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_arm/orderAccess_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_arm/prefetch_linux_arm.inline.hpp ++../../../src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp ++../../../src/hotspot/os_cpu/linux_arm/vm_version_linux_arm_32.cpp ++../../../src/hotspot/os_cpu/linux_arm/bytes_linux_arm.inline.hpp ++../../../src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp ++../../../src/hotspot/os_cpu/linux_arm/os_linux_arm.hpp ++../../../src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp ++../../../src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp ++../../../src/hotspot/os_cpu/linux_zero/assembler_linux_zero.cpp ++../../../src/hotspot/os_cpu/linux_zero/vm_version_linux_zero.cpp ++../../../src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_zero/orderAccess_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_zero/prefetch_linux_zero.inline.hpp ++../../../src/hotspot/os_cpu/linux_zero/vmStructs_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_zero/bytes_linux_zero.inline.hpp ++../../../src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp ++../../../src/hotspot/os_cpu/linux_x86/orderAccess_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/thread_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/prefetch_linux_x86.inline.hpp ++../../../src/hotspot/os_cpu/linux_x86/vmStructs_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/bytes_linux_x86.inline.hpp ++../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/assembler_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.inline.hpp ++../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/copy_linux_x86.inline.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zVirtualMemory_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zNUMA_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zAddress_linux_x86.inline.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zLargePages_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_x86/vm_version_linux_x86.cpp ++../../../src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp ++../../../src/hotspot/os_cpu/linux_aarch64/bytes_linux_aarch64.inline.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/assembler_linux_aarch64.cpp ++../../../src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp ++../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.inline.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/vmStructs_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/prefetch_linux_aarch64.inline.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/orderAccess_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp ++../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp ++../../../src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.inline.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/thread_solaris_sparc.cpp ++../../../src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/vm_version_solaris_sparc.cpp ++../../../src/hotspot/os_cpu/solaris_sparc/count_trailing_zeros_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/thread_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp ++../../../src/hotspot/os_cpu/solaris_sparc/globals_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/orderAccess_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/prefetch_solaris_sparc.inline.hpp ++../../../src/hotspot/os_cpu/solaris_sparc/vmStructs_solaris_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/globals_linux_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp ++../../../src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/thread_linux_sparc.cpp ++../../../src/hotspot/os_cpu/linux_sparc/prefetch_linux_sparc.inline.hpp ++../../../src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp ++../../../src/hotspot/os_cpu/linux_sparc/orderAccess_linux_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/thread_linux_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/os_linux_sparc.hpp ++../../../src/hotspot/os_cpu/linux_sparc/vmStructs_linux_sparc.hpp ++../../../src/hotspot/os_cpu/bsd_zero/bytes_bsd_zero.inline.hpp ++../../../src/hotspot/os_cpu/bsd_zero/prefetch_bsd_zero.inline.hpp ++../../../src/hotspot/os_cpu/bsd_zero/vm_version_bsd_zero.cpp ++../../../src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp ++../../../src/hotspot/os_cpu/bsd_zero/thread_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_zero/os_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_zero/thread_bsd_zero.cpp ++../../../src/hotspot/os_cpu/bsd_zero/assembler_bsd_zero.cpp ++../../../src/hotspot/os_cpu/bsd_zero/vmStructs_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_zero/orderAccess_bsd_zero.hpp ++../../../src/hotspot/os_cpu/bsd_x86/assembler_bsd_x86.cpp ++../../../src/hotspot/os_cpu/bsd_x86/orderAccess_bsd_x86.hpp ++../../../src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.inline.hpp ++../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp ++../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.inline.hpp ++../../../src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp ++../../../src/hotspot/os_cpu/bsd_x86/vm_version_bsd_x86.cpp ++../../../src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp ++../../../src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp ++../../../src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.hpp ++../../../src/hotspot/os_cpu/bsd_x86/prefetch_bsd_x86.inline.hpp ++../../../src/hotspot/os_cpu/bsd_x86/bytes_bsd_x86.inline.hpp ++../../../src/hotspot/os_cpu/bsd_x86/vmStructs_bsd_x86.hpp ++../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.hpp ++../../../src/hotspot/os_cpu/linux_ppc/os_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_ppc/prefetch_linux_ppc.inline.hpp ++../../../src/hotspot/os_cpu/linux_ppc/bytes_linux_ppc.inline.hpp ++../../../src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp ++../../../src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_ppc/vmStructs_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp ++../../../src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp ++../../../src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp ++../../../src/hotspot/os_cpu/linux_s390/prefetch_linux_s390.inline.hpp ++../../../src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp ++../../../src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp ++../../../src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp ++../../../src/hotspot/os_cpu/linux_s390/bytes_linux_s390.inline.hpp ++../../../src/hotspot/os_cpu/linux_s390/thread_linux_s390.hpp ++../../../src/hotspot/os_cpu/linux_s390/orderAccess_linux_s390.hpp ++../../../src/hotspot/os_cpu/linux_s390/vmStructs_linux_s390.hpp ++../../../src/hotspot/os_cpu/linux_s390/os_linux_s390.hpp ++../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp ++../../../src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/bytes_windows_x86.inline.hpp ++../../../src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/copy_windows_x86.inline.hpp ++../../../src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp ++../../../src/hotspot/os_cpu/windows_x86/prefetch_windows_x86.inline.hpp ++../../../src/hotspot/os_cpu/windows_x86/unwind_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/vm_version_windows_x86.cpp ++../../../src/hotspot/os_cpu/windows_x86/thread_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/orderAccess_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/assembler_windows_x86.cpp ++../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp ++../../../src/hotspot/os_cpu/windows_x86/vmStructs_windows_x86.hpp ++../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp ++../../../src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp ++../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp ++../../../src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp ++../../../src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.inline.hpp ++../../../src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp ++../../../src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/count_trailing_zeros_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp ++../../../src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp ++../../../src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.inline.hpp ++../../../src/hotspot/os/posix/jvm_posix.cpp ++../../../src/hotspot/os/posix/include/jvm_md.h ++../../../src/hotspot/os/posix/os_posix.hpp ++../../../src/hotspot/os/posix/semaphore_posix.cpp ++../../../src/hotspot/os/posix/threadLocalStorage_posix.cpp ++../../../src/hotspot/os/posix/vmError_posix.cpp ++../../../src/hotspot/os/posix/os_posix.cpp ++../../../src/hotspot/os/posix/semaphore_posix.hpp ++../../../src/hotspot/os/bsd/semaphore_bsd.cpp ++../../../src/hotspot/os/bsd/osThread_bsd.hpp ++../../../src/hotspot/os/bsd/os_bsd.inline.hpp ++../../../src/hotspot/os/bsd/globals_bsd.hpp ++../../../src/hotspot/os/bsd/os_share_bsd.hpp ++../../../src/hotspot/os/bsd/os_bsd.hpp ++../../../src/hotspot/os/bsd/perfMemory_bsd.cpp ++../../../src/hotspot/os/bsd/decoder_machO.cpp ++../../../src/hotspot/os/bsd/c1_globals_bsd.hpp ++../../../src/hotspot/os/bsd/threadCritical_bsd.cpp ++../../../src/hotspot/os/bsd/os_bsd.cpp ++../../../src/hotspot/os/bsd/attachListener_bsd.cpp ++../../../src/hotspot/os/bsd/decoder_machO.hpp ++../../../src/hotspot/os/bsd/vmStructs_bsd.hpp ++../../../src/hotspot/os/bsd/os_perf_bsd.cpp ++../../../src/hotspot/os/bsd/semaphore_bsd.hpp ++../../../src/hotspot/os/bsd/osThread_bsd.cpp ++../../../src/hotspot/os/bsd/c2_globals_bsd.hpp ++../../../src/hotspot/os/linux/osContainer_linux.cpp ++../../../src/hotspot/os/linux/decoder_linux.cpp ++../../../src/hotspot/os/linux/perfMemory_linux.cpp ++../../../src/hotspot/os/linux/osThread_linux.cpp ++../../../src/hotspot/os/linux/os_linux.cpp ++../../../src/hotspot/os/linux/globals_linux.hpp ++../../../src/hotspot/os/linux/c2_globals_linux.hpp ++../../../src/hotspot/os/linux/os_linux.hpp ++../../../src/hotspot/os/linux/os_share_linux.hpp ++../../../src/hotspot/os/linux/threadCritical_linux.cpp ++../../../src/hotspot/os/linux/os_linux.inline.hpp ++../../../src/hotspot/os/linux/osContainer_linux.hpp ++../../../src/hotspot/os/linux/attachListener_linux.cpp ++../../../src/hotspot/os/linux/c1_globals_linux.hpp ++../../../src/hotspot/os/linux/os_perf_linux.cpp ++../../../src/hotspot/os/linux/vmStructs_linux.hpp ++../../../src/hotspot/os/linux/osThread_linux.hpp ++../../../src/hotspot/os/windows/globals_windows.hpp ++../../../src/hotspot/os/windows/semaphore_windows.cpp ++../../../src/hotspot/os/windows/decoder_windows.cpp ++../../../src/hotspot/os/windows/os_perf_windows.cpp ++../../../src/hotspot/os/windows/iphlp_interface.cpp ++../../../src/hotspot/os/windows/threadCritical_windows.cpp ++../../../src/hotspot/os/windows/threadLocalStorage_windows.cpp ++../../../src/hotspot/os/windows/include/jvm_md.h ++../../../src/hotspot/os/windows/pdh_interface.cpp ++../../../src/hotspot/os/windows/symbolengine.hpp ++../../../src/hotspot/os/windows/windbghelp.hpp ++../../../src/hotspot/os/windows/osThread_windows.hpp ++../../../src/hotspot/os/windows/os_windows.hpp ++../../../src/hotspot/os/windows/vmStructs_windows.hpp ++../../../src/hotspot/os/windows/perfMemory_windows.cpp ++../../../src/hotspot/os/windows/pdh_interface.hpp ++../../../src/hotspot/os/windows/symbolengine.cpp ++../../../src/hotspot/os/windows/windbghelp.cpp ++../../../src/hotspot/os/windows/os_windows.cpp ++../../../src/hotspot/os/windows/osThread_windows.cpp ++../../../src/hotspot/os/windows/semaphore_windows.hpp ++../../../src/hotspot/os/windows/jvm_windows.cpp ++../../../src/hotspot/os/windows/c1_globals_windows.hpp ++../../../src/hotspot/os/windows/os_windows.inline.hpp ++../../../src/hotspot/os/windows/sharedRuntimeRem.cpp ++../../../src/hotspot/os/windows/c2_globals_windows.hpp ++../../../src/hotspot/os/windows/iphlp_interface.hpp ++../../../src/hotspot/os/windows/attachListener_windows.cpp ++../../../src/hotspot/os/windows/vmError_windows.cpp ++../../../src/hotspot/os/windows/os_share_windows.hpp ++../../../src/hotspot/os/solaris/globals_solaris.hpp ++../../../src/hotspot/os/solaris/decoder_solaris.cpp ++../../../src/hotspot/os/solaris/os_perf_solaris.cpp ++../../../src/hotspot/os/solaris/os_solaris.inline.hpp ++../../../src/hotspot/os/solaris/threadCritical_solaris.cpp ++../../../src/hotspot/os/solaris/osThread_solaris.hpp ++../../../src/hotspot/os/solaris/os_solaris.hpp ++../../../src/hotspot/os/solaris/perfMemory_solaris.cpp ++../../../src/hotspot/os/solaris/vmStructs_solaris.hpp ++../../../src/hotspot/os/solaris/os_solaris.cpp ++../../../src/hotspot/os/solaris/osThread_solaris.cpp ++../../../src/hotspot/os/solaris/c1_globals_solaris.hpp ++../../../src/hotspot/os/solaris/c2_globals_solaris.hpp ++../../../src/hotspot/os/solaris/os_share_solaris.hpp ++../../../src/hotspot/os/solaris/attachListener_solaris.cpp ++../../../src/hotspot/os/aix/loadlib_aix.hpp ++../../../src/hotspot/os/aix/threadCritical_aix.cpp ++../../../src/hotspot/os/aix/c1_globals_aix.hpp ++../../../src/hotspot/os/aix/libperfstat_aix.hpp ++../../../src/hotspot/os/aix/perfMemory_aix.cpp ++../../../src/hotspot/os/aix/os_aix.hpp ++../../../src/hotspot/os/aix/porting_aix.cpp ++../../../src/hotspot/os/aix/os_share_aix.hpp ++../../../src/hotspot/os/aix/safepointMechanism_aix.cpp ++../../../src/hotspot/os/aix/libodm_aix.cpp ++../../../src/hotspot/os/aix/libo4.cpp ++../../../src/hotspot/os/aix/misc_aix.cpp ++../../../src/hotspot/os/aix/globals_aix.hpp ++../../../src/hotspot/os/aix/osThread_aix.hpp ++../../../src/hotspot/os/aix/c2_globals_aix.hpp ++../../../src/hotspot/os/aix/libodm_aix.hpp ++../../../src/hotspot/os/aix/libo4.hpp ++../../../src/hotspot/os/aix/misc_aix.hpp ++../../../src/hotspot/os/aix/decoder_aix.hpp ++../../../src/hotspot/os/aix/osThread_aix.cpp ++../../../src/hotspot/os/aix/os_aix.inline.hpp ++../../../src/hotspot/os/aix/os_perf_aix.cpp ++../../../src/hotspot/os/aix/loadlib_aix.cpp ++../../../src/hotspot/os/aix/vmStructs_aix.hpp ++../../../src/hotspot/os/aix/attachListener_aix.cpp ++../../../src/hotspot/os/aix/libperfstat_aix.cpp ++../../../src/hotspot/os/aix/os_aix.cpp ++../../../src/hotspot/os/aix/porting_aix.hpp ++../../../src/hotspot/share/interpreter/bytecodeTracer.cpp ++../../../src/hotspot/share/interpreter/bytecodeHistogram.cpp ++../../../src/hotspot/share/interpreter/bytecodeInterpreter.cpp ++../../../src/hotspot/share/interpreter/cppInterpreterGenerator.hpp ++../../../src/hotspot/share/interpreter/rewriter.hpp ++../../../src/hotspot/share/interpreter/bytecodes.hpp ++../../../src/hotspot/share/interpreter/bytecode.cpp ++../../../src/hotspot/share/interpreter/templateInterpreter.hpp ++../../../src/hotspot/share/interpreter/bytecodeInterpreterProfiling.hpp ++../../../src/hotspot/share/interpreter/interpreter.cpp ++../../../src/hotspot/share/interpreter/oopMapCache.cpp ++../../../src/hotspot/share/interpreter/linkResolver.cpp ++../../../src/hotspot/share/interpreter/templateTable.hpp ++../../../src/hotspot/share/interpreter/abstractInterpreter.hpp ++../../../src/hotspot/share/interpreter/invocationCounter.cpp ++../../../src/hotspot/share/interpreter/cppInterpreter.cpp ++../../../src/hotspot/share/interpreter/interp_masm.hpp ++../../../src/hotspot/share/interpreter/bytecodeStream.cpp ++../../../src/hotspot/share/interpreter/templateInterpreterGenerator.hpp ++../../../src/hotspot/share/interpreter/interpreterRuntime.hpp ++../../../src/hotspot/share/interpreter/linkResolver.hpp ++../../../src/hotspot/share/interpreter/templateTable.cpp ++../../../src/hotspot/share/interpreter/abstractInterpreter.cpp ++../../../src/hotspot/share/interpreter/bytecodeInterpreter.inline.hpp ++../../../src/hotspot/share/interpreter/invocationCounter.hpp ++../../../src/hotspot/share/interpreter/cppInterpreter.hpp ++../../../src/hotspot/share/interpreter/bytecodeStream.hpp ++../../../src/hotspot/share/interpreter/templateInterpreterGenerator.cpp ++../../../src/hotspot/share/interpreter/interpreterRuntime.cpp ++../../../src/hotspot/share/interpreter/bytecodeHistogram.hpp ++../../../src/hotspot/share/interpreter/bytecodeTracer.hpp ++../../../src/hotspot/share/interpreter/bytecodeInterpreter.hpp ++../../../src/hotspot/share/interpreter/cppInterpreterGenerator.cpp ++../../../src/hotspot/share/interpreter/bytecodes.cpp ++../../../src/hotspot/share/interpreter/rewriter.cpp ++../../../src/hotspot/share/interpreter/bytecode.hpp ++../../../src/hotspot/share/interpreter/templateInterpreter.cpp ++../../../src/hotspot/share/interpreter/interpreter.hpp ++../../../src/hotspot/share/interpreter/oopMapCache.hpp ++../../../src/hotspot/share/interpreter/bytecode.inline.hpp ++../../../src/hotspot/share/metaprogramming/isIntegral.hpp ++../../../src/hotspot/share/metaprogramming/isPointer.hpp ++../../../src/hotspot/share/metaprogramming/isFloatingPoint.hpp ++../../../src/hotspot/share/metaprogramming/isVolatile.hpp ++../../../src/hotspot/share/metaprogramming/isSame.hpp ++../../../src/hotspot/share/metaprogramming/removePointer.hpp ++../../../src/hotspot/share/metaprogramming/removeReference.hpp ++../../../src/hotspot/share/metaprogramming/removeCV.hpp ++../../../src/hotspot/share/metaprogramming/decay.hpp ++../../../src/hotspot/share/metaprogramming/isSigned.hpp ++../../../src/hotspot/share/metaprogramming/enableIf.hpp ++../../../src/hotspot/share/metaprogramming/conditional.hpp ++../../../src/hotspot/share/metaprogramming/integralConstant.hpp ++../../../src/hotspot/share/metaprogramming/isConst.hpp ++../../../src/hotspot/share/metaprogramming/primitiveConversions.hpp ++../../../src/hotspot/share/metaprogramming/isRegisteredEnum.hpp ++../../../src/hotspot/share/asm/codeBuffer.hpp ++../../../src/hotspot/share/asm/macroAssembler.hpp ++../../../src/hotspot/share/asm/register.hpp ++../../../src/hotspot/share/asm/assembler.cpp ++../../../src/hotspot/share/asm/register.cpp ++../../../src/hotspot/share/asm/assembler.hpp ++../../../src/hotspot/share/asm/codeBuffer.cpp ++../../../src/hotspot/share/asm/assembler.inline.hpp ++../../../src/hotspot/share/asm/macroAssembler.inline.hpp ++../../../src/hotspot/share/memory/resourceArea.hpp ++../../../src/hotspot/share/memory/freeList.inline.hpp ++../../../src/hotspot/share/memory/oopFactory.cpp ++../../../src/hotspot/share/memory/metaspaceShared.cpp ++../../../src/hotspot/share/memory/metaspaceTracer.cpp ++../../../src/hotspot/share/memory/metaspace.cpp ++../../../src/hotspot/share/memory/metaspaceClosure.cpp ++../../../src/hotspot/share/memory/iterator.cpp ++../../../src/hotspot/share/memory/allocation.inline.hpp ++../../../src/hotspot/share/memory/metaspaceGCThresholdUpdater.hpp ++../../../src/hotspot/share/memory/memRegion.hpp ++../../../src/hotspot/share/memory/allocation.cpp ++../../../src/hotspot/share/memory/guardedMemory.hpp ++../../../src/hotspot/share/memory/binaryTreeDictionary.hpp ++../../../src/hotspot/share/memory/heapInspection.cpp ++../../../src/hotspot/share/memory/heap.cpp ++../../../src/hotspot/share/memory/metaspaceCounters.cpp ++../../../src/hotspot/share/memory/filemap.hpp ++../../../src/hotspot/share/memory/universe.hpp ++../../../src/hotspot/share/memory/arena.cpp ++../../../src/hotspot/share/memory/virtualspace.cpp ++../../../src/hotspot/share/memory/operator_new.cpp ++../../../src/hotspot/share/memory/iterator.inline.hpp ++../../../src/hotspot/share/memory/allocation.hpp ++../../../src/hotspot/share/memory/guardedMemory.cpp ++../../../src/hotspot/share/memory/padded.inline.hpp ++../../../src/hotspot/share/memory/heapInspection.hpp ++../../../src/hotspot/share/memory/heap.hpp ++../../../src/hotspot/share/memory/filemap.cpp ++../../../src/hotspot/share/memory/metaspaceCounters.hpp ++../../../src/hotspot/share/memory/arena.hpp ++../../../src/hotspot/share/memory/universe.cpp ++../../../src/hotspot/share/memory/virtualspace.hpp ++../../../src/hotspot/share/memory/resourceArea.cpp ++../../../src/hotspot/share/memory/metaspaceShared.hpp ++../../../src/hotspot/share/memory/oopFactory.hpp ++../../../src/hotspot/share/memory/metaspaceTracer.hpp ++../../../src/hotspot/share/memory/metaspace/virtualSpaceList.hpp ++../../../src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp ++../../../src/hotspot/share/memory/metaspace/metaspaceCommon.hpp ++../../../src/hotspot/share/memory/metaspace/chunkManager.hpp ++../../../src/hotspot/share/memory/metaspace/occupancyMap.cpp ++../../../src/hotspot/share/memory/metaspace/smallBlocks.hpp ++../../../src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp ++../../../src/hotspot/share/memory/metaspace/spaceManager.cpp ++../../../src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp ++../../../src/hotspot/share/memory/metaspace/metaDebug.cpp ++../../../src/hotspot/share/memory/metaspace/metachunk.hpp ++../../../src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.hpp ++../../../src/hotspot/share/memory/metaspace/blockFreelist.hpp ++../../../src/hotspot/share/memory/metaspace/metaspaceStatistics.hpp ++../../../src/hotspot/share/memory/metaspace/metablock.hpp ++../../../src/hotspot/share/memory/metaspace/metabase.hpp ++../../../src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp ++../../../src/hotspot/share/memory/metaspace/metaDebug.hpp ++../../../src/hotspot/share/memory/metaspace/metachunk.cpp ++../../../src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp ++../../../src/hotspot/share/memory/metaspace/blockFreelist.cpp ++../../../src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp ++../../../src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp ++../../../src/hotspot/share/memory/metaspace/virtualSpaceList.cpp ++../../../src/hotspot/share/memory/metaspace/metaspaceCommon.cpp ++../../../src/hotspot/share/memory/metaspace/occupancyMap.hpp ++../../../src/hotspot/share/memory/metaspace/chunkManager.cpp ++../../../src/hotspot/share/memory/metaspace/smallBlocks.cpp ++../../../src/hotspot/share/memory/metaspace/virtualSpaceNode.hpp ++../../../src/hotspot/share/memory/metaspace/spaceManager.hpp ++../../../src/hotspot/share/memory/metaspace.hpp ++../../../src/hotspot/share/memory/referenceType.hpp ++../../../src/hotspot/share/memory/metadataFactory.hpp ++../../../src/hotspot/share/memory/freeList.hpp ++../../../src/hotspot/share/memory/metaspaceClosure.hpp ++../../../src/hotspot/share/memory/resourceArea.inline.hpp ++../../../src/hotspot/share/memory/padded.hpp ++../../../src/hotspot/share/memory/metaspaceChunkFreeListSummary.hpp ++../../../src/hotspot/share/memory/iterator.hpp ++../../../src/hotspot/share/memory/binaryTreeDictionary.inline.hpp ++../../../src/hotspot/share/memory/memRegion.cpp ++../../../src/hotspot/share/jfr/dcmd/jfrDcmds.cpp ++../../../src/hotspot/share/jfr/dcmd/jfrDcmds.hpp ++../../../src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp ++../../../src/hotspot/share/jfr/periodic/jfrOSInterface.cpp ++../../../src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp ++../../../src/hotspot/share/jfr/periodic/jfrPeriodic.cpp ++../../../src/hotspot/share/jfr/periodic/jfrNetworkUtilization.cpp ++../../../src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp ++../../../src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp ++../../../src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp ++../../../src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.hpp ++../../../src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.cpp ++../../../src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp ++../../../src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp ++../../../src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp ++../../../src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp ++../../../src/hotspot/share/jfr/periodic/jfrOSInterface.hpp ++../../../src/hotspot/share/jfr/jfrEvents.hpp ++../../../src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp ++../../../src/hotspot/share/jfr/writers/jfrEventWriterHost.inline.hpp ++../../../src/hotspot/share/jfr/writers/jfrNativeEventWriter.hpp ++../../../src/hotspot/share/jfr/writers/jfrEncoding.hpp ++../../../src/hotspot/share/jfr/writers/jfrStorageHost.hpp ++../../../src/hotspot/share/jfr/writers/jfrStorageAdapter.hpp ++../../../src/hotspot/share/jfr/writers/jfrEncoders.hpp ++../../../src/hotspot/share/jfr/writers/jfrPosition.hpp ++../../../src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp ++../../../src/hotspot/share/jfr/writers/jfrPosition.inline.hpp ++../../../src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp ++../../../src/hotspot/share/jfr/writers/jfrStorageHost.inline.hpp ++../../../src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp ++../../../src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp ++../../../src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp ++../../../src/hotspot/share/jfr/writers/jfrBigEndianWriter.hpp ++../../../src/hotspot/share/jfr/writers/jfrWriterHost.hpp ++../../../src/hotspot/share/jfr/writers/jfrEventWriterHost.hpp ++../../../src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp ++../../../src/hotspot/share/jfr/jfr.hpp ++../../../src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.hpp ++../../../src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp ++../../../src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp ++../../../src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp ++../../../src/hotspot/share/jfr/utilities/jfrAllocation.cpp ++../../../src/hotspot/share/jfr/utilities/jfrTypes.hpp ++../../../src/hotspot/share/jfr/utilities/jfrTimeConverter.cpp ++../../../src/hotspot/share/jfr/utilities/jfrTryLock.hpp ++../../../src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp ++../../../src/hotspot/share/jfr/utilities/jfrResourceManager.hpp ++../../../src/hotspot/share/jfr/utilities/jfrTime.hpp ++../../../src/hotspot/share/jfr/utilities/jfrJavaLog.cpp ++../../../src/hotspot/share/jfr/utilities/jfrRefCountPointer.hpp ++../../../src/hotspot/share/jfr/utilities/jfrIterator.hpp ++../../../src/hotspot/share/jfr/utilities/jfrTime.cpp ++../../../src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp ++../../../src/hotspot/share/jfr/utilities/jfrJavaLog.hpp ++../../../src/hotspot/share/jfr/utilities/jfrHashtable.hpp ++../../../src/hotspot/share/jfr/utilities/jfrAllocation.hpp ++../../../src/hotspot/share/jfr/utilities/jfrLogTagSets.hpp ++../../../src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp ++../../../src/hotspot/share/jfr/utilities/jfrBigEndian.hpp ++../../../src/hotspot/share/jfr/jfr.cpp ++../../../src/hotspot/share/jfr/support/jfrIntrinsics.hpp ++../../../src/hotspot/share/jfr/support/jfrAllocationTracer.cpp ++../../../src/hotspot/share/jfr/support/jfrKlassExtension.hpp ++../../../src/hotspot/share/jfr/support/jfrFlush.hpp ++../../../src/hotspot/share/jfr/support/jfrStackTraceMark.hpp ++../../../src/hotspot/share/jfr/support/jfrThreadLocal.cpp ++../../../src/hotspot/share/jfr/support/jfrEventClass.cpp ++../../../src/hotspot/share/jfr/support/jfrFlush.cpp ++../../../src/hotspot/share/jfr/support/jfrStackTraceMark.cpp ++../../../src/hotspot/share/jfr/support/jfrThreadLocal.hpp ++../../../src/hotspot/share/jfr/support/jfrEventClass.hpp ++../../../src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp ++../../../src/hotspot/share/jfr/support/jfrThreadExtension.hpp ++../../../src/hotspot/share/jfr/support/jfrAllocationTracer.hpp ++../../../src/hotspot/share/jfr/support/jfrThreadId.hpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolBuffer.cpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolWriter.hpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolWriter.cpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp ++../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolBuffer.hpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp ++../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointBlob.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointBlob.cpp ++../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp ++../../../src/hotspot/share/jfr/recorder/jfrRecorder.hpp ++../../../src/hotspot/share/jfr/recorder/jfrEventSetting.cpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorageControl.cpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorage.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrStorageControl.hpp ++../../../src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp ++../../../src/hotspot/share/jfr/recorder/jfrRecorder.cpp ++../../../src/hotspot/share/jfr/recorder/jfrEventSetting.hpp ++../../../src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp ++../../../src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp ++../../../src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp ++../../../src/hotspot/share/jfr/recorder/service/jfrMemorySizer.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrEvent.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp ++../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp ++../../../src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp ++../../../src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp ++../../../src/hotspot/share/jfr/recorder/service/jfrEvent.hpp ++../../../src/hotspot/share/jfr/recorder/jfrEventSetting.inline.hpp ++../../../src/hotspot/share/jfr/leakprofiler/stopOperation.hpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.hpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.hpp ++../../../src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp ++../../../src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.hpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/sampleList.cpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/samplePriorityQueue.cpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/samplePriorityQueue.hpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp ++../../../src/hotspot/share/jfr/leakprofiler/sampling/sampleList.hpp ++../../../src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/saveRestore.hpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.cpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/saveRestore.cpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp ++../../../src/hotspot/share/jfr/leakprofiler/utilities/unifiedOop.hpp ++../../../src/hotspot/share/jfr/leakprofiler/startOperation.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edge.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/bitset.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/objectSampleMarker.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeQueue.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeQueue.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edge.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp ++../../../src/hotspot/share/jfr/leakprofiler/chains/bitset.cpp ++../../../src/hotspot/share/jfr/jni/jfrJniMethod.hpp ++../../../src/hotspot/share/jfr/jni/jfrUpcalls.cpp ++../../../src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp ++../../../src/hotspot/share/jfr/jni/jfrJavaSupport.cpp ++../../../src/hotspot/share/jfr/jni/jfrGetAllEventClasses.cpp ++../../../src/hotspot/share/jfr/jni/jfrJavaCall.hpp ++../../../src/hotspot/share/jfr/jni/jfrJavaSupport.hpp ++../../../src/hotspot/share/jfr/jni/jfrGetAllEventClasses.hpp ++../../../src/hotspot/share/jfr/jni/jfrJavaCall.cpp ++../../../src/hotspot/share/jfr/jni/jfrJniMethod.cpp ++../../../src/hotspot/share/jfr/jni/jfrUpcalls.hpp ++../../../src/hotspot/share/jfr/jni/jfrJniMethodRegistration.hpp ++../../../src/hotspot/share/jfr/metadata/jfrSerializer.hpp ++../../../src/hotspot/share/ci/ciConstantPoolCache.hpp ++../../../src/hotspot/share/ci/ciClassList.hpp ++../../../src/hotspot/share/ci/ciTypeArray.hpp ++../../../src/hotspot/share/ci/ciCallSite.hpp ++../../../src/hotspot/share/ci/ciType.cpp ++../../../src/hotspot/share/ci/ciTypeArrayKlass.cpp ++../../../src/hotspot/share/ci/ciMethodBlocks.hpp ++../../../src/hotspot/share/ci/ciArray.hpp ++../../../src/hotspot/share/ci/ciTypeFlow.hpp ++../../../src/hotspot/share/ci/bcEscapeAnalyzer.cpp ++../../../src/hotspot/share/ci/ciNullObject.hpp ++../../../src/hotspot/share/ci/ciField.hpp ++../../../src/hotspot/share/ci/ciConstant.cpp ++../../../src/hotspot/share/ci/ciArrayKlass.hpp ++../../../src/hotspot/share/ci/ciMethodType.hpp ++../../../src/hotspot/share/ci/ciReplay.hpp ++../../../src/hotspot/share/ci/ciInstanceKlass.hpp ++../../../src/hotspot/share/ci/ciSignature.hpp ++../../../src/hotspot/share/ci/ciInstance.cpp ++../../../src/hotspot/share/ci/ciSymbol.cpp ++../../../src/hotspot/share/ci/ciObjArray.cpp ++../../../src/hotspot/share/ci/ciMetadata.cpp ++../../../src/hotspot/share/ci/ciMemberName.cpp ++../../../src/hotspot/share/ci/ciObjArrayKlass.cpp ++../../../src/hotspot/share/ci/ciMethod.hpp ++../../../src/hotspot/share/ci/ciMethodHandle.hpp ++../../../src/hotspot/share/ci/ciFlags.cpp ++../../../src/hotspot/share/ci/ciObjectFactory.hpp ++../../../src/hotspot/share/ci/ciUtilities.hpp ++../../../src/hotspot/share/ci/ciEnv.hpp ++../../../src/hotspot/share/ci/ciStreams.cpp ++../../../src/hotspot/share/ci/ciKlass.hpp ++../../../src/hotspot/share/ci/ciMethodData.cpp ++../../../src/hotspot/share/ci/ciObject.cpp ++../../../src/hotspot/share/ci/ciExceptionHandler.cpp ++../../../src/hotspot/share/ci/ciBaseObject.cpp ++../../../src/hotspot/share/ci/ciObjArray.hpp ++../../../src/hotspot/share/ci/ciObjArrayKlass.hpp ++../../../src/hotspot/share/ci/ciMemberName.hpp ++../../../src/hotspot/share/ci/ciMetadata.hpp ++../../../src/hotspot/share/ci/ciUtilities.inline.hpp ++../../../src/hotspot/share/ci/ciMethodHandle.cpp ++../../../src/hotspot/share/ci/ciMethod.cpp ++../../../src/hotspot/share/ci/ciFlags.hpp ++../../../src/hotspot/share/ci/ciUtilities.cpp ++../../../src/hotspot/share/ci/ciObjectFactory.cpp ++../../../src/hotspot/share/ci/ciStreams.hpp ++../../../src/hotspot/share/ci/ciEnv.cpp ++../../../src/hotspot/share/ci/ciKlass.cpp ++../../../src/hotspot/share/ci/ciObject.hpp ++../../../src/hotspot/share/ci/ciMethodData.hpp ++../../../src/hotspot/share/ci/ciBaseObject.hpp ++../../../src/hotspot/share/ci/ciExceptionHandler.hpp ++../../../src/hotspot/share/ci/ciConstantPoolCache.cpp ++../../../src/hotspot/share/ci/ciTypeArray.cpp ++../../../src/hotspot/share/ci/ciTypeArrayKlass.hpp ++../../../src/hotspot/share/ci/ciType.hpp ++../../../src/hotspot/share/ci/ciCallSite.cpp ++../../../src/hotspot/share/ci/ciMethodBlocks.cpp ++../../../src/hotspot/share/ci/ciArray.cpp ++../../../src/hotspot/share/ci/compilerInterface.hpp ++../../../src/hotspot/share/ci/ciTypeFlow.cpp ++../../../src/hotspot/share/ci/bcEscapeAnalyzer.hpp ++../../../src/hotspot/share/ci/ciCallProfile.hpp ++../../../src/hotspot/share/ci/ciNullObject.cpp ++../../../src/hotspot/share/ci/ciField.cpp ++../../../src/hotspot/share/ci/ciConstant.hpp ++../../../src/hotspot/share/ci/ciArrayKlass.cpp ++../../../src/hotspot/share/ci/ciReplay.cpp ++../../../src/hotspot/share/ci/ciInstanceKlass.cpp ++../../../src/hotspot/share/ci/ciMethodType.cpp ++../../../src/hotspot/share/ci/ciSymbol.hpp ++../../../src/hotspot/share/ci/ciSignature.cpp ++../../../src/hotspot/share/ci/ciInstance.hpp ++../../../src/hotspot/share/include/jmm.h ++../../../src/hotspot/share/include/jvm.h ++../../../src/hotspot/share/c1/c1_FpuStackSim.hpp ++../../../src/hotspot/share/c1/c1_MacroAssembler.hpp ++../../../src/hotspot/share/c1/c1_ValueStack.hpp ++../../../src/hotspot/share/c1/c1_Compilation.cpp ++../../../src/hotspot/share/c1/c1_FrameMap.cpp ++../../../src/hotspot/share/c1/c1_RangeCheckElimination.hpp ++../../../src/hotspot/share/c1/c1_LIRGenerator.cpp ++../../../src/hotspot/share/c1/c1_CodeStubs.hpp ++../../../src/hotspot/share/c1/c1_InstructionPrinter.hpp ++../../../src/hotspot/share/c1/c1_IR.hpp ++../../../src/hotspot/share/c1/c1_LinearScan.hpp ++../../../src/hotspot/share/c1/c1_CFGPrinter.cpp ++../../../src/hotspot/share/c1/c1_Instruction.hpp ++../../../src/hotspot/share/c1/c1_Compiler.cpp ++../../../src/hotspot/share/c1/c1_Defs.cpp ++../../../src/hotspot/share/c1/c1_ValueSet.hpp ++../../../src/hotspot/share/c1/c1_LIR.cpp ++../../../src/hotspot/share/c1/c1_LIRAssembler.cpp ++../../../src/hotspot/share/c1/c1_Runtime1.hpp ++../../../src/hotspot/share/c1/c1_Optimizer.hpp ++../../../src/hotspot/share/c1/c1_ValueMap.cpp ++../../../src/hotspot/share/c1/c1_GraphBuilder.hpp ++../../../src/hotspot/share/c1/c1_Canonicalizer.cpp ++../../../src/hotspot/share/c1/c1_ValueType.hpp ++../../../src/hotspot/share/c1/c1_globals.hpp ++../../../src/hotspot/share/c1/c1_Instruction.cpp ++../../../src/hotspot/share/c1/c1_Defs.hpp ++../../../src/hotspot/share/c1/c1_Compiler.hpp ++../../../src/hotspot/share/c1/c1_ValueSet.cpp ++../../../src/hotspot/share/c1/c1_LIR.hpp ++../../../src/hotspot/share/c1/c1_LIRAssembler.hpp ++../../../src/hotspot/share/c1/c1_Runtime1.cpp ++../../../src/hotspot/share/c1/c1_ValueMap.hpp ++../../../src/hotspot/share/c1/c1_Optimizer.cpp ++../../../src/hotspot/share/c1/c1_GraphBuilder.cpp ++../../../src/hotspot/share/c1/c1_Canonicalizer.hpp ++../../../src/hotspot/share/c1/c1_Decorators.hpp ++../../../src/hotspot/share/c1/c1_globals.cpp ++../../../src/hotspot/share/c1/c1_ValueType.cpp ++../../../src/hotspot/share/c1/c1_ValueStack.cpp ++../../../src/hotspot/share/c1/c1_Compilation.hpp ++../../../src/hotspot/share/c1/c1_FrameMap.hpp ++../../../src/hotspot/share/c1/c1_RangeCheckElimination.cpp ++../../../src/hotspot/share/c1/c1_LIRGenerator.hpp ++../../../src/hotspot/share/c1/c1_ValueSet.inline.hpp ++../../../src/hotspot/share/c1/c1_InstructionPrinter.cpp ++../../../src/hotspot/share/c1/c1_IR.cpp ++../../../src/hotspot/share/c1/c1_LinearScan.cpp ++../../../src/hotspot/share/c1/c1_CFGPrinter.hpp ++../../../src/hotspot/share/runtime/stackValueCollection.cpp ++../../../src/hotspot/share/runtime/safepointMechanism.hpp ++../../../src/hotspot/share/runtime/prefetch.hpp ++../../../src/hotspot/share/runtime/synchronizer.cpp ++../../../src/hotspot/share/runtime/vframe.cpp ++../../../src/hotspot/share/runtime/init.hpp ++../../../src/hotspot/share/runtime/fieldDescriptor.hpp ++../../../src/hotspot/share/runtime/os.inline.hpp ++../../../src/hotspot/share/runtime/mutex.cpp ++../../../src/hotspot/share/runtime/safepoint.hpp ++../../../src/hotspot/share/runtime/thread.cpp ++../../../src/hotspot/share/runtime/jniHandles.cpp ++../../../src/hotspot/share/runtime/semaphore.hpp ++../../../src/hotspot/share/runtime/vframe.inline.hpp ++../../../src/hotspot/share/runtime/unhandledOops.hpp ++../../../src/hotspot/share/runtime/rframe.hpp ++../../../src/hotspot/share/runtime/sharedRuntimeTrig.cpp ++../../../src/hotspot/share/runtime/os.cpp ++../../../src/hotspot/share/runtime/frame.cpp ++../../../src/hotspot/share/runtime/osThread.cpp ++../../../src/hotspot/share/runtime/jniHandles.inline.hpp ++../../../src/hotspot/share/runtime/vmStructs.hpp ++../../../src/hotspot/share/runtime/vframeArray.cpp ++../../../src/hotspot/share/runtime/threadLocalStorage.hpp ++../../../src/hotspot/share/runtime/reflectionUtils.hpp ++../../../src/hotspot/share/runtime/signature.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlag.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagWriteableList.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp ++../../../src/hotspot/share/runtime/flags/jvmFlag.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp ++../../../src/hotspot/share/runtime/flags/flagSetting.hpp ++../../../src/hotspot/share/runtime/flags/jvmFlagWriteableList.hpp ++../../../src/hotspot/share/runtime/orderAccess.cpp ++../../../src/hotspot/share/runtime/handles.inline.hpp ++../../../src/hotspot/share/runtime/arguments.cpp ++../../../src/hotspot/share/runtime/handles.hpp ++../../../src/hotspot/share/runtime/objectMonitor.hpp ++../../../src/hotspot/share/runtime/threadCritical.hpp ++../../../src/hotspot/share/runtime/park.hpp ++../../../src/hotspot/share/runtime/sweeper.cpp ++../../../src/hotspot/share/runtime/relocator.cpp ++../../../src/hotspot/share/runtime/sharedRuntime.hpp ++../../../src/hotspot/share/runtime/arguments_ext.cpp ++../../../src/hotspot/share/runtime/prefetch.inline.hpp ++../../../src/hotspot/share/runtime/globals_ext.hpp ++../../../src/hotspot/share/runtime/basicLock.hpp ++../../../src/hotspot/share/runtime/compilationPolicy.cpp ++../../../src/hotspot/share/runtime/java.hpp ++../../../src/hotspot/share/runtime/objectMonitor.inline.hpp ++../../../src/hotspot/share/runtime/mutexLocker.cpp ++../../../src/hotspot/share/runtime/serviceThread.cpp ++../../../src/hotspot/share/runtime/statSampler.cpp ++../../../src/hotspot/share/runtime/vm_operations.hpp ++../../../src/hotspot/share/runtime/timer.cpp ++../../../src/hotspot/share/runtime/stackValue.hpp ++../../../src/hotspot/share/runtime/monitorChunk.hpp ++../../../src/hotspot/share/runtime/extendedPC.hpp ++../../../src/hotspot/share/runtime/biasedLocking.cpp ++../../../src/hotspot/share/runtime/vmThread.cpp ++../../../src/hotspot/share/runtime/timerTrace.cpp ++../../../src/hotspot/share/runtime/os_ext.hpp ++../../../src/hotspot/share/runtime/stubCodeGenerator.cpp ++../../../src/hotspot/share/runtime/threadSMR.cpp ++../../../src/hotspot/share/runtime/task.hpp ++../../../src/hotspot/share/runtime/perfData.hpp ++../../../src/hotspot/share/runtime/vframe_hp.hpp ++../../../src/hotspot/share/runtime/stubRoutines.hpp ++../../../src/hotspot/share/runtime/threadHeapSampler.hpp ++../../../src/hotspot/share/runtime/vm_version.cpp ++../../../src/hotspot/share/runtime/memprofiler.hpp ++../../../src/hotspot/share/runtime/fieldType.hpp ++../../../src/hotspot/share/runtime/safepointVerifiers.hpp ++../../../src/hotspot/share/runtime/globals.cpp ++../../../src/hotspot/share/runtime/threadStatisticalInfo.hpp ++../../../src/hotspot/share/runtime/handshake.cpp ++../../../src/hotspot/share/runtime/atomic.hpp ++../../../src/hotspot/share/runtime/jniPeriodicChecker.cpp ++../../../src/hotspot/share/runtime/deoptimization.hpp ++../../../src/hotspot/share/runtime/perfMemory.cpp ++../../../src/hotspot/share/runtime/interfaceSupport.inline.hpp ++../../../src/hotspot/share/runtime/os_perf.hpp ++../../../src/hotspot/share/runtime/globals_extension.hpp ++../../../src/hotspot/share/runtime/threadSMR.inline.hpp ++../../../src/hotspot/share/runtime/icache.hpp ++../../../src/hotspot/share/runtime/reflection.hpp ++../../../src/hotspot/share/runtime/javaCalls.hpp ++../../../src/hotspot/share/runtime/rtmLocking.hpp ++../../../src/hotspot/share/runtime/compilationPolicy.hpp ++../../../src/hotspot/share/runtime/basicLock.cpp ++../../../src/hotspot/share/runtime/java.cpp ++../../../src/hotspot/share/runtime/perfData.inline.hpp ++../../../src/hotspot/share/runtime/statSampler.hpp ++../../../src/hotspot/share/runtime/vm_operations.cpp ++../../../src/hotspot/share/runtime/mutexLocker.hpp ++../../../src/hotspot/share/runtime/serviceThread.hpp ++../../../src/hotspot/share/runtime/monitorChunk.cpp ++../../../src/hotspot/share/runtime/stackValue.cpp ++../../../src/hotspot/share/runtime/timer.hpp ++../../../src/hotspot/share/runtime/vmThread.hpp ++../../../src/hotspot/share/runtime/jfieldIDWorkaround.hpp ++../../../src/hotspot/share/runtime/biasedLocking.hpp ++../../../src/hotspot/share/runtime/registerMap.hpp ++../../../src/hotspot/share/runtime/threadSMR.hpp ++../../../src/hotspot/share/runtime/task.cpp ++../../../src/hotspot/share/runtime/perfData.cpp ++../../../src/hotspot/share/runtime/stubCodeGenerator.hpp ++../../../src/hotspot/share/runtime/timerTrace.hpp ++../../../src/hotspot/share/runtime/stubRoutines.cpp ++../../../src/hotspot/share/runtime/interfaceSupport.cpp ++../../../src/hotspot/share/runtime/vframe_hp.cpp ++../../../src/hotspot/share/runtime/threadHeapSampler.cpp ++../../../src/hotspot/share/runtime/vm_version.hpp ++../../../src/hotspot/share/runtime/javaFrameAnchor.hpp ++../../../src/hotspot/share/runtime/memprofiler.cpp ++../../../src/hotspot/share/runtime/globals.hpp ++../../../src/hotspot/share/runtime/safepointVerifiers.cpp ++../../../src/hotspot/share/runtime/fieldType.cpp ++../../../src/hotspot/share/runtime/deoptimization.cpp ++../../../src/hotspot/share/runtime/jniPeriodicChecker.hpp ++../../../src/hotspot/share/runtime/handshake.hpp ++../../../src/hotspot/share/runtime/thread.inline.hpp ++../../../src/hotspot/share/runtime/perfMemory.hpp ++../../../src/hotspot/share/runtime/javaCalls.cpp ++../../../src/hotspot/share/runtime/reflection.cpp ++../../../src/hotspot/share/runtime/icache.cpp ++../../../src/hotspot/share/runtime/rtmLocking.cpp ++../../../src/hotspot/share/runtime/stackValueCollection.hpp ++../../../src/hotspot/share/runtime/safepointMechanism.cpp ++../../../src/hotspot/share/runtime/semaphore.inline.hpp ++../../../src/hotspot/share/runtime/vframe.hpp ++../../../src/hotspot/share/runtime/synchronizer.hpp ++../../../src/hotspot/share/runtime/fieldDescriptor.cpp ++../../../src/hotspot/share/runtime/init.cpp ++../../../src/hotspot/share/runtime/mutex.hpp ++../../../src/hotspot/share/runtime/thread.hpp ++../../../src/hotspot/share/runtime/jniHandles.hpp ++../../../src/hotspot/share/runtime/safepoint.cpp ++../../../src/hotspot/share/runtime/unhandledOops.cpp ++../../../src/hotspot/share/runtime/rframe.cpp ++../../../src/hotspot/share/runtime/safepointMechanism.inline.hpp ++../../../src/hotspot/share/runtime/osThread.hpp ++../../../src/hotspot/share/runtime/frame.inline.hpp ++../../../src/hotspot/share/runtime/frame.hpp ++../../../src/hotspot/share/runtime/os.hpp ++../../../src/hotspot/share/runtime/vframeArray.hpp ++../../../src/hotspot/share/runtime/vmStructs.cpp ++../../../src/hotspot/share/runtime/signature.hpp ++../../../src/hotspot/share/runtime/reflectionUtils.cpp ++../../../src/hotspot/share/runtime/orderAccess.hpp ++../../../src/hotspot/share/runtime/arguments.hpp ++../../../src/hotspot/share/runtime/handles.cpp ++../../../src/hotspot/share/runtime/objectMonitor.cpp ++../../../src/hotspot/share/runtime/sharedRuntimeMath.hpp ++../../../src/hotspot/share/runtime/sweeper.hpp ++../../../src/hotspot/share/runtime/park.cpp ++../../../src/hotspot/share/runtime/sharedRuntime.cpp ++../../../src/hotspot/share/runtime/relocator.hpp ++../../../src/hotspot/share/runtime/sharedRuntimeTrans.cpp ++../../../src/hotspot/share/runtime/arguments_ext.hpp ++../../../src/hotspot/share/libadt/set.cpp ++../../../src/hotspot/share/libadt/vectset.hpp ++../../../src/hotspot/share/libadt/dict.cpp ++../../../src/hotspot/share/libadt/set.hpp ++../../../src/hotspot/share/libadt/dict.hpp ++../../../src/hotspot/share/libadt/vectset.cpp ++../../../src/hotspot/share/code/codeCache.hpp ++../../../src/hotspot/share/code/pcDesc.hpp ++../../../src/hotspot/share/code/oopRecorder.cpp ++../../../src/hotspot/share/code/dependencies.cpp ++../../../src/hotspot/share/code/compiledMethod.inline.hpp ++../../../src/hotspot/share/code/compressedStream.hpp ++../../../src/hotspot/share/code/stubs.cpp ++../../../src/hotspot/share/code/exceptionHandlerTable.hpp ++../../../src/hotspot/share/code/nmethod.hpp ++../../../src/hotspot/share/code/compiledMethod.hpp ++../../../src/hotspot/share/code/compiledIC.cpp ++../../../src/hotspot/share/code/codeBlob.cpp ++../../../src/hotspot/share/code/codeHeapState.cpp ++../../../src/hotspot/share/code/icBuffer.cpp ++../../../src/hotspot/share/code/dependencyContext.hpp ++../../../src/hotspot/share/code/debugInfo.hpp ++../../../src/hotspot/share/code/vtableStubs.cpp ++../../../src/hotspot/share/code/nativeInst.hpp ++../../../src/hotspot/share/code/location.cpp ++../../../src/hotspot/share/code/relocInfo.cpp ++../../../src/hotspot/share/code/relocInfo_ext.hpp ++../../../src/hotspot/share/code/vmreg.cpp ++../../../src/hotspot/share/code/scopeDesc.hpp ++../../../src/hotspot/share/code/debugInfoRec.hpp ++../../../src/hotspot/share/code/codeHeapState.hpp ++../../../src/hotspot/share/code/dependencyContext.cpp ++../../../src/hotspot/share/code/icBuffer.hpp ++../../../src/hotspot/share/code/debugInfo.cpp ++../../../src/hotspot/share/code/vtableStubs.hpp ++../../../src/hotspot/share/code/relocInfo.hpp ++../../../src/hotspot/share/code/location.hpp ++../../../src/hotspot/share/code/vmreg.inline.hpp ++../../../src/hotspot/share/code/vmreg.hpp ++../../../src/hotspot/share/code/relocInfo_ext.cpp ++../../../src/hotspot/share/code/debugInfoRec.cpp ++../../../src/hotspot/share/code/scopeDesc.cpp ++../../../src/hotspot/share/code/codeCache.cpp ++../../../src/hotspot/share/code/pcDesc.cpp ++../../../src/hotspot/share/code/oopRecorder.hpp ++../../../src/hotspot/share/code/dependencies.hpp ++../../../src/hotspot/share/code/stubs.hpp ++../../../src/hotspot/share/code/compressedStream.cpp ++../../../src/hotspot/share/code/exceptionHandlerTable.cpp ++../../../src/hotspot/share/code/nmethod.cpp ++../../../src/hotspot/share/code/compiledMethod.cpp ++../../../src/hotspot/share/code/compiledIC.hpp ++../../../src/hotspot/share/code/codeBlob.hpp ++../../../src/hotspot/share/prims/jvmtiImpl.hpp ++../../../src/hotspot/share/prims/jvmtiTagMap.cpp ++../../../src/hotspot/share/prims/jvmtiExport.hpp ++../../../src/hotspot/share/prims/jvmtiEventController.inline.hpp ++../../../src/hotspot/share/prims/whitebox.inline.hpp ++../../../src/hotspot/share/prims/jvmtiTrace.cpp ++../../../src/hotspot/share/prims/cdsoffsets.hpp ++../../../src/hotspot/share/prims/jvmtiRawMonitor.cpp ++../../../src/hotspot/share/prims/jvmtiExtensions.hpp ++../../../src/hotspot/share/prims/jvmtiManageCapabilities.cpp ++../../../src/hotspot/share/prims/jvmtiRedefineClasses.cpp ++../../../src/hotspot/share/prims/nativeLookup.cpp ++../../../src/hotspot/share/prims/perf.cpp ++../../../src/hotspot/share/prims/jniCheck.cpp ++../../../src/hotspot/share/prims/forte.cpp ++../../../src/hotspot/share/prims/jvmtiEventController.hpp ++../../../src/hotspot/share/prims/jvmtiEnvThreadState.hpp ++../../../src/hotspot/share/prims/methodComparator.cpp ++../../../src/hotspot/share/prims/jvmtiThreadState.inline.hpp ++../../../src/hotspot/share/prims/resolvedMethodTable.hpp ++../../../src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp ++../../../src/hotspot/share/prims/whitebox.cpp ++../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.hpp ++../../../src/hotspot/share/prims/jvmtiAgentThread.hpp ++../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp ++../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++../../../src/hotspot/share/prims/stackwalk.cpp ++../../../src/hotspot/share/prims/privilegedStack.hpp ++../../../src/hotspot/share/prims/jvmtiUtil.hpp ++../../../src/hotspot/share/prims/jvmtiEnvBase.hpp ++../../../src/hotspot/share/prims/jvmtiThreadState.cpp ++../../../src/hotspot/share/prims/methodHandles.hpp ++../../../src/hotspot/share/prims/jniFastGetField.hpp ++../../../src/hotspot/share/prims/wbtestmethods/parserTests.cpp ++../../../src/hotspot/share/prims/wbtestmethods/parserTests.hpp ++../../../src/hotspot/share/prims/unsafe.cpp ++../../../src/hotspot/share/prims/methodComparator.hpp ++../../../src/hotspot/share/prims/jvmtiEnvThreadState.cpp ++../../../src/hotspot/share/prims/resolvedMethodTable.cpp ++../../../src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp ++../../../src/hotspot/share/prims/evmCompat.cpp ++../../../src/hotspot/share/prims/whitebox.hpp ++../../../src/hotspot/share/prims/jvmtiEnter.inline.hpp ++../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp ++../../../src/hotspot/share/prims/stackwalk.hpp ++../../../src/hotspot/share/prims/privilegedStack.cpp ++../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.hpp ++../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++../../../src/hotspot/share/prims/jvmtiUtil.cpp ++../../../src/hotspot/share/prims/jvmtiEnvBase.cpp ++../../../src/hotspot/share/prims/methodHandles.cpp ++../../../src/hotspot/share/prims/jvmtiThreadState.hpp ++../../../src/hotspot/share/prims/jniFastGetField.cpp ++../../../src/hotspot/share/prims/jvm_misc.hpp ++../../../src/hotspot/share/prims/unsafe.hpp ++../../../src/hotspot/share/prims/jvmtiImpl.cpp ++../../../src/hotspot/share/prims/jvmtiTagMap.hpp ++../../../src/hotspot/share/prims/jvmtiExport.cpp ++../../../src/hotspot/share/prims/jvmtiTrace.hpp ++../../../src/hotspot/share/prims/cdsoffsets.cpp ++../../../src/hotspot/share/prims/jvmtiRawMonitor.hpp ++../../../src/hotspot/share/prims/jvmtiExtensions.cpp ++../../../src/hotspot/share/prims/jniExport.hpp ++../../../src/hotspot/share/prims/jvmtiManageCapabilities.hpp ++../../../src/hotspot/share/prims/jvmtiRedefineClasses.hpp ++../../../src/hotspot/share/prims/jni.cpp ++../../../src/hotspot/share/prims/jvm.cpp ++../../../src/hotspot/share/prims/jvmtiEnv.cpp ++../../../src/hotspot/share/prims/nativeLookup.hpp ++../../../src/hotspot/share/prims/jniCheck.hpp ++../../../src/hotspot/share/prims/jvmtiEventController.cpp ++../../../src/hotspot/share/prims/forte.hpp ++../../../src/hotspot/share/classfile/sharedPathsMiscInfo.hpp ++../../../src/hotspot/share/classfile/classLoaderStats.cpp ++../../../src/hotspot/share/classfile/javaClasses.cpp ++../../../src/hotspot/share/classfile/compactHashtable.hpp ++../../../src/hotspot/share/classfile/metadataOnStackMark.cpp ++../../../src/hotspot/share/classfile/classFileStream.hpp ++../../../src/hotspot/share/classfile/klassFactory.cpp ++../../../src/hotspot/share/classfile/moduleEntry.cpp ++../../../src/hotspot/share/classfile/packageEntry.cpp ++../../../src/hotspot/share/classfile/bytecodeAssembler.hpp ++../../../src/hotspot/share/classfile/classListParser.hpp ++../../../src/hotspot/share/classfile/javaClasses.inline.hpp ++../../../src/hotspot/share/classfile/classLoaderExt.hpp ++../../../src/hotspot/share/classfile/classLoader.hpp ++../../../src/hotspot/share/classfile/dictionary.hpp ++../../../src/hotspot/share/classfile/classLoaderData.inline.hpp ++../../../src/hotspot/share/classfile/stringTable.cpp ++../../../src/hotspot/share/classfile/stackMapFrame.hpp ++../../../src/hotspot/share/classfile/altHashing.cpp ++../../../src/hotspot/share/classfile/placeholders.cpp ++../../../src/hotspot/share/classfile/defaultMethods.hpp ++../../../src/hotspot/share/classfile/systemDictionaryShared.hpp ++../../../src/hotspot/share/classfile/classLoader.inline.hpp ++../../../src/hotspot/share/classfile/classFileError.cpp ++../../../src/hotspot/share/classfile/javaAssertions.cpp ++../../../src/hotspot/share/classfile/classFileParser.hpp ++../../../src/hotspot/share/classfile/verifier.hpp ++../../../src/hotspot/share/classfile/protectionDomainCache.hpp ++../../../src/hotspot/share/classfile/dictionary.inline.hpp ++../../../src/hotspot/share/classfile/stackMapTable.hpp ++../../../src/hotspot/share/classfile/resolutionErrors.hpp ++../../../src/hotspot/share/classfile/symbolTable.hpp ++../../../src/hotspot/share/classfile/vmSymbols.hpp ++../../../src/hotspot/share/classfile/compactHashtable.inline.hpp ++../../../src/hotspot/share/classfile/modules.cpp ++../../../src/hotspot/share/classfile/verificationType.cpp ++../../../src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp ++../../../src/hotspot/share/classfile/loaderConstraints.cpp ++../../../src/hotspot/share/classfile/classLoaderData.cpp ++../../../src/hotspot/share/classfile/systemDictionary.hpp ++../../../src/hotspot/share/classfile/altHashing.hpp ++../../../src/hotspot/share/classfile/stringTable.hpp ++../../../src/hotspot/share/classfile/stackMapFrame.cpp ++../../../src/hotspot/share/classfile/defaultMethods.cpp ++../../../src/hotspot/share/classfile/placeholders.hpp ++../../../src/hotspot/share/classfile/systemDictionaryShared.cpp ++../../../src/hotspot/share/classfile/javaAssertions.hpp ++../../../src/hotspot/share/classfile/protectionDomainCache.cpp ++../../../src/hotspot/share/classfile/classFileParser.cpp ++../../../src/hotspot/share/classfile/verifier.cpp ++../../../src/hotspot/share/classfile/stackMapTable.cpp ++../../../src/hotspot/share/classfile/vmSymbols.cpp ++../../../src/hotspot/share/classfile/symbolTable.cpp ++../../../src/hotspot/share/classfile/resolutionErrors.cpp ++../../../src/hotspot/share/classfile/verificationType.hpp ++../../../src/hotspot/share/classfile/modules.hpp ++../../../src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp ++../../../src/hotspot/share/classfile/loaderConstraints.hpp ++../../../src/hotspot/share/classfile/classLoaderData.hpp ++../../../src/hotspot/share/classfile/systemDictionary.cpp ++../../../src/hotspot/share/classfile/sharedPathsMiscInfo.cpp ++../../../src/hotspot/share/classfile/javaClasses.hpp ++../../../src/hotspot/share/classfile/classLoaderStats.hpp ++../../../src/hotspot/share/classfile/compactHashtable.cpp ++../../../src/hotspot/share/classfile/metadataOnStackMark.hpp ++../../../src/hotspot/share/classfile/classFileStream.cpp ++../../../src/hotspot/share/classfile/moduleEntry.hpp ++../../../src/hotspot/share/classfile/klassFactory.hpp ++../../../src/hotspot/share/classfile/packageEntry.hpp ++../../../src/hotspot/share/classfile/stackMapTableFormat.hpp ++../../../src/hotspot/share/classfile/bytecodeAssembler.cpp ++../../../src/hotspot/share/classfile/classListParser.cpp ++../../../src/hotspot/share/classfile/classLoaderExt.cpp ++../../../src/hotspot/share/classfile/classLoader.cpp ++../../../src/hotspot/share/classfile/dictionary.cpp ++../../../src/hotspot/share/utilities/numberSeq.hpp ++../../../src/hotspot/share/utilities/exceptions.cpp ++../../../src/hotspot/share/utilities/vmError.hpp ++../../../src/hotspot/share/utilities/globalCounter.hpp ++../../../src/hotspot/share/utilities/resourceHash.hpp ++../../../src/hotspot/share/utilities/pair.hpp ++../../../src/hotspot/share/utilities/constantTag.hpp ++../../../src/hotspot/share/utilities/bitMap.inline.hpp ++../../../src/hotspot/share/utilities/globalDefinitions_xlc.hpp ++../../../src/hotspot/share/utilities/defaultStream.hpp ++../../../src/hotspot/share/utilities/globalCounter.inline.hpp ++../../../src/hotspot/share/utilities/intHisto.hpp ++../../../src/hotspot/share/utilities/utf8.hpp ++../../../src/hotspot/share/utilities/copy.cpp ++../../../src/hotspot/share/utilities/globalDefinitions_visCPP.hpp ++../../../src/hotspot/share/utilities/json.hpp ++../../../src/hotspot/share/utilities/elfFuncDescTable.hpp ++../../../src/hotspot/share/utilities/bitMap.cpp ++../../../src/hotspot/share/utilities/count_trailing_zeros.hpp ++../../../src/hotspot/share/utilities/quickSort.hpp ++../../../src/hotspot/share/utilities/sizes.cpp ++../../../src/hotspot/share/utilities/decoder_elf.cpp ++../../../src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp ++../../../src/hotspot/share/utilities/ostream.hpp ++../../../src/hotspot/share/utilities/macros.hpp ++../../../src/hotspot/share/utilities/elfFile.cpp ++../../../src/hotspot/share/utilities/align.hpp ++../../../src/hotspot/share/utilities/xmlstream.hpp ++../../../src/hotspot/share/utilities/internalVMTests.cpp ++../../../src/hotspot/share/utilities/preserveException.cpp ++../../../src/hotspot/share/utilities/elfSymbolTable.hpp ++../../../src/hotspot/share/utilities/spinYield.cpp ++../../../src/hotspot/share/utilities/accessFlags.cpp ++../../../src/hotspot/share/utilities/formatBuffer.cpp ++../../../src/hotspot/share/utilities/errorReporter.hpp ++../../../src/hotspot/share/utilities/globalDefinitions_sparcWorks.hpp ++../../../src/hotspot/share/utilities/histogram.hpp ++../../../src/hotspot/share/utilities/stringUtils.cpp ++../../../src/hotspot/share/utilities/ticks.cpp ++../../../src/hotspot/share/utilities/dtrace_disabled.hpp ++../../../src/hotspot/share/utilities/debug.hpp ++../../../src/hotspot/share/utilities/growableArray.cpp ++../../../src/hotspot/share/utilities/globalDefinitions.hpp ++../../../src/hotspot/share/utilities/nativeCallStack.hpp ++../../../src/hotspot/share/utilities/hashtable.hpp ++../../../src/hotspot/share/utilities/decoder.hpp ++../../../src/hotspot/share/utilities/elfStringTable.cpp ++../../../src/hotspot/share/utilities/events.hpp ++../../../src/hotspot/share/utilities/ostream.cpp ++../../../src/hotspot/share/utilities/elfFile.hpp ++../../../src/hotspot/share/utilities/internalVMTests.hpp ++../../../src/hotspot/share/utilities/fakeRttiSupport.hpp ++../../../src/hotspot/share/utilities/xmlstream.cpp ++../../../src/hotspot/share/utilities/elfSymbolTable.cpp ++../../../src/hotspot/share/utilities/preserveException.hpp ++../../../src/hotspot/share/utilities/accessFlags.hpp ++../../../src/hotspot/share/utilities/spinYield.hpp ++../../../src/hotspot/share/utilities/formatBuffer.hpp ++../../../src/hotspot/share/utilities/errorReporter.cpp ++../../../src/hotspot/share/utilities/breakpoint.hpp ++../../../src/hotspot/share/utilities/histogram.cpp ++../../../src/hotspot/share/utilities/ticks.hpp ++../../../src/hotspot/share/utilities/stringUtils.hpp ++../../../src/hotspot/share/utilities/growableArray.hpp ++../../../src/hotspot/share/utilities/debug.cpp ++../../../src/hotspot/share/utilities/globalDefinitions.cpp ++../../../src/hotspot/share/utilities/bytes.hpp ++../../../src/hotspot/share/utilities/stack.hpp ++../../../src/hotspot/share/utilities/hashtable.cpp ++../../../src/hotspot/share/utilities/nativeCallStack.cpp ++../../../src/hotspot/share/utilities/events.cpp ++../../../src/hotspot/share/utilities/decoder.cpp ++../../../src/hotspot/share/utilities/elfStringTable.hpp ++../../../src/hotspot/share/utilities/exceptions.hpp ++../../../src/hotspot/share/utilities/globalDefinitions_gcc.hpp ++../../../src/hotspot/share/utilities/dtrace.hpp ++../../../src/hotspot/share/utilities/numberSeq.cpp ++../../../src/hotspot/share/utilities/vmError.cpp ++../../../src/hotspot/share/utilities/globalCounter.cpp ++../../../src/hotspot/share/utilities/constantTag.cpp ++../../../src/hotspot/share/utilities/stack.inline.hpp ++../../../src/hotspot/share/utilities/hashtable.inline.hpp ++../../../src/hotspot/share/utilities/concurrentHashTable.inline.hpp ++../../../src/hotspot/share/utilities/intHisto.cpp ++../../../src/hotspot/share/utilities/copy.hpp ++../../../src/hotspot/share/utilities/utf8.cpp ++../../../src/hotspot/share/utilities/json.cpp ++../../../src/hotspot/share/utilities/concurrentHashTable.hpp ++../../../src/hotspot/share/utilities/elfFuncDescTable.cpp ++../../../src/hotspot/share/utilities/bitMap.hpp ++../../../src/hotspot/share/utilities/decoder_elf.hpp ++../../../src/hotspot/share/utilities/linkedlist.hpp ++../../../src/hotspot/share/utilities/chunkedList.hpp ++../../../src/hotspot/share/utilities/sizes.hpp ++../../../src/hotspot/share/utilities/compilerWarnings.hpp ++../../../src/hotspot/share/adlc/dict2.hpp ++../../../src/hotspot/share/adlc/filebuff.cpp ++../../../src/hotspot/share/adlc/formssel.hpp ++../../../src/hotspot/share/adlc/adlc.hpp ++../../../src/hotspot/share/adlc/forms.cpp ++../../../src/hotspot/share/adlc/output_c.cpp ++../../../src/hotspot/share/adlc/formsopt.cpp ++../../../src/hotspot/share/adlc/dfa.cpp ++../../../src/hotspot/share/adlc/archDesc.cpp ++../../../src/hotspot/share/adlc/arena.cpp ++../../../src/hotspot/share/adlc/adlparse.hpp ++../../../src/hotspot/share/adlc/formsopt.hpp ++../../../src/hotspot/share/adlc/archDesc.hpp ++../../../src/hotspot/share/adlc/output_h.cpp ++../../../src/hotspot/share/adlc/arena.hpp ++../../../src/hotspot/share/adlc/adlparse.cpp ++../../../src/hotspot/share/adlc/filebuff.hpp ++../../../src/hotspot/share/adlc/dict2.cpp ++../../../src/hotspot/share/adlc/formssel.cpp ++../../../src/hotspot/share/adlc/main.cpp ++../../../src/hotspot/share/adlc/forms.hpp ++../../../src/hotspot/share/gc/parallel/vmPSOperations.cpp ++../../../src/hotspot/share/gc/parallel/psGenerationCounters.hpp ++../../../src/hotspot/share/gc/parallel/spaceCounters.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionManager.cpp ++../../../src/hotspot/share/gc/parallel/parallelArguments.cpp ++../../../src/hotspot/share/gc/parallel/psScavenge.cpp ++../../../src/hotspot/share/gc/parallel/asPSOldGen.hpp ++../../../src/hotspot/share/gc/parallel/psTasks.cpp ++../../../src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp ++../../../src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionLAB.cpp ++../../../src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp ++../../../src/hotspot/share/gc/parallel/mutableNUMASpace.hpp ++../../../src/hotspot/share/gc/parallel/pcTasks.hpp ++../../../src/hotspot/share/gc/parallel/psMarkSweep.hpp ++../../../src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp ++../../../src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp ++../../../src/hotspot/share/gc/parallel/psOldGen.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp ++../../../src/hotspot/share/gc/parallel/generationSizer.cpp ++../../../src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp ++../../../src/hotspot/share/gc/parallel/asPSYoungGen.cpp ++../../../src/hotspot/share/gc/parallel/psVirtualspace.hpp ++../../../src/hotspot/share/gc/parallel/adjoiningVirtualSpaces.cpp ++../../../src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp ++../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp ++../../../src/hotspot/share/gc/parallel/psCompactionManager.hpp ++../../../src/hotspot/share/gc/parallel/gcTaskManager.cpp ++../../../src/hotspot/share/gc/parallel/gcTaskThread.cpp ++../../../src/hotspot/share/gc/parallel/immutableSpace.cpp ++../../../src/hotspot/share/gc/parallel/psParallelCompact.hpp ++../../../src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp ++../../../src/hotspot/share/gc/parallel/psYoungGen.cpp ++../../../src/hotspot/share/gc/parallel/psMemoryPool.cpp ++../../../src/hotspot/share/gc/parallel/mutableSpace.hpp ++../../../src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp ++../../../src/hotspot/share/gc/parallel/psCardTable.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp ++../../../src/hotspot/share/gc/parallel/adjoiningGenerations.cpp ++../../../src/hotspot/share/gc/parallel/objectStartArray.hpp ++../../../src/hotspot/share/gc/parallel/parMarkBitMap.cpp ++../../../src/hotspot/share/gc/parallel/psMarkSweepProxy.hpp ++../../../src/hotspot/share/gc/parallel/generationSizer.hpp ++../../../src/hotspot/share/gc/parallel/asPSYoungGen.hpp ++../../../src/hotspot/share/gc/parallel/psVirtualspace.cpp ++../../../src/hotspot/share/gc/parallel/adjoiningVirtualSpaces.hpp ++../../../src/hotspot/share/gc/parallel/gcTaskManager.hpp ++../../../src/hotspot/share/gc/parallel/gcTaskThread.hpp ++../../../src/hotspot/share/gc/parallel/psCompactionManager.cpp ++../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp ++../../../src/hotspot/share/gc/parallel/psParallelCompact.cpp ++../../../src/hotspot/share/gc/parallel/immutableSpace.hpp ++../../../src/hotspot/share/gc/parallel/psScavenge.inline.hpp ++../../../src/hotspot/share/gc/parallel/psMemoryPool.hpp ++../../../src/hotspot/share/gc/parallel/psYoungGen.hpp ++../../../src/hotspot/share/gc/parallel/mutableSpace.cpp ++../../../src/hotspot/share/gc/parallel/psCardTable.cpp ++../../../src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp ++../../../src/hotspot/share/gc/parallel/adjoiningGenerations.hpp ++../../../src/hotspot/share/gc/parallel/objectStartArray.cpp ++../../../src/hotspot/share/gc/parallel/parMarkBitMap.hpp ++../../../src/hotspot/share/gc/parallel/vmPSOperations.hpp ++../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp ++../../../src/hotspot/share/gc/parallel/parallelArguments.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionManager.hpp ++../../../src/hotspot/share/gc/parallel/spaceCounters.cpp ++../../../src/hotspot/share/gc/parallel/psGenerationCounters.cpp ++../../../src/hotspot/share/gc/parallel/psScavenge.hpp ++../../../src/hotspot/share/gc/parallel/asPSOldGen.cpp ++../../../src/hotspot/share/gc/parallel/psTasks.hpp ++../../../src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.cpp ++../../../src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.cpp ++../../../src/hotspot/share/gc/parallel/objectStartArray.inline.hpp ++../../../src/hotspot/share/gc/parallel/psPromotionLAB.hpp ++../../../src/hotspot/share/gc/parallel/mutableNUMASpace.cpp ++../../../src/hotspot/share/gc/parallel/pcTasks.cpp ++../../../src/hotspot/share/gc/parallel/psMarkSweep.cpp ++../../../src/hotspot/share/gc/parallel/parallel_globals.hpp ++../../../src/hotspot/share/gc/parallel/psOldGen.cpp ++../../../src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp ++../../../src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp ++../../../src/hotspot/share/gc/g1/heapRegionManager.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedupQueue.hpp ++../../../src/hotspot/share/gc/g1/g1RemSetSummary.hpp ++../../../src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp ++../../../src/hotspot/share/gc/g1/g1Predictions.hpp ++../../../src/hotspot/share/gc/g1/g1FullCollector.cpp ++../../../src/hotspot/share/gc/g1/g1InCSetState.hpp ++../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.inline.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp ++../../../src/hotspot/share/gc/g1/g1CollectionSet.hpp ++../../../src/hotspot/share/gc/g1/g1BarrierSet.cpp ++../../../src/hotspot/share/gc/g1/heapRegionTracer.hpp ++../../../src/hotspot/share/gc/g1/g1Arguments.cpp ++../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp ++../../../src/hotspot/share/gc/g1/heapRegion.inline.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp ++../../../src/hotspot/share/gc/g1/g1IHOPControl.cpp ++../../../src/hotspot/share/gc/g1/sparsePRT.hpp ++../../../src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp ++../../../src/hotspot/share/gc/g1/g1HotCardCache.hpp ++../../../src/hotspot/share/gc/g1/survRateGroup.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp ++../../../src/hotspot/share/gc/g1/g1CollectorState.hpp ++../../../src/hotspot/share/gc/g1/vm_operations_g1.cpp ++../../../src/hotspot/share/gc/g1/g1RootClosures.cpp ++../../../src/hotspot/share/gc/g1/dirtyCardQueue.cpp ++../../../src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp ++../../../src/hotspot/share/gc/g1/g1SharedClosures.hpp ++../../../src/hotspot/share/gc/g1/g1CardCounts.hpp ++../../../src/hotspot/share/gc/g1/g1EvacFailure.hpp ++../../../src/hotspot/share/gc/g1/heapRegionBounds.hpp ++../../../src/hotspot/share/gc/g1/satbMarkQueue.hpp ++../../../src/hotspot/share/gc/g1/g1HeapRegionEventSender.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMark.hpp ++../../../src/hotspot/share/gc/g1/g1Policy.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp ++../../../src/hotspot/share/gc/g1/g1HeapVerifier.cpp ++../../../src/hotspot/share/gc/g1/g1BarrierSetRuntime.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedupStat.hpp ++../../../src/hotspot/share/gc/g1/g1RootProcessor.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp ++../../../src/hotspot/share/gc/g1/g1BarrierSetAssembler.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp ++../../../src/hotspot/share/gc/g1/g1CollectedHeap.hpp ++../../../src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp ++../../../src/hotspot/share/gc/g1/heapRegionBounds.inline.hpp ++../../../src/hotspot/share/gc/g1/g1CodeBlobClosure.hpp ++../../../src/hotspot/share/gc/g1/heapRegionType.hpp ++../../../src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp ++../../../src/hotspot/share/gc/g1/g1MMUTracker.cpp ++../../../src/hotspot/share/gc/g1/g1AllocRegion.hpp ++../../../src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp ++../../../src/hotspot/share/gc/g1/g1MemoryPool.cpp ++../../../src/hotspot/share/gc/g1/g1EvacStats.hpp ++../../../src/hotspot/share/gc/g1/g1HeapTransition.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp ++../../../src/hotspot/share/gc/g1/collectionSetChooser.cpp ++../../../src/hotspot/share/gc/g1/g1ParScanThreadState.hpp ++../../../src/hotspot/share/gc/g1/g1Analytics.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCMarkTask.hpp ++../../../src/hotspot/share/gc/g1/g1CodeCacheRemSet.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp ++../../../src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp ++../../../src/hotspot/share/gc/g1/c1/g1BarrierSetC1.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCMarker.hpp ++../../../src/hotspot/share/gc/g1/g1CodeRootSetTable.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.hpp ++../../../src/hotspot/share/gc/g1/g1CardTable.cpp ++../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp ++../../../src/hotspot/share/gc/g1/g1FromCardCache.cpp ++../../../src/hotspot/share/gc/g1/g1Allocator.hpp ++../../../src/hotspot/share/gc/g1/g1RemSet.cpp ++../../../src/hotspot/share/gc/g1/g1ThreadLocalData.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCTask.hpp ++../../../src/hotspot/share/gc/g1/g1SurvivorRegions.cpp ++../../../src/hotspot/share/gc/g1/ptrQueue.hpp ++../../../src/hotspot/share/gc/g1/g1YoungGenSizer.cpp ++../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedup.cpp ++../../../src/hotspot/share/gc/g1/heapRegion.cpp ++../../../src/hotspot/share/gc/g1/g1BiasedArray.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCScope.hpp ++../../../src/hotspot/share/gc/g1/g1MonitoringSupport.hpp ++../../../src/hotspot/share/gc/g1/heapRegionRemSet.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp ++../../../src/hotspot/share/gc/g1/g1CollectorPolicy.cpp ++../../../src/hotspot/share/gc/g1/g1OopClosures.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp ++../../../src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp ++../../../src/hotspot/share/gc/g1/g1OopClosures.inline.hpp ++../../../src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.hpp ++../../../src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp ++../../../src/hotspot/share/gc/g1/heapRegionSet.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp ++../../../src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp ++../../../src/hotspot/share/gc/g1/g1CollectedHeap.cpp ++../../../src/hotspot/share/gc/g1/heapRegionType.cpp ++../../../src/hotspot/share/gc/g1/g1Allocator.inline.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp ++../../../src/hotspot/share/gc/g1/g1RootProcessor.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp ++../../../src/hotspot/share/gc/g1/g1AllocRegion.cpp ++../../../src/hotspot/share/gc/g1/g1MMUTracker.hpp ++../../../src/hotspot/share/gc/g1/g1MemoryPool.hpp ++../../../src/hotspot/share/gc/g1/g1EvacStats.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCAdjustTask.hpp ++../../../src/hotspot/share/gc/g1/g1HeapTransition.cpp ++../../../src/hotspot/share/gc/g1/collectionSetChooser.hpp ++../../../src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp ++../../../src/hotspot/share/gc/g1/g1Analytics.hpp ++../../../src/hotspot/share/gc/g1/g1ParScanThreadState.cpp ++../../../src/hotspot/share/gc/g1/g1YCTypes.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCMarkTask.cpp ++../../../src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp ++../../../src/hotspot/share/gc/g1/g1FullGCMarker.cpp ++../../../src/hotspot/share/gc/g1/heapRegionSet.inline.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp ++../../../src/hotspot/share/gc/g1/g1FromCardCache.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.inline.hpp ++../../../src/hotspot/share/gc/g1/g1CardTable.hpp ++../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp ++../../../src/hotspot/share/gc/g1/g1RemSet.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCTask.cpp ++../../../src/hotspot/share/gc/g1/g1CardTable.inline.hpp ++../../../src/hotspot/share/gc/g1/g1SurvivorRegions.hpp ++../../../src/hotspot/share/gc/g1/vmStructs_g1.hpp ++../../../src/hotspot/share/gc/g1/g1Allocator.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedup.hpp ++../../../src/hotspot/share/gc/g1/g1YoungGenSizer.hpp ++../../../src/hotspot/share/gc/g1/ptrQueue.cpp ++../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp ++../../../src/hotspot/share/gc/g1/heapRegionRemSet.hpp ++../../../src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCScope.cpp ++../../../src/hotspot/share/gc/g1/heapRegion.hpp ++../../../src/hotspot/share/gc/g1/g1BiasedArray.cpp ++../../../src/hotspot/share/gc/g1/g1MonitoringSupport.cpp ++../../../src/hotspot/share/gc/g1/g1OopClosures.hpp ++../../../src/hotspot/share/gc/g1/g1CollectorPolicy.hpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp ++../../../src/hotspot/share/gc/g1/g1_globals.hpp ++../../../src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp ++../../../src/hotspot/share/gc/g1/heapRegionSet.hpp ++../../../src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp ++../../../src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp ++../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy_ext.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedupQueue.cpp ++../../../src/hotspot/share/gc/g1/g1RemSetSummary.cpp ++../../../src/hotspot/share/gc/g1/heapRegionManager.hpp ++../../../src/hotspot/share/gc/g1/g1EdenRegions.hpp ++../../../src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp ++../../../src/hotspot/share/gc/g1/g1FullCollector.hpp ++../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp ++../../../src/hotspot/share/gc/g1/g1BarrierSet.hpp ++../../../src/hotspot/share/gc/g1/g1CollectionSet.cpp ++../../../src/hotspot/share/gc/g1/evacuationInfo.hpp ++../../../src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp ++../../../src/hotspot/share/gc/g1/c2/g1BarrierSetC2.hpp ++../../../src/hotspot/share/gc/g1/heapRegionTracer.cpp ++../../../src/hotspot/share/gc/g1/g1Arguments.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp ++../../../src/hotspot/share/gc/g1/sparsePRT.cpp ++../../../src/hotspot/share/gc/g1/g1IHOPControl.hpp ++../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.hpp ++../../../src/hotspot/share/gc/g1/g1HotCardCache.cpp ++../../../src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.hpp ++../../../src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp ++../../../src/hotspot/share/gc/g1/survRateGroup.hpp ++../../../src/hotspot/share/gc/g1/g1EvacStats.inline.hpp ++../../../src/hotspot/share/gc/g1/dirtyCardQueue.hpp ++../../../src/hotspot/share/gc/g1/g1RootClosures.hpp ++../../../src/hotspot/share/gc/g1/g1HRPrinter.hpp ++../../../src/hotspot/share/gc/g1/vm_operations_g1.hpp ++../../../src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp ++../../../src/hotspot/share/gc/g1/heapRegionManager.inline.hpp ++../../../src/hotspot/share/gc/g1/satbMarkQueue.cpp ++../../../src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp ++../../../src/hotspot/share/gc/g1/g1CardCounts.cpp ++../../../src/hotspot/share/gc/g1/g1EvacFailure.cpp ++../../../src/hotspot/share/gc/g1/g1InitialMarkToMixedTimeTracker.hpp ++../../../src/hotspot/share/gc/g1/g1HeapVerifier.hpp ++../../../src/hotspot/share/gc/g1/g1Policy.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMark.cpp ++../../../src/hotspot/share/gc/g1/g1StringDedupStat.cpp ++../../../src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp ++../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonMemoryPool.cpp ++../../../src/hotspot/share/gc/epsilon/epsilonArguments.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonHeap.cpp ++../../../src/hotspot/share/gc/epsilon/vmStructs_epsilon.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp ++../../../src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp ++../../../src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp ++../../../src/hotspot/share/gc/epsilon/epsilon_globals.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonMemoryPool.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonArguments.cpp ++../../../src/hotspot/share/gc/epsilon/epsilonHeap.hpp ++../../../src/hotspot/share/gc/epsilon/epsilonThreadLocalData.hpp ++../../../src/hotspot/share/gc/z/zMetronome.cpp ++../../../src/hotspot/share/gc/z/zHeap.cpp ++../../../src/hotspot/share/gc/z/zHash.inline.hpp ++../../../src/hotspot/share/gc/z/zValue.hpp ++../../../src/hotspot/share/gc/z/zLock.inline.hpp ++../../../src/hotspot/share/gc/z/zRelocationSetSelector.cpp ++../../../src/hotspot/share/gc/z/zCollectorPolicy.hpp ++../../../src/hotspot/share/gc/z/zAddress.hpp ++../../../src/hotspot/share/gc/z/zArguments.cpp ++../../../src/hotspot/share/gc/z/zTask.hpp ++../../../src/hotspot/share/gc/z/zVirtualMemory.cpp ++../../../src/hotspot/share/gc/z/zResurrection.cpp ++../../../src/hotspot/share/gc/z/zDirector.hpp ++../../../src/hotspot/share/gc/z/zList.hpp ++../../../src/hotspot/share/gc/z/zErrno.hpp ++../../../src/hotspot/share/gc/z/zBarrier.inline.hpp ++../../../src/hotspot/share/gc/z/zFuture.hpp ++../../../src/hotspot/share/gc/z/zReferenceProcessor.hpp ++../../../src/hotspot/share/gc/z/zLargePages.cpp ++../../../src/hotspot/share/gc/z/zFuture.inline.hpp ++../../../src/hotspot/share/gc/z/zForwardingTable.cpp ++../../../src/hotspot/share/gc/z/zMarkStack.cpp ++../../../src/hotspot/share/gc/z/zForwardingTable.inline.hpp ++../../../src/hotspot/share/gc/z/zWorkers.hpp ++../../../src/hotspot/share/gc/z/zLiveMap.cpp ++../../../src/hotspot/share/gc/z/zMemory.cpp ++../../../src/hotspot/share/gc/z/zOopClosures.inline.hpp ++../../../src/hotspot/share/gc/z/zNUMA.hpp ++../../../src/hotspot/share/gc/z/zRootsIterator.hpp ++../../../src/hotspot/share/gc/z/zGlobals.cpp ++../../../src/hotspot/share/gc/z/zVirtualMemory.inline.hpp ++../../../src/hotspot/share/gc/z/zRelocationSet.hpp ++../../../src/hotspot/share/gc/z/zArray.hpp ++../../../src/hotspot/share/gc/z/zResurrection.inline.hpp ++../../../src/hotspot/share/gc/z/zMemory.inline.hpp ++../../../src/hotspot/share/gc/z/zHeapIterator.cpp ++../../../src/hotspot/share/gc/z/zInitialize.cpp ++../../../src/hotspot/share/gc/z/zMarkCache.hpp ++../../../src/hotspot/share/gc/z/zPageCache.hpp ++../../../src/hotspot/share/gc/z/zTracer.hpp ++../../../src/hotspot/share/gc/z/zThread.cpp ++../../../src/hotspot/share/gc/z/zRelocate.hpp ++../../../src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp ++../../../src/hotspot/share/gc/z/zStat.cpp ++../../../src/hotspot/share/gc/z/z_globals.hpp ++../../../src/hotspot/share/gc/z/zBarrierSet.hpp ++../../../src/hotspot/share/gc/z/zLock.hpp ++../../../src/hotspot/share/gc/z/zBarrier.hpp ++../../../src/hotspot/share/gc/z/zPhysicalMemory.hpp ++../../../src/hotspot/share/gc/z/zDriver.hpp ++../../../src/hotspot/share/gc/z/zWeakRootsProcessor.cpp ++../../../src/hotspot/share/gc/z/zMessagePort.hpp ++../../../src/hotspot/share/gc/z/zPageTable.cpp ++../../../src/hotspot/share/gc/z/zCollectedHeap.hpp ++../../../src/hotspot/share/gc/z/zRuntimeWorkers.hpp ++../../../src/hotspot/share/gc/z/c1/zBarrierSetC1.hpp ++../../../src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp ++../../../src/hotspot/share/gc/z/zAddress.inline.hpp ++../../../src/hotspot/share/gc/z/zMark.cpp ++../../../src/hotspot/share/gc/z/vmStructs_z.cpp ++../../../src/hotspot/share/gc/z/zPreMappedMemory.inline.hpp ++../../../src/hotspot/share/gc/z/zOopClosures.cpp ++../../../src/hotspot/share/gc/z/zAllocationFlags.hpp ++../../../src/hotspot/share/gc/z/zPageTable.inline.hpp ++../../../src/hotspot/share/gc/z/zServiceability.cpp ++../../../src/hotspot/share/gc/z/zLargePages.inline.hpp ++../../../src/hotspot/share/gc/z/zPageAllocator.cpp ++../../../src/hotspot/share/gc/z/zBarrierSetAssembler.hpp ++../../../src/hotspot/share/gc/z/zPreMappedMemory.cpp ++../../../src/hotspot/share/gc/z/zPageCache.inline.hpp ++../../../src/hotspot/share/gc/z/zBarrierSetRuntime.cpp ++../../../src/hotspot/share/gc/z/zPage.cpp ++../../../src/hotspot/share/gc/z/zUtils.cpp ++../../../src/hotspot/share/gc/z/zObjectAllocator.hpp ++../../../src/hotspot/share/gc/z/zHash.hpp ++../../../src/hotspot/share/gc/z/zNMethodTable.cpp ++../../../src/hotspot/share/gc/z/zPageTableEntry.hpp ++../../../src/hotspot/share/gc/z/zCPU.hpp ++../../../src/hotspot/share/gc/z/zBitMap.inline.hpp ++../../../src/hotspot/share/gc/z/zStat.hpp ++../../../src/hotspot/share/gc/z/zBarrierSet.cpp ++../../../src/hotspot/share/gc/z/zBarrier.cpp ++../../../src/hotspot/share/gc/z/zHeap.inline.hpp ++../../../src/hotspot/share/gc/z/zDriver.cpp ++../../../src/hotspot/share/gc/z/zMessagePort.inline.hpp ++../../../src/hotspot/share/gc/z/zPhysicalMemory.cpp ++../../../src/hotspot/share/gc/z/zPageTable.hpp ++../../../src/hotspot/share/gc/z/zRelocationSet.inline.hpp ++../../../src/hotspot/share/gc/z/zPage.inline.hpp ++../../../src/hotspot/share/gc/z/zUtils.inline.hpp ++../../../src/hotspot/share/gc/z/zMarkTerminate.hpp ++../../../src/hotspot/share/gc/z/zWeakRootsProcessor.hpp ++../../../src/hotspot/share/gc/z/zCollectedHeap.cpp ++../../../src/hotspot/share/gc/z/zRuntimeWorkers.cpp ++../../../src/hotspot/share/gc/z/zArray.inline.hpp ++../../../src/hotspot/share/gc/z/zBitField.hpp ++../../../src/hotspot/share/gc/z/zAddressRangeMap.hpp ++../../../src/hotspot/share/gc/z/zMarkStackEntry.hpp ++../../../src/hotspot/share/gc/z/vmStructs_z.hpp ++../../../src/hotspot/share/gc/z/zMarkStack.inline.hpp ++../../../src/hotspot/share/gc/z/zMark.hpp ++../../../src/hotspot/share/gc/z/zOopClosures.hpp ++../../../src/hotspot/share/gc/z/zTracer.inline.hpp ++../../../src/hotspot/share/gc/z/zBarrierSetAssembler.cpp ++../../../src/hotspot/share/gc/z/zPageAllocator.hpp ++../../../src/hotspot/share/gc/z/zServiceability.hpp ++../../../src/hotspot/share/gc/z/zPreMappedMemory.hpp ++../../../src/hotspot/share/gc/z/zMark.inline.hpp ++../../../src/hotspot/share/gc/z/zBarrierSetRuntime.hpp ++../../../src/hotspot/share/gc/z/zAddressRangeMap.inline.hpp ++../../../src/hotspot/share/gc/z/zOop.inline.hpp ++../../../src/hotspot/share/gc/z/zUtils.hpp ++../../../src/hotspot/share/gc/z/zPage.hpp ++../../../src/hotspot/share/gc/z/zObjectAllocator.cpp ++../../../src/hotspot/share/gc/z/zCPU.cpp ++../../../src/hotspot/share/gc/z/zNMethodTable.hpp ++../../../src/hotspot/share/gc/z/zMetronome.hpp ++../../../src/hotspot/share/gc/z/zHeap.hpp ++../../../src/hotspot/share/gc/z/zLiveMap.inline.hpp ++../../../src/hotspot/share/gc/z/zCollectorPolicy.cpp ++../../../src/hotspot/share/gc/z/zRelocationSetSelector.hpp ++../../../src/hotspot/share/gc/z/zWorkers.inline.hpp ++../../../src/hotspot/share/gc/z/zArguments.hpp ++../../../src/hotspot/share/gc/z/zForwardingTableEntry.hpp ++../../../src/hotspot/share/gc/z/zTask.cpp ++../../../src/hotspot/share/gc/z/zAddress.cpp ++../../../src/hotspot/share/gc/z/zErrno.cpp ++../../../src/hotspot/share/gc/z/zBarrierSet.inline.hpp ++../../../src/hotspot/share/gc/z/zResurrection.hpp ++../../../src/hotspot/share/gc/z/zVirtualMemory.hpp ++../../../src/hotspot/share/gc/z/zDirector.cpp ++../../../src/hotspot/share/gc/z/zNMethodTableEntry.hpp ++../../../src/hotspot/share/gc/z/zList.inline.hpp ++../../../src/hotspot/share/gc/z/zReferenceProcessor.cpp ++../../../src/hotspot/share/gc/z/zLargePages.hpp ++../../../src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp ++../../../src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp ++../../../src/hotspot/share/gc/z/zMarkStack.hpp ++../../../src/hotspot/share/gc/z/zThreadLocalData.hpp ++../../../src/hotspot/share/gc/z/zBitMap.hpp ++../../../src/hotspot/share/gc/z/zForwardingTable.hpp ++../../../src/hotspot/share/gc/z/zMarkCache.inline.hpp ++../../../src/hotspot/share/gc/z/zWorkers.cpp ++../../../src/hotspot/share/gc/z/zRootsIterator.cpp ++../../../src/hotspot/share/gc/z/zNUMA.cpp ++../../../src/hotspot/share/gc/z/zGlobals.hpp ++../../../src/hotspot/share/gc/z/zMemory.hpp ++../../../src/hotspot/share/gc/z/zLiveMap.hpp ++../../../src/hotspot/share/gc/z/zRelocationSet.cpp ++../../../src/hotspot/share/gc/z/zMarkTerminate.inline.hpp ++../../../src/hotspot/share/gc/z/zInitialize.hpp ++../../../src/hotspot/share/gc/z/zHeapIterator.hpp ++../../../src/hotspot/share/gc/z/zThread.hpp ++../../../src/hotspot/share/gc/z/zTracer.cpp ++../../../src/hotspot/share/gc/z/zMarkCache.cpp ++../../../src/hotspot/share/gc/z/zPageCache.cpp ++../../../src/hotspot/share/gc/z/zRelocate.cpp ++../../../src/hotspot/share/gc/z/zOop.hpp ++../../../src/hotspot/share/gc/shared/gcCause.cpp ++../../../src/hotspot/share/gc/shared/oopStorageParState.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessorStats.hpp ++../../../src/hotspot/share/gc/shared/plab.hpp ++../../../src/hotspot/share/gc/shared/gcConfiguration.cpp ++../../../src/hotspot/share/gc/shared/spaceDecorator.cpp ++../../../src/hotspot/share/gc/shared/gcPolicyCounters.hpp ++../../../src/hotspot/share/gc/shared/allocTracer.cpp ++../../../src/hotspot/share/gc/shared/gcTraceTime.inline.hpp ++../../../src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp ++../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp ++../../../src/hotspot/share/gc/shared/collectedHeap.cpp ++../../../src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp ++../../../src/hotspot/share/gc/shared/collectedHeap.inline.hpp ++../../../src/hotspot/share/gc/shared/ageTable.hpp ++../../../src/hotspot/share/gc/shared/blockOffsetTable.cpp ++../../../src/hotspot/share/gc/shared/hSpaceCounters.hpp ++../../../src/hotspot/share/gc/shared/space.inline.hpp ++../../../src/hotspot/share/gc/shared/collectorCounters.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessor.cpp ++../../../src/hotspot/share/gc/shared/accessBarrierSupport.cpp ++../../../src/hotspot/share/gc/shared/oopStorage.inline.hpp ++../../../src/hotspot/share/gc/shared/taskqueue.hpp ++../../../src/hotspot/share/gc/shared/gcTraceTime.hpp ++../../../src/hotspot/share/gc/shared/gcThreadLocalData.hpp ++../../../src/hotspot/share/gc/shared/gcTraceSend.cpp ++../../../src/hotspot/share/gc/shared/weakProcessor.cpp ++../../../src/hotspot/share/gc/shared/space.hpp ++../../../src/hotspot/share/gc/shared/cardTableRS.hpp ++../../../src/hotspot/share/gc/shared/objectCountEventSender.hpp ++../../../src/hotspot/share/gc/shared/generationSpec.cpp ++../../../src/hotspot/share/gc/shared/cardGeneration.hpp ++../../../src/hotspot/share/gc/shared/vmGCOperations.cpp ++../../../src/hotspot/share/gc/shared/softRefGenPolicy.cpp ++../../../src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp ++../../../src/hotspot/share/gc/shared/gcArguments.hpp ++../../../src/hotspot/share/gc/shared/workerDataArray.hpp ++../../../src/hotspot/share/gc/shared/suspendibleThreadSet.hpp ++../../../src/hotspot/share/gc/shared/collectorPolicy.cpp ++../../../src/hotspot/share/gc/shared/barrierSet.hpp ++../../../src/hotspot/share/gc/shared/genMemoryPools.hpp ++../../../src/hotspot/share/gc/shared/ageTableTracer.hpp ++../../../src/hotspot/share/gc/shared/workerDataArray.inline.hpp ++../../../src/hotspot/share/gc/shared/concurrentGCThread.hpp ++../../../src/hotspot/share/gc/shared/plab.inline.hpp ++../../../src/hotspot/share/gc/shared/cardTable.cpp ++../../../src/hotspot/share/gc/shared/softRefPolicy.cpp ++../../../src/hotspot/share/gc/shared/genCollectedHeap.cpp ++../../../src/hotspot/share/gc/shared/gcLocker.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessor.inline.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp ++../../../src/hotspot/share/gc/shared/preservedMarks.inline.hpp ++../../../src/hotspot/share/gc/shared/c1/barrierSetC1.hpp ++../../../src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.hpp ++../../../src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp ++../../../src/hotspot/share/gc/shared/c1/barrierSetC1.cpp ++../../../src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.hpp ++../../../src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp ++../../../src/hotspot/share/gc/shared/cardTableBarrierSet.hpp ++../../../src/hotspot/share/gc/shared/oopStorage.hpp ++../../../src/hotspot/share/gc/shared/gcConfig.cpp ++../../../src/hotspot/share/gc/shared/barrierSetAssembler.hpp ++../../../src/hotspot/share/gc/shared/modRefBarrierSet.hpp ++../../../src/hotspot/share/gc/shared/memAllocator.cpp ++../../../src/hotspot/share/gc/shared/referencePolicy.hpp ++../../../src/hotspot/share/gc/shared/gcTrace.hpp ++../../../src/hotspot/share/gc/shared/generationCounters.hpp ++../../../src/hotspot/share/gc/shared/strongRootsScope.hpp ++../../../src/hotspot/share/gc/shared/gcUtil.cpp ++../../../src/hotspot/share/gc/shared/generation.hpp ++../../../src/hotspot/share/gc/shared/concurrentGCPhaseManager.hpp ++../../../src/hotspot/share/gc/shared/gcId.cpp ++../../../src/hotspot/share/gc/shared/gcStats.hpp ++../../../src/hotspot/share/gc/shared/workgroup.cpp ++../../../src/hotspot/share/gc/shared/gcTimer.hpp ++../../../src/hotspot/share/gc/shared/preservedMarks.cpp ++../../../src/hotspot/share/gc/shared/referenceDiscoverer.hpp ++../../../src/hotspot/share/gc/shared/cardGeneration.cpp ++../../../src/hotspot/share/gc/shared/generationSpec.hpp ++../../../src/hotspot/share/gc/shared/vmGCOperations.hpp ++../../../src/hotspot/share/gc/shared/softRefGenPolicy.hpp ++../../../src/hotspot/share/gc/shared/collectorPolicy.hpp ++../../../src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp ++../../../src/hotspot/share/gc/shared/barrierSet.cpp ++../../../src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp ++../../../src/hotspot/share/gc/shared/suspendibleThreadSet.cpp ++../../../src/hotspot/share/gc/shared/workerDataArray.cpp ++../../../src/hotspot/share/gc/shared/gcArguments.cpp ++../../../src/hotspot/share/gc/shared/ageTableTracer.cpp ++../../../src/hotspot/share/gc/shared/isGCActiveMark.hpp ++../../../src/hotspot/share/gc/shared/genMemoryPools.cpp ++../../../src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupStat.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.cpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.inline.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.inline.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.inline.hpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp ++../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.hpp ++../../../src/hotspot/share/gc/shared/softRefPolicy.hpp ++../../../src/hotspot/share/gc/shared/oopStorageParState.inline.hpp ++../../../src/hotspot/share/gc/shared/genCollectedHeap.hpp ++../../../src/hotspot/share/gc/shared/concurrentGCThread.cpp ++../../../src/hotspot/share/gc/shared/cardTable.hpp ++../../../src/hotspot/share/gc/shared/vmStructs_gc.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp ++../../../src/hotspot/share/gc/shared/gcLocker.cpp ++../../../src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp ++../../../src/hotspot/share/gc/shared/barrierSetConfig.hpp ++../../../src/hotspot/share/gc/shared/cardTableBarrierSet.cpp ++../../../src/hotspot/share/gc/shared/oopStorage.cpp ++../../../src/hotspot/share/gc/shared/gcConfig.hpp ++../../../src/hotspot/share/gc/shared/genOopClosures.inline.hpp ++../../../src/hotspot/share/gc/shared/gcName.hpp ++../../../src/hotspot/share/gc/shared/referencePolicy.cpp ++../../../src/hotspot/share/gc/shared/gcArguments.inline.hpp ++../../../src/hotspot/share/gc/shared/memAllocator.hpp ++../../../src/hotspot/share/gc/shared/strongRootsScope.cpp ++../../../src/hotspot/share/gc/shared/generationCounters.cpp ++../../../src/hotspot/share/gc/shared/gcUtil.hpp ++../../../src/hotspot/share/gc/shared/gcTrace.cpp ++../../../src/hotspot/share/gc/shared/memset_with_concurrent_readers.hpp ++../../../src/hotspot/share/gc/shared/gcId.hpp ++../../../src/hotspot/share/gc/shared/gcStats.cpp ++../../../src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp ++../../../src/hotspot/share/gc/shared/workgroup.hpp ++../../../src/hotspot/share/gc/shared/generation.cpp ++../../../src/hotspot/share/gc/shared/cardGeneration.inline.hpp ++../../../src/hotspot/share/gc/shared/preservedMarks.hpp ++../../../src/hotspot/share/gc/shared/gcUtil.inline.hpp ++../../../src/hotspot/share/gc/shared/gcTimer.cpp ++../../../src/hotspot/share/gc/shared/gcCause.hpp ++../../../src/hotspot/share/gc/shared/plab.cpp ++../../../src/hotspot/share/gc/shared/genOopClosures.hpp ++../../../src/hotspot/share/gc/shared/ageTable.inline.hpp ++../../../src/hotspot/share/gc/shared/spaceDecorator.hpp ++../../../src/hotspot/share/gc/shared/barrierSet.inline.hpp ++../../../src/hotspot/share/gc/shared/gcConfiguration.hpp ++../../../src/hotspot/share/gc/shared/copyFailedInfo.hpp ++../../../src/hotspot/share/gc/shared/allocTracer.hpp ++../../../src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp ++../../../src/hotspot/share/gc/shared/workerManager.hpp ++../../../src/hotspot/share/gc/shared/gcPolicyCounters.cpp ++../../../src/hotspot/share/gc/shared/gcLocker.inline.hpp ++../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp ++../../../src/hotspot/share/gc/shared/taskqueue.inline.hpp ++../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp ++../../../src/hotspot/share/gc/shared/c2/barrierSetC2.hpp ++../../../src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.hpp ++../../../src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp ++../../../src/hotspot/share/gc/shared/c2/barrierSetC2.cpp ++../../../src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.hpp ++../../../src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp ++../../../src/hotspot/share/gc/shared/collectedHeap.hpp ++../../../src/hotspot/share/gc/shared/ageTable.cpp ++../../../src/hotspot/share/gc/shared/gc_globals.hpp ++../../../src/hotspot/share/gc/shared/blockOffsetTable.hpp ++../../../src/hotspot/share/gc/shared/gcHeapSummary.hpp ++../../../src/hotspot/share/gc/shared/hSpaceCounters.cpp ++../../../src/hotspot/share/gc/shared/accessBarrierSupport.hpp ++../../../src/hotspot/share/gc/shared/referenceProcessor.hpp ++../../../src/hotspot/share/gc/shared/collectorCounters.cpp ++../../../src/hotspot/share/gc/shared/gcTraceTime.cpp ++../../../src/hotspot/share/gc/shared/taskqueue.cpp ++../../../src/hotspot/share/gc/shared/cardTableBarrierSetAssembler.hpp ++../../../src/hotspot/share/gc/shared/cardTableRS.cpp ++../../../src/hotspot/share/gc/shared/weakProcessor.hpp ++../../../src/hotspot/share/gc/shared/space.cpp ++../../../src/hotspot/share/gc/shared/accessBarrierSupport.inline.hpp ++../../../src/hotspot/share/gc/shared/gcWhen.hpp ++../../../src/hotspot/share/gc/shared/objectCountEventSender.cpp ++../../../src/hotspot/share/gc/shared/modRefBarrierSetAssembler.hpp ++../../../src/hotspot/share/gc/cms/concurrentMarkSweepThread.hpp ++../../../src/hotspot/share/gc/cms/gSpaceCounters.hpp ++../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp ++../../../src/hotspot/share/gc/cms/cmsGCStats.cpp ++../../../src/hotspot/share/gc/cms/cmsCardTable.cpp ++../../../src/hotspot/share/gc/cms/cmsOopClosures.hpp ++../../../src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.hpp ++../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp ++../../../src/hotspot/share/gc/cms/cmsHeap.inline.hpp ++../../../src/hotspot/share/gc/cms/vmCMSOperations.hpp ++../../../src/hotspot/share/gc/cms/cms_globals.hpp ++../../../src/hotspot/share/gc/cms/yieldingWorkgroup.hpp ++../../../src/hotspot/share/gc/cms/cmsHeap.hpp ++../../../src/hotspot/share/gc/cms/cmsArguments.cpp ++../../../src/hotspot/share/gc/cms/adaptiveFreeList.cpp ++../../../src/hotspot/share/gc/cms/promotionInfo.cpp ++../../../src/hotspot/share/gc/cms/parNewGeneration.cpp ++../../../src/hotspot/share/gc/cms/freeChunk.hpp ++../../../src/hotspot/share/gc/cms/cmsLockVerifier.cpp ++../../../src/hotspot/share/gc/cms/allocationStats.cpp ++../../../src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp ++../../../src/hotspot/share/gc/cms/parOopClosures.hpp ++../../../src/hotspot/share/gc/cms/vmCMSOperations.cpp ++../../../src/hotspot/share/gc/cms/yieldingWorkgroup.cpp ++../../../src/hotspot/share/gc/cms/cmsOopClosures.inline.hpp ++../../../src/hotspot/share/gc/cms/promotionInfo.inline.hpp ++../../../src/hotspot/share/gc/cms/cmsHeap.cpp ++../../../src/hotspot/share/gc/cms/cmsArguments.hpp ++../../../src/hotspot/share/gc/cms/adaptiveFreeList.hpp ++../../../src/hotspot/share/gc/cms/promotionInfo.hpp ++../../../src/hotspot/share/gc/cms/parOopClosures.inline.hpp ++../../../src/hotspot/share/gc/cms/parNewGeneration.hpp ++../../../src/hotspot/share/gc/cms/freeChunk.cpp ++../../../src/hotspot/share/gc/cms/cmsLockVerifier.hpp ++../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp ++../../../src/hotspot/share/gc/cms/vmStructs_cms.hpp ++../../../src/hotspot/share/gc/cms/cmsCollectorPolicy.hpp ++../../../src/hotspot/share/gc/cms/allocationStats.hpp ++../../../src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp ++../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp ++../../../src/hotspot/share/gc/cms/gSpaceCounters.cpp ++../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp ++../../../src/hotspot/share/gc/cms/cmsGCStats.hpp ++../../../src/hotspot/share/gc/cms/cmsCardTable.hpp ++../../../src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp ++../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp ++../../../src/hotspot/share/gc/cms/parNewGeneration.inline.hpp ++../../../src/hotspot/share/gc/serial/markSweep.cpp ++../../../src/hotspot/share/gc/serial/cSpaceCounters.hpp ++../../../src/hotspot/share/gc/serial/serialHeap.hpp ++../../../src/hotspot/share/gc/serial/tenuredGeneration.hpp ++../../../src/hotspot/share/gc/serial/genMarkSweep.cpp ++../../../src/hotspot/share/gc/serial/defNewGeneration.inline.hpp ++../../../src/hotspot/share/gc/serial/serialHeap.inline.hpp ++../../../src/hotspot/share/gc/serial/defNewGeneration.cpp ++../../../src/hotspot/share/gc/serial/serialArguments.cpp ++../../../src/hotspot/share/gc/serial/serial_globals.hpp ++../../../src/hotspot/share/gc/serial/tenuredGeneration.cpp ++../../../src/hotspot/share/gc/serial/genMarkSweep.hpp ++../../../src/hotspot/share/gc/serial/markSweep.inline.hpp ++../../../src/hotspot/share/gc/serial/defNewGeneration.hpp ++../../../src/hotspot/share/gc/serial/serialArguments.hpp ++../../../src/hotspot/share/gc/serial/markSweep.hpp ++../../../src/hotspot/share/gc/serial/vmStructs_serial.hpp ++../../../src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp ++../../../src/hotspot/share/gc/serial/cSpaceCounters.cpp ++../../../src/hotspot/share/gc/serial/serialHeap.cpp ++../../../src/hotspot/share/oops/objArrayKlass.inline.hpp ++../../../src/hotspot/share/oops/cpCache.inline.hpp ++../../../src/hotspot/share/oops/annotations.hpp ++../../../src/hotspot/share/oops/accessBackend.inline.hpp ++../../../src/hotspot/share/oops/typeArrayKlass.inline.hpp ++../../../src/hotspot/share/oops/compressedOops.inline.hpp ++../../../src/hotspot/share/oops/methodCounters.hpp ++../../../src/hotspot/share/oops/generateOopMap.cpp ++../../../src/hotspot/share/oops/access.hpp ++../../../src/hotspot/share/oops/symbol.cpp ++../../../src/hotspot/share/oops/arrayOop.inline.hpp ++../../../src/hotspot/share/oops/instanceOop.cpp ++../../../src/hotspot/share/oops/methodData.inline.hpp ++../../../src/hotspot/share/oops/instanceRefKlass.cpp ++../../../src/hotspot/share/oops/method.inline.hpp ++../../../src/hotspot/share/oops/arrayKlass.cpp ++../../../src/hotspot/share/oops/weakHandle.hpp ++../../../src/hotspot/share/oops/klass.hpp ++../../../src/hotspot/share/oops/constantPool.hpp ++../../../src/hotspot/share/oops/oopHandle.hpp ++../../../src/hotspot/share/oops/accessDecorators.hpp ++../../../src/hotspot/share/oops/instanceKlass.cpp ++../../../src/hotspot/share/oops/typeArrayOop.inline.hpp ++../../../src/hotspot/share/oops/instanceMirrorKlass.hpp ++../../../src/hotspot/share/oops/objArrayKlass.hpp ++../../../src/hotspot/share/oops/array.hpp ++../../../src/hotspot/share/oops/typeArrayKlass.hpp ++../../../src/hotspot/share/oops/oopHandle.inline.hpp ++../../../src/hotspot/share/oops/accessBackend.hpp ++../../../src/hotspot/share/oops/oop.cpp ++../../../src/hotspot/share/oops/cpCache.hpp ++../../../src/hotspot/share/oops/compiledICHolder.hpp ++../../../src/hotspot/share/oops/fieldInfo.hpp ++../../../src/hotspot/share/oops/reflectionAccessorImplKlassHelper.hpp ++../../../src/hotspot/share/oops/verifyOopClosure.hpp ++../../../src/hotspot/share/oops/markOop.hpp ++../../../src/hotspot/share/oops/methodData.hpp ++../../../src/hotspot/share/oops/markOop.inline.hpp ++../../../src/hotspot/share/oops/objArrayOop.hpp ++../../../src/hotspot/share/oops/constMethod.cpp ++../../../src/hotspot/share/oops/klassVtable.hpp ++../../../src/hotspot/share/oops/instanceMirrorKlass.inline.hpp ++../../../src/hotspot/share/oops/oopsHierarchy.hpp ++../../../src/hotspot/share/oops/metadata.hpp ++../../../src/hotspot/share/oops/fieldStreams.hpp ++../../../src/hotspot/share/oops/method.hpp ++../../../src/hotspot/share/oops/objArrayKlass.cpp ++../../../src/hotspot/share/oops/instanceMirrorKlass.cpp ++../../../src/hotspot/share/oops/typeArrayKlass.cpp ++../../../src/hotspot/share/oops/accessBackend.cpp ++../../../src/hotspot/share/oops/oop.hpp ++../../../src/hotspot/share/oops/weakHandle.inline.hpp ++../../../src/hotspot/share/oops/cpCache.cpp ++../../../src/hotspot/share/oops/objArrayOop.inline.hpp ++../../../src/hotspot/share/oops/compiledICHolder.cpp ++../../../src/hotspot/share/oops/reflectionAccessorImplKlassHelper.cpp ++../../../src/hotspot/share/oops/klass.inline.hpp ++../../../src/hotspot/share/oops/markOop.cpp ++../../../src/hotspot/share/oops/instanceKlass.inline.hpp ++../../../src/hotspot/share/oops/methodData.cpp ++../../../src/hotspot/share/oops/objArrayOop.cpp ++../../../src/hotspot/share/oops/constMethod.hpp ++../../../src/hotspot/share/oops/oop.inline.hpp ++../../../src/hotspot/share/oops/klassVtable.cpp ++../../../src/hotspot/share/oops/method.cpp ++../../../src/hotspot/share/oops/oopsHierarchy.cpp ++../../../src/hotspot/share/oops/metadata.cpp ++../../../src/hotspot/share/oops/arrayKlass.inline.hpp ++../../../src/hotspot/share/oops/typeArrayOop.hpp ++../../../src/hotspot/share/oops/instanceRefKlass.inline.hpp ++../../../src/hotspot/share/oops/arrayOop.hpp ++../../../src/hotspot/share/oops/annotations.cpp ++../../../src/hotspot/share/oops/methodCounters.cpp ++../../../src/hotspot/share/oops/generateOopMap.hpp ++../../../src/hotspot/share/oops/symbol.hpp ++../../../src/hotspot/share/oops/instanceClassLoaderKlass.hpp ++../../../src/hotspot/share/oops/access.cpp ++../../../src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp ++../../../src/hotspot/share/oops/instanceOop.hpp ++../../../src/hotspot/share/oops/arrayKlass.hpp ++../../../src/hotspot/share/oops/weakHandle.cpp ++../../../src/hotspot/share/oops/constantPool.inline.hpp ++../../../src/hotspot/share/oops/instanceRefKlass.hpp ++../../../src/hotspot/share/oops/klass.cpp ++../../../src/hotspot/share/oops/array.inline.hpp ++../../../src/hotspot/share/oops/constantPool.cpp ++../../../src/hotspot/share/oops/access.inline.hpp ++../../../src/hotspot/share/oops/instanceKlass.hpp ++../../../src/hotspot/share/opto/ad.hpp ++../../../src/hotspot/share/opto/ifnode.cpp ++../../../src/hotspot/share/opto/phase.cpp ++../../../src/hotspot/share/opto/parseHelper.cpp ++../../../src/hotspot/share/opto/callGenerator.cpp ++../../../src/hotspot/share/opto/c2_globals.hpp ++../../../src/hotspot/share/opto/replacednodes.hpp ++../../../src/hotspot/share/opto/runtime.hpp ++../../../src/hotspot/share/opto/chaitin.hpp ++../../../src/hotspot/share/opto/subnode.hpp ++../../../src/hotspot/share/opto/divnode.hpp ++../../../src/hotspot/share/opto/intrinsicnode.cpp ++../../../src/hotspot/share/opto/multnode.cpp ++../../../src/hotspot/share/opto/live.cpp ++../../../src/hotspot/share/opto/macro.cpp ++../../../src/hotspot/share/opto/phaseX.hpp ++../../../src/hotspot/share/opto/convertnode.cpp ++../../../src/hotspot/share/opto/addnode.hpp ++../../../src/hotspot/share/opto/graphKit.hpp ++../../../src/hotspot/share/opto/type.hpp ++../../../src/hotspot/share/opto/connode.cpp ++../../../src/hotspot/share/opto/vectornode.cpp ++../../../src/hotspot/share/opto/regmask.hpp ++../../../src/hotspot/share/opto/escape.cpp ++../../../src/hotspot/share/opto/coalesce.cpp ++../../../src/hotspot/share/opto/matcher.cpp ++../../../src/hotspot/share/opto/cfgnode.hpp ++../../../src/hotspot/share/opto/opaquenode.cpp ++../../../src/hotspot/share/opto/classes.hpp ++../../../src/hotspot/share/opto/idealGraphPrinter.cpp ++../../../src/hotspot/share/opto/loopPredicate.cpp ++../../../src/hotspot/share/opto/mathexactnode.cpp ++../../../src/hotspot/share/opto/loopTransform.cpp ++../../../src/hotspot/share/opto/callnode.cpp ++../../../src/hotspot/share/opto/doCall.cpp ++../../../src/hotspot/share/opto/block.cpp ++../../../src/hotspot/share/opto/gcm.cpp ++../../../src/hotspot/share/opto/locknode.hpp ++../../../src/hotspot/share/opto/movenode.hpp ++../../../src/hotspot/share/opto/node.cpp ++../../../src/hotspot/share/opto/regalloc.cpp ++../../../src/hotspot/share/opto/countbitsnode.cpp ++../../../src/hotspot/share/opto/indexSet.cpp ++../../../src/hotspot/share/opto/stringopts.hpp ++../../../src/hotspot/share/opto/compile.hpp ++../../../src/hotspot/share/opto/opcodes.hpp ++../../../src/hotspot/share/opto/phasetype.hpp ++../../../src/hotspot/share/opto/mulnode.cpp ++../../../src/hotspot/share/opto/narrowptrnode.cpp ++../../../src/hotspot/share/opto/superword.hpp ++../../../src/hotspot/share/opto/memnode.hpp ++../../../src/hotspot/share/opto/rootnode.hpp ++../../../src/hotspot/share/opto/castnode.hpp ++../../../src/hotspot/share/opto/loopnode.cpp ++../../../src/hotspot/share/opto/loopopts.cpp ++../../../src/hotspot/share/opto/arraycopynode.cpp ++../../../src/hotspot/share/opto/c2compiler.hpp ++../../../src/hotspot/share/opto/idealKit.hpp ++../../../src/hotspot/share/opto/output.cpp ++../../../src/hotspot/share/opto/machnode.hpp ++../../../src/hotspot/share/opto/generateOptoStub.cpp ++../../../src/hotspot/share/opto/split_if.cpp ++../../../src/hotspot/share/opto/reg_split.cpp ++../../../src/hotspot/share/opto/matcher.hpp ++../../../src/hotspot/share/opto/idealGraphPrinter.hpp ++../../../src/hotspot/share/opto/mathexactnode.hpp ++../../../src/hotspot/share/opto/opaquenode.hpp ++../../../src/hotspot/share/opto/cfgnode.cpp ++../../../src/hotspot/share/opto/classes.cpp ++../../../src/hotspot/share/opto/callnode.hpp ++../../../src/hotspot/share/opto/block.hpp ++../../../src/hotspot/share/opto/node.hpp ++../../../src/hotspot/share/opto/movenode.cpp ++../../../src/hotspot/share/opto/regalloc.hpp ++../../../src/hotspot/share/opto/locknode.cpp ++../../../src/hotspot/share/opto/countbitsnode.hpp ++../../../src/hotspot/share/opto/stringopts.cpp ++../../../src/hotspot/share/opto/compile.cpp ++../../../src/hotspot/share/opto/indexSet.hpp ++../../../src/hotspot/share/opto/opcodes.cpp ++../../../src/hotspot/share/opto/narrowptrnode.hpp ++../../../src/hotspot/share/opto/mulnode.hpp ++../../../src/hotspot/share/opto/memnode.cpp ++../../../src/hotspot/share/opto/rootnode.cpp ++../../../src/hotspot/share/opto/superword.cpp ++../../../src/hotspot/share/opto/loopnode.hpp ++../../../src/hotspot/share/opto/castnode.cpp ++../../../src/hotspot/share/opto/adlcVMDeps.hpp ++../../../src/hotspot/share/opto/arraycopynode.hpp ++../../../src/hotspot/share/opto/c2compiler.cpp ++../../../src/hotspot/share/opto/machnode.cpp ++../../../src/hotspot/share/opto/output.hpp ++../../../src/hotspot/share/opto/optoreg.hpp ++../../../src/hotspot/share/opto/idealKit.cpp ++../../../src/hotspot/share/opto/ifg.cpp ++../../../src/hotspot/share/opto/phase.hpp ++../../../src/hotspot/share/opto/c2_globals.cpp ++../../../src/hotspot/share/opto/callGenerator.hpp ++../../../src/hotspot/share/opto/domgraph.cpp ++../../../src/hotspot/share/opto/macroArrayCopy.cpp ++../../../src/hotspot/share/opto/replacednodes.cpp ++../../../src/hotspot/share/opto/postaloc.cpp ++../../../src/hotspot/share/opto/lcm.cpp ++../../../src/hotspot/share/opto/runtime.cpp ++../../../src/hotspot/share/opto/subnode.cpp ++../../../src/hotspot/share/opto/chaitin.cpp ++../../../src/hotspot/share/opto/intrinsicnode.hpp ++../../../src/hotspot/share/opto/multnode.hpp ++../../../src/hotspot/share/opto/loopUnswitch.cpp ++../../../src/hotspot/share/opto/divnode.cpp ++../../../src/hotspot/share/opto/buildOopMap.cpp ++../../../src/hotspot/share/opto/convertnode.hpp ++../../../src/hotspot/share/opto/live.hpp ++../../../src/hotspot/share/opto/macro.hpp ++../../../src/hotspot/share/opto/parse2.cpp ++../../../src/hotspot/share/opto/bytecodeInfo.cpp ++../../../src/hotspot/share/opto/phaseX.cpp ++../../../src/hotspot/share/opto/parse3.cpp ++../../../src/hotspot/share/opto/addnode.cpp ++../../../src/hotspot/share/opto/parse.hpp ++../../../src/hotspot/share/opto/connode.hpp ++../../../src/hotspot/share/opto/type.cpp ++../../../src/hotspot/share/opto/graphKit.cpp ++../../../src/hotspot/share/opto/parse1.cpp ++../../../src/hotspot/share/opto/vectornode.hpp ++../../../src/hotspot/share/opto/coalesce.hpp ++../../../src/hotspot/share/opto/library_call.cpp ++../../../src/hotspot/share/opto/escape.hpp ++../../../src/hotspot/share/opto/regmask.cpp ++../../../src/hotspot/share/precompiled/precompiled.hpp ++../../../src/hotspot/share/compiler/abstractCompiler.cpp ++../../../src/hotspot/share/compiler/compilerDefinitions.cpp ++../../../src/hotspot/share/compiler/methodMatcher.cpp ++../../../src/hotspot/share/compiler/compilerOracle.cpp ++../../../src/hotspot/share/compiler/compileTask.hpp ++../../../src/hotspot/share/compiler/disassembler.cpp ++../../../src/hotspot/share/compiler/oopMap.hpp ++../../../src/hotspot/share/compiler/compileLog.hpp ++../../../src/hotspot/share/compiler/directivesParser.hpp ++../../../src/hotspot/share/compiler/compileBroker.cpp ++../../../src/hotspot/share/compiler/compilerDirectives.cpp ++../../../src/hotspot/share/compiler/methodLiveness.cpp ++../../../src/hotspot/share/compiler/oopMap.cpp ++../../../src/hotspot/share/compiler/compileLog.cpp ++../../../src/hotspot/share/compiler/directivesParser.cpp ++../../../src/hotspot/share/compiler/compileBroker.hpp ++../../../src/hotspot/share/compiler/compilerDirectives.hpp ++../../../src/hotspot/share/compiler/methodLiveness.hpp ++../../../src/hotspot/share/compiler/compilerDefinitions.hpp ++../../../src/hotspot/share/compiler/abstractCompiler.hpp ++../../../src/hotspot/share/compiler/methodMatcher.hpp ++../../../src/hotspot/share/compiler/compilerOracle.hpp ++../../../src/hotspot/share/compiler/compileTask.cpp ++../../../src/hotspot/share/compiler/disassembler.hpp ++../../../src/hotspot/share/logging/logTagSet.cpp ++../../../src/hotspot/share/logging/logOutput.hpp ++../../../src/hotspot/share/logging/logDecorations.hpp ++../../../src/hotspot/share/logging/logFileStreamOutput.hpp ++../../../src/hotspot/share/logging/logOutputList.hpp ++../../../src/hotspot/share/logging/logSelection.cpp ++../../../src/hotspot/share/logging/logLevel.hpp ++../../../src/hotspot/share/logging/logStream.cpp ++../../../src/hotspot/share/logging/logConfiguration.hpp ++../../../src/hotspot/share/logging/logTag.hpp ++../../../src/hotspot/share/logging/logDecorators.cpp ++../../../src/hotspot/share/logging/logMessage.hpp ++../../../src/hotspot/share/logging/logTagSetDescriptions.hpp ++../../../src/hotspot/share/logging/logSelectionList.hpp ++../../../src/hotspot/share/logging/logFileOutput.cpp ++../../../src/hotspot/share/logging/logMessageBuffer.hpp ++../../../src/hotspot/share/logging/logDiagnosticCommand.hpp ++../../../src/hotspot/share/logging/logTag.cpp ++../../../src/hotspot/share/logging/logConfiguration.cpp ++../../../src/hotspot/share/logging/logDecorators.hpp ++../../../src/hotspot/share/logging/logPrefix.hpp ++../../../src/hotspot/share/logging/logTagSetDescriptions.cpp ++../../../src/hotspot/share/logging/logMessageBuffer.cpp ++../../../src/hotspot/share/logging/logSelectionList.cpp ++../../../src/hotspot/share/logging/logFileOutput.hpp ++../../../src/hotspot/share/logging/logDiagnosticCommand.cpp ++../../../src/hotspot/share/logging/logHandle.hpp ++../../../src/hotspot/share/logging/logTagSet.hpp ++../../../src/hotspot/share/logging/log.hpp ++../../../src/hotspot/share/logging/logOutput.cpp ++../../../src/hotspot/share/logging/logFileStreamOutput.cpp ++../../../src/hotspot/share/logging/logDecorations.cpp ++../../../src/hotspot/share/logging/logOutputList.cpp ++../../../src/hotspot/share/logging/logTag_ext.hpp ++../../../src/hotspot/share/logging/logSelection.hpp ++../../../src/hotspot/share/logging/logLevel.cpp ++../../../src/hotspot/share/logging/logStream.hpp ++../../../src/hotspot/share/services/gcNotifier.cpp ++../../../src/hotspot/share/services/memBaseline.cpp ++../../../src/hotspot/share/services/heapDumper.hpp ++../../../src/hotspot/share/services/memoryPool.hpp ++../../../src/hotspot/share/services/nmtCommon.cpp ++../../../src/hotspot/share/services/mallocTracker.hpp ++../../../src/hotspot/share/services/nmtDCmd.cpp ++../../../src/hotspot/share/services/diagnosticCommand.cpp ++../../../src/hotspot/share/services/lowMemoryDetector.cpp ++../../../src/hotspot/share/services/writeableFlags.cpp ++../../../src/hotspot/share/services/threadService.cpp ++../../../src/hotspot/share/services/runtimeService.cpp ++../../../src/hotspot/share/services/attachListener.hpp ++../../../src/hotspot/share/services/memoryService.cpp ++../../../src/hotspot/share/services/memoryManager.hpp ++../../../src/hotspot/share/services/management.hpp ++../../../src/hotspot/share/services/memReporter.hpp ++../../../src/hotspot/share/services/memTracker.hpp ++../../../src/hotspot/share/services/allocationSite.hpp ++../../../src/hotspot/share/services/classLoadingService.cpp ++../../../src/hotspot/share/services/virtualMemoryTracker.hpp ++../../../src/hotspot/share/services/mallocSiteTable.cpp ++../../../src/hotspot/share/services/dtraceAttacher.hpp ++../../../src/hotspot/share/services/diagnosticArgument.cpp ++../../../src/hotspot/share/services/diagnosticFramework.hpp ++../../../src/hotspot/share/services/runtimeService.hpp ++../../../src/hotspot/share/services/threadService.hpp ++../../../src/hotspot/share/services/memoryService.hpp ++../../../src/hotspot/share/services/attachListener.cpp ++../../../src/hotspot/share/services/mallocTracker.inline.hpp ++../../../src/hotspot/share/services/memTracker.cpp ++../../../src/hotspot/share/services/management.cpp ++../../../src/hotspot/share/services/memReporter.cpp ++../../../src/hotspot/share/services/memoryManager.cpp ++../../../src/hotspot/share/services/classLoadingService.hpp ++../../../src/hotspot/share/services/memoryUsage.hpp ++../../../src/hotspot/share/services/dtraceAttacher.cpp ++../../../src/hotspot/share/services/mallocSiteTable.hpp ++../../../src/hotspot/share/services/virtualMemoryTracker.cpp ++../../../src/hotspot/share/services/diagnosticFramework.cpp ++../../../src/hotspot/share/services/diagnosticArgument.hpp ++../../../src/hotspot/share/services/gcNotifier.hpp ++../../../src/hotspot/share/services/memBaseline.hpp ++../../../src/hotspot/share/services/heapDumper.cpp ++../../../src/hotspot/share/services/memoryPool.cpp ++../../../src/hotspot/share/services/nmtCommon.hpp ++../../../src/hotspot/share/services/mallocTracker.cpp ++../../../src/hotspot/share/services/nmtDCmd.hpp ++../../../src/hotspot/share/services/lowMemoryDetector.hpp ++../../../src/hotspot/share/services/diagnosticCommand.hpp ++../../../src/hotspot/share/services/writeableFlags.hpp ++../../../src/hotspot/share/services/diagnosticCommand_ext.hpp ++../../../src/hotspot/share/aot/aotCodeHeap.cpp ++../../../src/hotspot/share/aot/aotCompiledMethod.cpp ++../../../src/hotspot/share/aot/aotLoader.hpp ++../../../src/hotspot/share/aot/compiledIC_aot.hpp ++../../../src/hotspot/share/aot/compiledIC_aot.cpp ++../../../src/hotspot/share/aot/aotCompiledMethod.hpp ++../../../src/hotspot/share/aot/aotCodeHeap.hpp ++../../../src/hotspot/share/aot/aotLoader.cpp ++../../../src/hotspot/share/aot/aotLoader.inline.hpp ++../../../src/hotspot/share/jvmci/vmStructs_jvmci.hpp ++../../../src/hotspot/share/jvmci/compilerRuntime.cpp ++../../../src/hotspot/share/jvmci/jvmciCodeInstaller.hpp ++../../../src/hotspot/share/jvmci/jvmci_globals.cpp ++../../../src/hotspot/share/jvmci/systemDictionary_jvmci.hpp ++../../../src/hotspot/share/jvmci/jvmciJavaClasses.hpp ++../../../src/hotspot/share/jvmci/jvmciRuntime.cpp ++../../../src/hotspot/share/jvmci/jvmciEnv.hpp ++../../../src/hotspot/share/jvmci/jvmciCompiler.cpp ++../../../src/hotspot/share/jvmci/vmSymbols_jvmci.hpp ++../../../src/hotspot/share/jvmci/jvmciCompilerToVM.hpp ++../../../src/hotspot/share/jvmci/jvmciEnv.cpp ++../../../src/hotspot/share/jvmci/jvmciCompiler.hpp ++../../../src/hotspot/share/jvmci/jvmciCompilerToVM.cpp ++../../../src/hotspot/share/jvmci/vmStructs_jvmci.cpp ++../../../src/hotspot/share/jvmci/compilerRuntime.hpp ++../../../src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp ++../../../src/hotspot/share/jvmci/jvmciCodeInstaller.cpp ++../../../src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp ++../../../src/hotspot/share/jvmci/jvmci_globals.hpp ++../../../src/hotspot/share/jvmci/jvmciJavaClasses.cpp ++../../../src/hotspot/share/jvmci/jvmciRuntime.hpp) ++ ++add_executable(hotspot ${SOURCE_FILES}) +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch b/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch new file mode 100644 index 000000000000..49c840624d52 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch @@ -0,0 +1,25 @@ +From d56e73885111b386771f564ec6beb305338993df Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Mon, 19 Oct 2020 20:00:04 +0200 +Subject: [PATCH 12/34] Set HOTSPOT_VM_DISTRO=Dynamic Code Evolution + +--- + make/autoconf/version-numbers | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers +index aabdc5bed20..df8025a2e84 100644 +--- a/make/autoconf/version-numbers ++++ b/make/autoconf/version-numbers +@@ -45,7 +45,7 @@ PRODUCT_NAME=OpenJDK + PRODUCT_SUFFIX="Runtime Environment" + JDK_RC_PLATFORM_NAME=Platform + COMPANY_NAME=N/A +-HOTSPOT_VM_DISTRO="OpenJDK" ++HOTSPOT_VM_DISTRO="Dynamic Code Evolution" + VENDOR_URL=https://openjdk.java.net/ + VENDOR_URL_BUG=https://bugreport.java.com/bugreport/ + VENDOR_URL_VM_BUG=https://bugreport.java.com/bugreport/crash.jsp +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch b/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch new file mode 100644 index 000000000000..3c2bcd50a96d --- /dev/null +++ b/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch @@ -0,0 +1,71 @@ +From 7ebad43ed45805b0a3736c510f708ff17697ba7e Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 11 Oct 2020 10:43:28 +0200 +Subject: [PATCH 13/34] Fix G1 nmethod registration + +--- + .../prims/jvmtiEnhancedRedefineClasses.cpp | 19 ++++++++++++++++--- + .../prims/jvmtiEnhancedRedefineClasses.hpp | 3 ++- + 2 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index b09ba554e07..718426f2819 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -216,7 +216,14 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { + } + } + +-void VM_EnhancedRedefineClasses::mark_as_scavengable_g1(nmethod* nm) { ++void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { ++ // It should work not only for G1 but also for another GCs, but this way is safer now ++ if (!nm->is_zombie() && !nm->is_unloaded()) { ++ Universe::heap()->unregister_nmethod(nm); ++ } ++} ++ ++void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) { + // It should work not only for G1 but also for another GCs, but this way is safer now + if (!nm->is_zombie() && !nm->is_unloaded()) { + Universe::heap()->register_nmethod(nm); +@@ -521,8 +528,9 @@ void VM_EnhancedRedefineClasses::doit() { + // For now, mark all nmethod's as scavengable that are not scavengable already + if (ScavengeRootsInCode) { + if (UseG1GC) { +- // this should work also for other GCs +- CodeCache::nmethods_do(mark_as_scavengable_g1); ++ // G1 holds references to nmethods in regions based on oops values. Since oops in nmethod can be changed in ChangePointers* closures ++ // we unregister nmethods from G1 heap, then closures are processed (oops are changed) and finally we register nmethod to G1 again ++ CodeCache::nmethods_do(unregister_nmethod_g1); + } else { + CodeCache::nmethods_do(mark_as_scavengable); + } +@@ -545,6 +553,11 @@ void VM_EnhancedRedefineClasses::doit() { + + Universe::root_oops_do(&oopClosureNoBarrier); + ++ if (UseG1GC) { ++ // this should work also for other GCs ++ CodeCache::nmethods_do(register_nmethod_g1); ++ } ++ + } + log_trace(redefine, class, obsolete, metadata)("After updating instances"); + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index 9755944d70b..4c0412d343d 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -116,7 +116,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + + void rollback(); + static void mark_as_scavengable(nmethod* nm); +- static void mark_as_scavengable_g1(nmethod* nm); ++ static void unregister_nmethod_g1(nmethod* nm); ++ static void register_nmethod_g1(nmethod* nm); + static void unpatch_bytecode(Method* method); + static void fix_invoke_method(Method* method); + +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch b/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch new file mode 100644 index 000000000000..1741c6091bd5 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch @@ -0,0 +1,26 @@ +From 5c7e5f245f79d7e8575461dab0c356ed74c8e9a3 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Thu, 22 Oct 2020 20:15:20 +0200 +Subject: [PATCH 14/34] Initialize method's _new_version/_old_version to NULL + +--- + src/hotspot/share/oops/method.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp +index 1c88511a5fc..ce940cf10a9 100644 +--- a/src/hotspot/share/oops/method.cpp ++++ b/src/hotspot/share/oops/method.cpp +@@ -91,7 +91,8 @@ Method* Method::allocate(ClassLoaderData* loader_data, + return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags); + } + +-Method::Method(ConstMethod* xconst, AccessFlags access_flags) { ++Method::Method(ConstMethod* xconst, AccessFlags access_flags) : _new_version(NULL), ++ _old_version(NULL) { + NoSafepointVerifier no_safepoint; + set_constMethod(xconst); + set_access_flags(access_flags); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch b/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch new file mode 100644 index 000000000000..72144d85d8f6 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch @@ -0,0 +1,193 @@ +From 6ffac6e5064ec6633fdbeb8520333dca00bc6a62 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Fri, 23 Oct 2020 10:20:26 +0200 +Subject: [PATCH 15/34] Clear dcevm code separation + +--- + src/hotspot/share/classfile/systemDictionary.cpp | 4 ++-- + src/hotspot/share/gc/serial/genMarkSweep.cpp | 8 +++++--- + src/hotspot/share/interpreter/linkResolver.cpp | 16 +++++++++++----- + .../instrumentation/jfrEventClassTransformer.cpp | 2 +- + src/hotspot/share/oops/instanceKlass.cpp | 10 ++++++---- + src/hotspot/share/oops/method.cpp | 2 +- + .../share/prims/jvmtiGetLoadedClasses.cpp | 2 +- + src/hotspot/share/runtime/reflection.cpp | 2 +- + 8 files changed, 28 insertions(+), 18 deletions(-) + +diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp +index 8f2b46add4d..9ac6ec96cb5 100644 +--- a/src/hotspot/share/classfile/systemDictionary.cpp ++++ b/src/hotspot/share/classfile/systemDictionary.cpp +@@ -1241,7 +1241,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, + MutexLocker mu(THREAD, SystemDictionary_lock); + + Klass* check = find_class(h_name, k->class_loader_data()); +- assert((check == k && !k->is_redefining()) || (k->is_redefining() && check == k->old_version()), "should be present in the dictionary"); ++ assert(check == k && !k->is_redefining() || k->is_redefining() && check == k->old_version(), "should be present in the dictionary"); + } ); + + return k; +@@ -2290,7 +2290,7 @@ void SystemDictionary::check_constraints(unsigned int d_hash, + // also hold array classes. + + assert(check->is_instance_klass(), "noninstance in systemdictionary"); +- if ((defining == true) || ((k != check) && k->old_version() != check)) { ++ if ((defining == true) || (k != check && (!AllowEnhancedClassRedefinition || k->old_version() != check))) { + throwException = true; + ss.print("loader %s", loader_data->loader_name_and_id()); + ss.print(" attempted duplicate %s definition for %s. (%s)", +diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp +index 1d13c647452..548df01e557 100644 +--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp ++++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp +@@ -334,7 +334,9 @@ void GenMarkSweep::mark_sweep_phase4() { + + GenCompactClosure blk; + gch->generation_iterate(&blk, true); +- DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); +- DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); +- MarkSweep::_rescued_oops = NULL; ++ if (AllowEnhancedClassRedefinition) { ++ DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); ++ DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); ++ MarkSweep::_rescued_oops = NULL; ++ } + } +diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp +index b6e9e0a308d..b2f24ddbeda 100644 +--- a/src/hotspot/share/interpreter/linkResolver.cpp ++++ b/src/hotspot/share/interpreter/linkResolver.cpp +@@ -282,9 +282,14 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass, + if (!base_klass->is_instance_klass()) { + return; // no relevant check to do + } +- +- Reflection::VerifyClassAccessResults vca_result = +- Reflection::verify_class_access(ref_klass->newest_version(), InstanceKlass::cast(base_klass->newest_version()), true); ++ Klass* refKlassNewest = ref_klass; ++ Klass* baseKlassNewest = base_klass; ++ if (AllowEnhancedClassRedefinition) { ++ refKlassNewest = ref_klass->newest_version(); ++ baseKlassNewest = base_klass->newest_version(); ++ } ++ Reflection::VerifyClassAccessResults vca_result = ++ Reflection::verify_class_access(refKlassNewest, InstanceKlass::cast(baseKlassNewest), true); + if (vca_result != Reflection::ACCESS_OK) { + ResourceMark rm(THREAD); + char* msg = Reflection::verify_class_access_msg(ref_klass, +@@ -566,7 +571,8 @@ void LinkResolver::check_method_accessability(Klass* ref_klass, + // We'll check for the method name first, as that's most likely + // to be false (so we'll short-circuit out of these tests). + if (sel_method->name() == vmSymbols::clone_name() && +- sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version() && ++ ( !AllowEnhancedClassRedefinition && sel_klass == SystemDictionary::Object_klass() || ++ AllowEnhancedClassRedefinition && sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version()) && + resolved_klass->is_array_klass()) { + // We need to change "protected" to "public". + assert(flags.is_protected(), "clone not protected?"); +@@ -1011,7 +1017,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, + // or by the method (in case of an instance field). + if (is_put && fd.access_flags().is_final()) { + +- if (sel_klass != current_klass && sel_klass != current_klass->active_version()) { ++ if (sel_klass != current_klass && (!AllowEnhancedClassRedefinition || sel_klass != current_klass->active_version())) { + ResourceMark rm(THREAD); + stringStream ss; + ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", +diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +index 96fc139bea3..f7284197c5a 100644 +--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp ++++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +@@ -1471,7 +1471,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre + cld, + &cl_info, + ClassFileParser::INTERNAL, // internal visibility +- false, ++ false, + THREAD); + if (HAS_PENDING_EXCEPTION) { + log_pending_exception(PENDING_EXCEPTION); +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index 3be3a09ef8f..f8e60941046 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -199,7 +199,9 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { + // able to perform that loading but we can't exclude the compiler threads from + // executing this logic. But it should actually be impossible to trigger loading here. + Klass* k2 = _constants->klass_at(cp_index, THREAD); +- k2 = k2->newest_version(); ++ if (AllowEnhancedClassRedefinition) { ++ k2 = k2->newest_version(); ++ } + assert(!HAS_PENDING_EXCEPTION || PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass()), + "Exceptions should not be possible here"); + if (k2 == k) { +@@ -1003,7 +1005,7 @@ bool InstanceKlass::link_class_impl(TRAPS) { + #endif + set_init_state(linked); + // (DCEVM) Must check for old version in order to prevent infinite loops. +- if (JvmtiExport::should_post_class_prepare() && old_version() == NULL /* JVMTI deadlock otherwise */) { ++ if (JvmtiExport::should_post_class_prepare() && (!AllowEnhancedClassRedefinition || old_version() == NULL) /* JVMTI deadlock otherwise */) { + Thread *thread = THREAD; + assert(thread->is_Java_thread(), "thread->is_Java_thread()"); + JvmtiExport::post_class_prepare((JavaThread *) thread, this); +@@ -1084,7 +1086,7 @@ void InstanceKlass::initialize_impl(TRAPS) { + // we might end up throwing IE from link/symbol resolution sites + // that aren't expected to throw. This would wreak havoc. See 6320309. + while ((is_being_initialized() && !is_reentrant_initialization(jt)) +- || (old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { ++ || (AllowEnhancedClassRedefinition && old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { + wait = true; + jt->set_class_to_be_initialized(this); + ol.wait_uninterruptibly(jt); +@@ -3782,7 +3784,7 @@ void InstanceKlass::verify_on(outputStream* st) { + + guarantee(sib->is_klass(), "should be klass"); + // TODO: (DCEVM) explain +- guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); ++ guarantee(sib->super() == super || AllowEnhancedClassRedefinition && super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); + } + + // Verify local interfaces +diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp +index ce940cf10a9..2d8e5b0256b 100644 +--- a/src/hotspot/share/oops/method.cpp ++++ b/src/hotspot/share/oops/method.cpp +@@ -2208,7 +2208,7 @@ void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) { + // Add a method id to the jmethod_ids + jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) { + // FIXME: (DCEVM) ??? +- if (m != m->newest_version()) { ++ if (AllowEnhancedClassRedefinition && m != m->newest_version()) { + m = m->newest_version(); + } + ClassLoaderData* cld = loader_data; +diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +index 1c7677f270f..6c12ee64a6e 100644 +--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +@@ -75,7 +75,7 @@ public: + // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was + // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we + // must use new versions only. +- if (k->new_version()==NULL) { ++ if (AllowEnhancedClassRedefinition && k->new_version()==NULL) { + _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); + if (_dictionary_walk) { + // Collect array classes this way when walking the dictionary (because array classes are +diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp +index 0e7722dba7d..d67457f02ac 100644 +--- a/src/hotspot/share/runtime/reflection.cpp ++++ b/src/hotspot/share/runtime/reflection.cpp +@@ -628,7 +628,7 @@ bool Reflection::verify_member_access(const Klass* current_class, + TRAPS) { + + // (DCEVM) Decide accessibility based on active version +- if (current_class != NULL) { ++ if (AllowEnhancedClassRedefinition && current_class != NULL) { + current_class = current_class->active_version(); + } + +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch b/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch new file mode 100644 index 000000000000..ac5132f7c98e --- /dev/null +++ b/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch @@ -0,0 +1,26 @@ +From dc675de6ac42819b8536827ea450fcad13a97448 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Wed, 11 Nov 2020 18:45:15 +0100 +Subject: [PATCH 16/34] Fix LoadedClassesClosure - fixes problems with remote + debugging + +--- + src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +index 6c12ee64a6e..2a469555dbd 100644 +--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp +@@ -75,7 +75,7 @@ public: + // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was + // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we + // must use new versions only. +- if (AllowEnhancedClassRedefinition && k->new_version()==NULL) { ++ if (!AllowEnhancedClassRedefinition || k->new_version()==NULL) { + _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); + if (_dictionary_walk) { + // Collect array classes this way when walking the dictionary (because array classes are +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch b/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch new file mode 100644 index 000000000000..8491b58fb385 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch @@ -0,0 +1,3934 @@ +From 5cdb7847b227797e74bdf025065696ef6273dcd6 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Mon, 16 Nov 2020 20:54:06 +0100 +Subject: [PATCH 17/34] pre dcevm15 - Cleanup code related to removed CMS + +--- + .../share/gc/cms/compactibleFreeListSpace.cpp | 3148 ----------------- + .../share/gc/cms/compactibleFreeListSpace.hpp | 759 ---- + 2 files changed, 3907 deletions(-) + delete mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp + delete mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp + +diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp +deleted file mode 100644 +index a93f764f1b9..00000000000 +--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp ++++ /dev/null +@@ -1,3148 +0,0 @@ +-/* +- * Copyright (c) 2001, 2018, 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/cms/cmsHeap.hpp" +-#include "gc/cms/cmsLockVerifier.hpp" +-#include "gc/cms/compactibleFreeListSpace.hpp" +-#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" +-#include "gc/cms/concurrentMarkSweepThread.hpp" +-#include "gc/shared/blockOffsetTable.inline.hpp" +-#include "gc/shared/collectedHeap.inline.hpp" +-#include "gc/shared/genOopClosures.inline.hpp" +-#include "gc/shared/space.inline.hpp" +-#include "gc/shared/spaceDecorator.hpp" +-#include "logging/log.hpp" +-#include "logging/logStream.hpp" +-#include "memory/allocation.inline.hpp" +-#include "memory/binaryTreeDictionary.inline.hpp" +-#include "memory/iterator.inline.hpp" +-#include "memory/resourceArea.hpp" +-#include "memory/universe.hpp" +-#include "oops/access.inline.hpp" +-#include "oops/compressedOops.inline.hpp" +-#include "oops/oop.inline.hpp" +-#include "runtime/globals.hpp" +-#include "runtime/handles.inline.hpp" +-#include "runtime/init.hpp" +-#include "runtime/java.hpp" +-#include "runtime/orderAccess.hpp" +-#include "runtime/vmThread.hpp" +-#include "utilities/align.hpp" +-#include "utilities/copy.hpp" +- +-// Specialize for AdaptiveFreeList which tries to avoid +-// splitting a chunk of a size that is under populated in favor of +-// an over populated size. The general get_better_list() just returns +-// the current list. +-template <> +-TreeList >* +-TreeList >::get_better_list( +- BinaryTreeDictionary >* dictionary) { +- // A candidate chunk has been found. If it is already under +- // populated, get a chunk associated with the hint for this +- // chunk. +- +- TreeList >* curTL = this; +- if (curTL->surplus() <= 0) { +- /* Use the hint to find a size with a surplus, and reset the hint. */ +- TreeList >* hintTL = this; +- while (hintTL->hint() != 0) { +- assert(hintTL->hint() > hintTL->size(), +- "hint points in the wrong direction"); +- hintTL = dictionary->find_list(hintTL->hint()); +- assert(curTL != hintTL, "Infinite loop"); +- if (hintTL == NULL || +- hintTL == curTL /* Should not happen but protect against it */ ) { +- // No useful hint. Set the hint to NULL and go on. +- curTL->set_hint(0); +- break; +- } +- assert(hintTL->size() > curTL->size(), "hint is inconsistent"); +- if (hintTL->surplus() > 0) { +- // The hint led to a list that has a surplus. Use it. +- // Set the hint for the candidate to an overpopulated +- // size. +- curTL->set_hint(hintTL->size()); +- // Change the candidate. +- curTL = hintTL; +- break; +- } +- } +- } +- return curTL; +-} +- +-void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) { +- TreeList >* nd = find_list(size); +- if (nd) { +- if (split) { +- if (birth) { +- nd->increment_split_births(); +- nd->increment_surplus(); +- } else { +- nd->increment_split_deaths(); +- nd->decrement_surplus(); +- } +- } else { +- if (birth) { +- nd->increment_coal_births(); +- nd->increment_surplus(); +- } else { +- nd->increment_coal_deaths(); +- nd->decrement_surplus(); +- } +- } +- } +- // A list for this size may not be found (nd == 0) if +- // This is a death where the appropriate list is now +- // empty and has been removed from the list. +- // This is a birth associated with a LinAB. The chunk +- // for the LinAB is not in the dictionary. +-} +- +-bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { +- if (FLSAlwaysCoalesceLarge) return true; +- +- TreeList >* list_of_size = find_list(size); +- // None of requested size implies overpopulated. +- return list_of_size == NULL || list_of_size->coal_desired() <= 0 || +- list_of_size->count() > list_of_size->coal_desired(); +-} +- +-// For each list in the tree, calculate the desired, desired +-// coalesce, count before sweep, and surplus before sweep. +-class BeginSweepClosure : public AscendTreeCensusClosure > { +- double _percentage; +- float _inter_sweep_current; +- float _inter_sweep_estimate; +- float _intra_sweep_estimate; +- +- public: +- BeginSweepClosure(double p, float inter_sweep_current, +- float inter_sweep_estimate, +- float intra_sweep_estimate) : +- _percentage(p), +- _inter_sweep_current(inter_sweep_current), +- _inter_sweep_estimate(inter_sweep_estimate), +- _intra_sweep_estimate(intra_sweep_estimate) { } +- +- void do_list(AdaptiveFreeList* fl) { +- double coalSurplusPercent = _percentage; +- fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); +- fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent)); +- fl->set_before_sweep(fl->count()); +- fl->set_bfr_surp(fl->surplus()); +- } +-}; +- +-void AFLBinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent, +- float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { +- BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, +- inter_sweep_estimate, +- intra_sweep_estimate); +- bsc.do_tree(root()); +-} +- +-// Calculate surpluses for the lists in the tree. +-class setTreeSurplusClosure : public AscendTreeCensusClosure > { +- double percentage; +- public: +- setTreeSurplusClosure(double v) { percentage = v; } +- +- void do_list(AdaptiveFreeList* fl) { +- double splitSurplusPercent = percentage; +- fl->set_surplus(fl->count() - +- (ssize_t)((double)fl->desired() * splitSurplusPercent)); +- } +-}; +- +-void AFLBinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) { +- setTreeSurplusClosure sts(splitSurplusPercent); +- sts.do_tree(root()); +-} +- +-// Set hints for the lists in the tree. +-class setTreeHintsClosure : public DescendTreeCensusClosure > { +- size_t hint; +- public: +- setTreeHintsClosure(size_t v) { hint = v; } +- +- void do_list(AdaptiveFreeList* fl) { +- fl->set_hint(hint); +- assert(fl->hint() == 0 || fl->hint() > fl->size(), +- "Current hint is inconsistent"); +- if (fl->surplus() > 0) { +- hint = fl->size(); +- } +- } +-}; +- +-void AFLBinaryTreeDictionary::set_tree_hints(void) { +- setTreeHintsClosure sth(0); +- sth.do_tree(root()); +-} +- +-// Save count before previous sweep and splits and coalesces. +-class clearTreeCensusClosure : public AscendTreeCensusClosure > { +- void do_list(AdaptiveFreeList* fl) { +- fl->set_prev_sweep(fl->count()); +- fl->set_coal_births(0); +- fl->set_coal_deaths(0); +- fl->set_split_births(0); +- fl->set_split_deaths(0); +- } +-}; +- +-void AFLBinaryTreeDictionary::clear_tree_census(void) { +- clearTreeCensusClosure ctc; +- ctc.do_tree(root()); +-} +- +-// Do reporting and post sweep clean up. +-void AFLBinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) { +- // Does walking the tree 3 times hurt? +- set_tree_surplus(splitSurplusPercent); +- set_tree_hints(); +- LogTarget(Trace, gc, freelist, stats) log; +- if (log.is_enabled()) { +- LogStream out(log); +- report_statistics(&out); +- } +- clear_tree_census(); +-} +- +-// Print census information - counts, births, deaths, etc. +-// for each list in the tree. Also print some summary +-// information. +-class PrintTreeCensusClosure : public AscendTreeCensusClosure > { +- int _print_line; +- size_t _total_free; +- AdaptiveFreeList _total; +- +- public: +- PrintTreeCensusClosure() { +- _print_line = 0; +- _total_free = 0; +- } +- AdaptiveFreeList* total() { return &_total; } +- size_t total_free() { return _total_free; } +- +- void do_list(AdaptiveFreeList* fl) { +- LogStreamHandle(Debug, gc, freelist, census) out; +- +- if (++_print_line >= 40) { +- AdaptiveFreeList::print_labels_on(&out, "size"); +- _print_line = 0; +- } +- fl->print_on(&out); +- _total_free += fl->count() * fl->size() ; +- total()->set_count( total()->count() + fl->count() ); +- total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() ); +- total()->set_surplus( total()->split_deaths() + fl->surplus() ); +- total()->set_desired( total()->desired() + fl->desired() ); +- total()->set_prev_sweep( total()->prev_sweep() + fl->prev_sweep() ); +- total()->set_before_sweep(total()->before_sweep() + fl->before_sweep()); +- total()->set_coal_births( total()->coal_births() + fl->coal_births() ); +- total()->set_coal_deaths( total()->coal_deaths() + fl->coal_deaths() ); +- total()->set_split_births(total()->split_births() + fl->split_births()); +- total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); +- } +-}; +- +-void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const { +- +- st->print_cr("BinaryTree"); +- AdaptiveFreeList::print_labels_on(st, "size"); +- PrintTreeCensusClosure ptc; +- ptc.do_tree(root()); +- +- AdaptiveFreeList* total = ptc.total(); +- AdaptiveFreeList::print_labels_on(st, " "); +- total->print_on(st, "TOTAL\t"); +- st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f deficit: %8.5f", +- ptc.total_free(), +- (double)(total->split_births() + total->coal_births() +- - total->split_deaths() - total->coal_deaths()) +- /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0), +- (double)(total->desired() - total->count()) +- /(total->desired() != 0 ? (double)total->desired() : 1.0)); +-} +- +-///////////////////////////////////////////////////////////////////////// +-//// CompactibleFreeListSpace +-///////////////////////////////////////////////////////////////////////// +- +-// highest ranked free list lock rank +-int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3; +- +-// Defaults are 0 so things will break badly if incorrectly initialized. +-size_t CompactibleFreeListSpace::IndexSetStart = 0; +-size_t CompactibleFreeListSpace::IndexSetStride = 0; +-size_t CompactibleFreeListSpace::_min_chunk_size_in_bytes = 0; +- +-size_t MinChunkSize = 0; +- +-void CompactibleFreeListSpace::set_cms_values() { +- // Set CMS global values +- assert(MinChunkSize == 0, "already set"); +- +- // MinChunkSize should be a multiple of MinObjAlignment and be large enough +- // for chunks to contain a FreeChunk. +- _min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes); +- MinChunkSize = _min_chunk_size_in_bytes / BytesPerWord; +- +- assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); +- IndexSetStart = MinChunkSize; +- IndexSetStride = MinObjAlignment; +-} +- +-// Constructor +-CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) : +- _bt(bs, mr), +- // free list locks are in the range of values taken by _lockRank +- // This range currently is [_leaf+2, _leaf+3] +- // Note: this requires that CFLspace c'tors +- // are called serially in the order in which the locks are +- // are acquired in the program text. This is true today. +- _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true, +- Monitor::_safepoint_check_sometimes), +- _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1 +- "CompactibleFreeListSpace._dict_par_lock", true, +- Monitor::_safepoint_check_never), +- _rescan_task_size(CardTable::card_size_in_words * BitsPerWord * +- CMSRescanMultiple), +- _marking_task_size(CardTable::card_size_in_words * BitsPerWord * +- CMSConcMarkMultiple), +- _collector(NULL), +- _preconsumptionDirtyCardClosure(NULL) +-{ +- assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, +- "FreeChunk is larger than expected"); +- _bt.set_space(this); +- initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); +- +- _dictionary = new AFLBinaryTreeDictionary(mr); +- +- assert(_dictionary != NULL, "CMS dictionary initialization"); +- // The indexed free lists are initially all empty and are lazily +- // filled in on demand. Initialize the array elements to NULL. +- initializeIndexedFreeListArray(); +- +- _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, +- SmallForLinearAlloc); +- +- // CMSIndexedFreeListReplenish should be at least 1 +- CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish); +- _promoInfo.setSpace(this); +- if (UseCMSBestFit) { +- _fitStrategy = FreeBlockBestFitFirst; +- } else { +- _fitStrategy = FreeBlockStrategyNone; +- } +- check_free_list_consistency(); +- +- // Initialize locks for parallel case. +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 +- "a freelist par lock", true, Mutex::_safepoint_check_sometimes); +- DEBUG_ONLY( +- _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); +- ) +- } +- _dictionary->set_par_lock(&_parDictionaryAllocLock); +- +- _used_stable = 0; +-} +- +-HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size, +- CompactPoint* cp, HeapWord* compact_top) { +- ShouldNotReachHere(); +- return NULL; +-} +- +-// Like CompactibleSpace forward() but always calls cross_threshold() to +-// update the block offset table. Removed initialize_threshold call because +-// CFLS does not use a block offset array for contiguous spaces. +-HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size, +- CompactPoint* cp, HeapWord* compact_top) { +- // q is alive +- // First check if we should switch compaction space +- assert(this == cp->space, "'this' should be current compaction space."); +- size_t compaction_max_size = pointer_delta(end(), compact_top); +- assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), +- "virtual adjustObjectSize_v() method is not correct"); +- size_t adjusted_size = adjustObjectSize(size); +- assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, +- "no small fragments allowed"); +- assert(minimum_free_block_size() == MinChunkSize, +- "for de-virtualized reference below"); +- // Can't leave a nonzero size, residual fragment smaller than MinChunkSize +- if (adjusted_size + MinChunkSize > compaction_max_size && +- adjusted_size != compaction_max_size) { +- do { +- // switch to next compaction space +- cp->space->set_compaction_top(compact_top); +- cp->space = cp->space->next_compaction_space(); +- if (cp->space == NULL) { +- cp->gen = CMSHeap::heap()->young_gen(); +- assert(cp->gen != NULL, "compaction must succeed"); +- cp->space = cp->gen->first_compaction_space(); +- assert(cp->space != NULL, "generation must have a first compaction space"); +- } +- compact_top = cp->space->bottom(); +- cp->space->set_compaction_top(compact_top); +- // The correct adjusted_size may not be the same as that for this method +- // (i.e., cp->space may no longer be "this" so adjust the size again. +- // Use the virtual method which is not used above to save the virtual +- // dispatch. +- adjusted_size = cp->space->adjust_object_size_v(size); +- compaction_max_size = pointer_delta(cp->space->end(), compact_top); +- assert(cp->space->minimum_free_block_size() == 0, "just checking"); +- } while (adjusted_size > compaction_max_size); +- } +- +- // store the forwarding pointer into the mark word +- if ((HeapWord*)q != compact_top) { +- q->forward_to(oop(compact_top)); +- assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); +- } else { +- // if the object isn't moving we can just set the mark to the default +- // mark and handle it specially later on. +- q->init_mark_raw(); +- assert(q->forwardee() == NULL, "should be forwarded to NULL"); +- } +- +- compact_top += adjusted_size; +- +- // we need to update the offset table so that the beginnings of objects can be +- // found during scavenge. Note that we are updating the offset table based on +- // where the object will be once the compaction phase finishes. +- +- // Always call cross_threshold(). A contiguous space can only call it when +- // the compaction_top exceeds the current threshold but not for an +- // non-contiguous space. +- cp->threshold = +- cp->space->cross_threshold(compact_top - adjusted_size, compact_top); +- return compact_top; +-} +- +-// A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt +-// and use of single_block instead of alloc_block. The name here is not really +-// appropriate - maybe a more general name could be invented for both the +-// contiguous and noncontiguous spaces. +- +-HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) { +- _bt.single_block(start, the_end); +- return end(); +-} +- +-// Initialize them to NULL. +-void CompactibleFreeListSpace::initializeIndexedFreeListArray() { +- for (size_t i = 0; i < IndexSetSize; i++) { +- // Note that on platforms where objects are double word aligned, +- // the odd array elements are not used. It is convenient, however, +- // to map directly from the object size to the array element. +- _indexedFreeList[i].reset(IndexSetSize); +- _indexedFreeList[i].set_size(i); +- assert(_indexedFreeList[i].count() == 0, "reset check failed"); +- assert(_indexedFreeList[i].head() == NULL, "reset check failed"); +- assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); +- assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); +- } +-} +- +-size_t CompactibleFreeListSpace::obj_size(const HeapWord* addr) const { +- return adjustObjectSize(oop(addr)->size()); +-} +- +-void CompactibleFreeListSpace::resetIndexedFreeListArray() { +- for (size_t i = 1; i < IndexSetSize; i++) { +- assert(_indexedFreeList[i].size() == (size_t) i, +- "Indexed free list sizes are incorrect"); +- _indexedFreeList[i].reset(IndexSetSize); +- assert(_indexedFreeList[i].count() == 0, "reset check failed"); +- assert(_indexedFreeList[i].head() == NULL, "reset check failed"); +- assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); +- assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); +- } +-} +- +-void CompactibleFreeListSpace::reset(MemRegion mr) { +- resetIndexedFreeListArray(); +- dictionary()->reset(); +- if (BlockOffsetArrayUseUnallocatedBlock) { +- assert(end() == mr.end(), "We are compacting to the bottom of CMS gen"); +- // Everything's allocated until proven otherwise. +- _bt.set_unallocated_block(end()); +- } +- if (!mr.is_empty()) { +- assert(mr.word_size() >= MinChunkSize, "Chunk size is too small"); +- _bt.single_block(mr.start(), mr.word_size()); +- FreeChunk* fc = (FreeChunk*) mr.start(); +- fc->set_size(mr.word_size()); +- if (mr.word_size() >= IndexSetSize ) { +- returnChunkToDictionary(fc); +- } else { +- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); +- _indexedFreeList[mr.word_size()].return_chunk_at_head(fc); +- } +- coalBirth(mr.word_size()); +- } +- _promoInfo.reset(); +- _smallLinearAllocBlock._ptr = NULL; +- _smallLinearAllocBlock._word_size = 0; +-} +- +-void CompactibleFreeListSpace::reset_after_compaction() { +- // Reset the space to the new reality - one free chunk. +- MemRegion mr(compaction_top(), end()); +- reset(mr); +- // Now refill the linear allocation block(s) if possible. +- refillLinearAllocBlocksIfNeeded(); +-} +- +-// Walks the entire dictionary, returning a coterminal +-// chunk, if it exists. Use with caution since it involves +-// a potentially complete walk of a potentially large tree. +-FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() { +- +- assert_lock_strong(&_freelistLock); +- +- return dictionary()->find_chunk_ends_at(end()); +-} +- +- +-#ifndef PRODUCT +-void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() { +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- _indexedFreeList[i].allocation_stats()->set_returned_bytes(0); +- } +-} +- +-size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() { +- size_t sum = 0; +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- sum += _indexedFreeList[i].allocation_stats()->returned_bytes(); +- } +- return sum; +-} +- +-size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const { +- size_t count = 0; +- for (size_t i = IndexSetStart; i < IndexSetSize; i++) { +- debug_only( +- ssize_t total_list_count = 0; +- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; +- fc = fc->next()) { +- total_list_count++; +- } +- assert(total_list_count == _indexedFreeList[i].count(), +- "Count in list is incorrect"); +- ) +- count += _indexedFreeList[i].count(); +- } +- return count; +-} +- +-size_t CompactibleFreeListSpace::totalCount() { +- size_t num = totalCountInIndexedFreeLists(); +- num += dictionary()->total_count(); +- if (_smallLinearAllocBlock._word_size != 0) { +- num++; +- } +- return num; +-} +-#endif +- +-bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const { +- FreeChunk* fc = (FreeChunk*) p; +- return fc->is_free(); +-} +- +-size_t CompactibleFreeListSpace::used() const { +- return capacity() - free(); +-} +- +-size_t CompactibleFreeListSpace::used_stable() const { +- return _used_stable; +-} +- +-void CompactibleFreeListSpace::recalculate_used_stable() { +- _used_stable = used(); +-} +- +-size_t CompactibleFreeListSpace::free() const { +- // "MT-safe, but not MT-precise"(TM), if you will: i.e. +- // if you do this while the structures are in flux you +- // may get an approximate answer only; for instance +- // because there is concurrent allocation either +- // directly by mutators or for promotion during a GC. +- // It's "MT-safe", however, in the sense that you are guaranteed +- // not to crash and burn, for instance, because of walking +- // pointers that could disappear as you were walking them. +- // The approximation is because the various components +- // that are read below are not read atomically (and +- // further the computation of totalSizeInIndexedFreeLists() +- // is itself a non-atomic computation. The normal use of +- // this is during a resize operation at the end of GC +- // and at that time you are guaranteed to get the +- // correct actual value. However, for instance, this is +- // also read completely asynchronously by the "perf-sampler" +- // that supports jvmstat, and you are apt to see the values +- // flicker in such cases. +- assert(_dictionary != NULL, "No _dictionary?"); +- return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) + +- totalSizeInIndexedFreeLists() + +- _smallLinearAllocBlock._word_size) * HeapWordSize; +-} +- +-size_t CompactibleFreeListSpace::max_alloc_in_words() const { +- assert(_dictionary != NULL, "No _dictionary?"); +- assert_locked(); +- size_t res = _dictionary->max_chunk_size(); +- res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, +- (size_t) SmallForLinearAlloc - 1)); +- // XXX the following could potentially be pretty slow; +- // should one, pessimistically for the rare cases when res +- // calculated above is less than IndexSetSize, +- // just return res calculated above? My reasoning was that +- // those cases will be so rare that the extra time spent doesn't +- // really matter.... +- // Note: do not change the loop test i >= res + IndexSetStride +- // to i > res below, because i is unsigned and res may be zero. +- for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride; +- i -= IndexSetStride) { +- if (_indexedFreeList[i].head() != NULL) { +- assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); +- return i; +- } +- } +- return res; +-} +- +-void LinearAllocBlock::print_on(outputStream* st) const { +- st->print_cr(" LinearAllocBlock: ptr = " PTR_FORMAT ", word_size = " SIZE_FORMAT +- ", refillsize = " SIZE_FORMAT ", allocation_size_limit = " SIZE_FORMAT, +- p2i(_ptr), _word_size, _refillSize, _allocation_size_limit); +-} +- +-void CompactibleFreeListSpace::print_on(outputStream* st) const { +- st->print_cr("COMPACTIBLE FREELIST SPACE"); +- st->print_cr(" Space:"); +- Space::print_on(st); +- +- st->print_cr("promoInfo:"); +- _promoInfo.print_on(st); +- +- st->print_cr("_smallLinearAllocBlock"); +- _smallLinearAllocBlock.print_on(st); +- +- // dump_memory_block(_smallLinearAllocBlock->_ptr, 128); +- +- st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy)); +-} +- +-void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) +-const { +- reportIndexedFreeListStatistics(st); +- st->print_cr("Layout of Indexed Freelists"); +- st->print_cr("---------------------------"); +- AdaptiveFreeList::print_labels_on(st, "size"); +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- _indexedFreeList[i].print_on(st); +- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; fc = fc->next()) { +- st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", +- p2i(fc), p2i((HeapWord*)fc + i), +- fc->cantCoalesce() ? "\t CC" : ""); +- } +- } +-} +- +-void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st) +-const { +- _promoInfo.print_on(st); +-} +- +-void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st) +-const { +- _dictionary->report_statistics(st); +- st->print_cr("Layout of Freelists in Tree"); +- st->print_cr("---------------------------"); +- _dictionary->print_free_lists(st); +-} +- +-class BlkPrintingClosure: public BlkClosure { +- const CMSCollector* _collector; +- const CompactibleFreeListSpace* _sp; +- const CMSBitMap* _live_bit_map; +- const bool _post_remark; +- outputStream* _st; +-public: +- BlkPrintingClosure(const CMSCollector* collector, +- const CompactibleFreeListSpace* sp, +- const CMSBitMap* live_bit_map, +- outputStream* st): +- _collector(collector), +- _sp(sp), +- _live_bit_map(live_bit_map), +- _post_remark(collector->abstract_state() > CMSCollector::FinalMarking), +- _st(st) { } +- size_t do_blk(HeapWord* addr); +-}; +- +-size_t BlkPrintingClosure::do_blk(HeapWord* addr) { +- size_t sz = _sp->block_size_no_stall(addr, _collector); +- assert(sz != 0, "Should always be able to compute a size"); +- if (_sp->block_is_obj(addr)) { +- const bool dead = _post_remark && !_live_bit_map->isMarked(addr); +- _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s", +- p2i(addr), +- dead ? "dead" : "live", +- sz, +- (!dead && CMSPrintObjectsInDump) ? ":" : "."); +- if (CMSPrintObjectsInDump && !dead) { +- oop(addr)->print_on(_st); +- _st->print_cr("--------------------------------------"); +- } +- } else { // free block +- _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s", +- p2i(addr), sz, CMSPrintChunksInDump ? ":" : "."); +- if (CMSPrintChunksInDump) { +- ((FreeChunk*)addr)->print_on(_st); +- _st->print_cr("--------------------------------------"); +- } +- } +- return sz; +-} +- +-void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st) { +- st->print_cr("========================="); +- st->print_cr("Block layout in CMS Heap:"); +- st->print_cr("========================="); +- BlkPrintingClosure bpcl(c, this, c->markBitMap(), st); +- blk_iterate(&bpcl); +- +- st->print_cr("======================================="); +- st->print_cr("Order & Layout of Promotion Info Blocks"); +- st->print_cr("======================================="); +- print_promo_info_blocks(st); +- +- st->print_cr("==========================="); +- st->print_cr("Order of Indexed Free Lists"); +- st->print_cr("========================="); +- print_indexed_free_lists(st); +- +- st->print_cr("================================="); +- st->print_cr("Order of Free Lists in Dictionary"); +- st->print_cr("================================="); +- print_dictionary_free_lists(st); +-} +- +- +-void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const { +- assert_lock_strong(&_freelistLock); +- Log(gc, freelist, stats) log; +- if (!log.is_debug()) { +- return; +- } +- log.debug("%s", title); +- +- LogStream out(log.debug()); +- _dictionary->report_statistics(&out); +- +- if (log.is_trace()) { +- LogStream trace_out(log.trace()); +- reportIndexedFreeListStatistics(&trace_out); +- size_t total_size = totalSizeInIndexedFreeLists() + +- _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); +- log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); +- } +-} +- +-void CompactibleFreeListSpace::reportIndexedFreeListStatistics(outputStream* st) const { +- assert_lock_strong(&_freelistLock); +- st->print_cr("Statistics for IndexedFreeLists:"); +- st->print_cr("--------------------------------"); +- size_t total_size = totalSizeInIndexedFreeLists(); +- size_t free_blocks = numFreeBlocksInIndexedFreeLists(); +- st->print_cr("Total Free Space: " SIZE_FORMAT, total_size); +- st->print_cr("Max Chunk Size: " SIZE_FORMAT, maxChunkSizeInIndexedFreeLists()); +- st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks); +- if (free_blocks != 0) { +- st->print_cr("Av. Block Size: " SIZE_FORMAT, total_size/free_blocks); +- } +-} +- +-size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { +- size_t res = 0; +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- debug_only( +- ssize_t recount = 0; +- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; +- fc = fc->next()) { +- recount += 1; +- } +- assert(recount == _indexedFreeList[i].count(), +- "Incorrect count in list"); +- ) +- res += _indexedFreeList[i].count(); +- } +- return res; +-} +- +-size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const { +- for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { +- if (_indexedFreeList[i].head() != NULL) { +- assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); +- return (size_t)i; +- } +- } +- return 0; +-} +- +-void CompactibleFreeListSpace::set_end(HeapWord* value) { +- HeapWord* prevEnd = end(); +- assert(prevEnd != value, "unnecessary set_end call"); +- assert(prevEnd == NULL || !BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), +- "New end is below unallocated block"); +- _end = value; +- if (prevEnd != NULL) { +- // Resize the underlying block offset table. +- _bt.resize(pointer_delta(value, bottom())); +- if (value <= prevEnd) { +- assert(!BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), +- "New end is below unallocated block"); +- } else { +- // Now, take this new chunk and add it to the free blocks. +- // Note that the BOT has not yet been updated for this block. +- size_t newFcSize = pointer_delta(value, prevEnd); +- // Add the block to the free lists, if possible coalescing it +- // with the last free block, and update the BOT and census data. +- addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); +- } +- } +-} +- +-class FreeListSpaceDCTOC : public FilteringDCTOC { +- CompactibleFreeListSpace* _cfls; +- CMSCollector* _collector; +- bool _parallel; +-protected: +- // Override. +-#define walk_mem_region_with_cl_DECL(ClosureType) \ +- virtual void walk_mem_region_with_cl(MemRegion mr, \ +- HeapWord* bottom, HeapWord* top, \ +- ClosureType* cl); \ +- void walk_mem_region_with_cl_par(MemRegion mr, \ +- HeapWord* bottom, HeapWord* top, \ +- ClosureType* cl); \ +- void walk_mem_region_with_cl_nopar(MemRegion mr, \ +- HeapWord* bottom, HeapWord* top, \ +- ClosureType* cl) +- walk_mem_region_with_cl_DECL(OopIterateClosure); +- walk_mem_region_with_cl_DECL(FilteringClosure); +- +-public: +- FreeListSpaceDCTOC(CompactibleFreeListSpace* sp, +- CMSCollector* collector, +- OopIterateClosure* cl, +- CardTable::PrecisionStyle precision, +- HeapWord* boundary, +- bool parallel) : +- FilteringDCTOC(sp, cl, precision, boundary), +- _cfls(sp), _collector(collector), _parallel(parallel) {} +-}; +- +-// We de-virtualize the block-related calls below, since we know that our +-// space is a CompactibleFreeListSpace. +- +-#define FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \ +-void FreeListSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \ +- HeapWord* bottom, \ +- HeapWord* top, \ +- ClosureType* cl) { \ +- if (_parallel) { \ +- walk_mem_region_with_cl_par(mr, bottom, top, cl); \ +- } else { \ +- walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \ +- } \ +-} \ +-void FreeListSpaceDCTOC::walk_mem_region_with_cl_par(MemRegion mr, \ +- HeapWord* bottom, \ +- HeapWord* top, \ +- ClosureType* cl) { \ +- /* Skip parts that are before "mr", in case "block_start" sent us \ +- back too far. */ \ +- HeapWord* mr_start = mr.start(); \ +- size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ +- HeapWord* next = bottom + bot_size; \ +- while (next < mr_start) { \ +- bottom = next; \ +- bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ +- next = bottom + bot_size; \ +- } \ +- \ +- while (bottom < top) { \ +- if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) && \ +- !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ +- oop(bottom)) && \ +- !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ +- size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ +- bottom += _cfls->adjustObjectSize(word_sz); \ +- } else { \ +- bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \ +- } \ +- } \ +-} \ +-void FreeListSpaceDCTOC::walk_mem_region_with_cl_nopar(MemRegion mr, \ +- HeapWord* bottom, \ +- HeapWord* top, \ +- ClosureType* cl) { \ +- /* Skip parts that are before "mr", in case "block_start" sent us \ +- back too far. */ \ +- HeapWord* mr_start = mr.start(); \ +- size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ +- HeapWord* next = bottom + bot_size; \ +- while (next < mr_start) { \ +- bottom = next; \ +- bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ +- next = bottom + bot_size; \ +- } \ +- \ +- while (bottom < top) { \ +- if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) && \ +- !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ +- oop(bottom)) && \ +- !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ +- size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ +- bottom += _cfls->adjustObjectSize(word_sz); \ +- } else { \ +- bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ +- } \ +- } \ +-} +- +-// (There are only two of these, rather than N, because the split is due +-// only to the introduction of the FilteringClosure, a local part of the +-// impl of this abstraction.) +-FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure) +-FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) +- +-DirtyCardToOopClosure* +-CompactibleFreeListSpace::new_dcto_cl(OopIterateClosure* cl, +- CardTable::PrecisionStyle precision, +- HeapWord* boundary, +- bool parallel) { +- return new FreeListSpaceDCTOC(this, _collector, cl, precision, boundary, parallel); +-} +- +- +-// Note on locking for the space iteration functions: +-// since the collector's iteration activities are concurrent with +-// allocation activities by mutators, absent a suitable mutual exclusion +-// mechanism the iterators may go awry. For instance a block being iterated +-// may suddenly be allocated or divided up and part of it allocated and +-// so on. +- +-// Apply the given closure to each block in the space. +-void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) { +- assert_lock_strong(freelistLock()); +- HeapWord *cur, *limit; +- for (cur = bottom(), limit = end(); cur < limit; +- cur += cl->do_blk_careful(cur)); +-} +- +-// Apply the given closure to each block in the space. +-void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) { +- assert_lock_strong(freelistLock()); +- HeapWord *cur, *limit; +- for (cur = bottom(), limit = end(); cur < limit; +- cur += cl->do_blk(cur)); +-} +- +-// Apply the given closure to each oop in the space. +-void CompactibleFreeListSpace::oop_iterate(OopIterateClosure* cl) { +- assert_lock_strong(freelistLock()); +- HeapWord *cur, *limit; +- size_t curSize; +- for (cur = bottom(), limit = end(); cur < limit; +- cur += curSize) { +- curSize = block_size(cur); +- if (block_is_obj(cur)) { +- oop(cur)->oop_iterate(cl); +- } +- } +-} +- +-// NOTE: In the following methods, in order to safely be able to +-// apply the closure to an object, we need to be sure that the +-// object has been initialized. We are guaranteed that an object +-// is initialized if we are holding the Heap_lock with the +-// world stopped. +-void CompactibleFreeListSpace::verify_objects_initialized() const { +- if (is_init_completed()) { +- assert_locked_or_safepoint(Heap_lock); +- if (Universe::is_fully_initialized()) { +- guarantee(SafepointSynchronize::is_at_safepoint(), +- "Required for objects to be initialized"); +- } +- } // else make a concession at vm start-up +-} +- +-// Apply the given closure to each object in the space +-void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { +- assert_lock_strong(freelistLock()); +- NOT_PRODUCT(verify_objects_initialized()); +- HeapWord *cur, *limit; +- size_t curSize; +- for (cur = bottom(), limit = end(); cur < limit; +- cur += curSize) { +- curSize = block_size(cur); +- if (block_is_obj(cur)) { +- blk->do_object(oop(cur)); +- } +- } +-} +- +-// Apply the given closure to each live object in the space +-// The usage of CompactibleFreeListSpace +-// by the ConcurrentMarkSweepGeneration for concurrent GC's allows +-// objects in the space with references to objects that are no longer +-// valid. For example, an object may reference another object +-// that has already been sweep up (collected). This method uses +-// obj_is_alive() to determine whether it is safe to apply the closure to +-// an object. See obj_is_alive() for details on how liveness of an +-// object is decided. +- +-void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { +- assert_lock_strong(freelistLock()); +- NOT_PRODUCT(verify_objects_initialized()); +- HeapWord *cur, *limit; +- size_t curSize; +- for (cur = bottom(), limit = end(); cur < limit; +- cur += curSize) { +- curSize = block_size(cur); +- if (block_is_obj(cur) && obj_is_alive(cur)) { +- blk->do_object(oop(cur)); +- } +- } +-} +- +-void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, +- UpwardsObjectClosure* cl) { +- assert_locked(freelistLock()); +- NOT_PRODUCT(verify_objects_initialized()); +- assert(!mr.is_empty(), "Should be non-empty"); +- // We use MemRegion(bottom(), end()) rather than used_region() below +- // because the two are not necessarily equal for some kinds of +- // spaces, in particular, certain kinds of free list spaces. +- // We could use the more complicated but more precise: +- // MemRegion(used_region().start(), align_up(used_region().end(), CardSize)) +- // but the slight imprecision seems acceptable in the assertion check. +- assert(MemRegion(bottom(), end()).contains(mr), +- "Should be within used space"); +- HeapWord* prev = cl->previous(); // max address from last time +- if (prev >= mr.end()) { // nothing to do +- return; +- } +- // This assert will not work when we go from cms space to perm +- // space, and use same closure. Easy fix deferred for later. XXX YSR +- // assert(prev == NULL || contains(prev), "Should be within space"); +- +- bool last_was_obj_array = false; +- HeapWord *blk_start_addr, *region_start_addr; +- if (prev > mr.start()) { +- region_start_addr = prev; +- blk_start_addr = prev; +- // The previous invocation may have pushed "prev" beyond the +- // last allocated block yet there may be still be blocks +- // in this region due to a particular coalescing policy. +- // Relax the assertion so that the case where the unallocated +- // block is maintained and "prev" is beyond the unallocated +- // block does not cause the assertion to fire. +- assert((BlockOffsetArrayUseUnallocatedBlock && +- (!is_in(prev))) || +- (blk_start_addr == block_start(region_start_addr)), "invariant"); +- } else { +- region_start_addr = mr.start(); +- blk_start_addr = block_start(region_start_addr); +- } +- HeapWord* region_end_addr = mr.end(); +- MemRegion derived_mr(region_start_addr, region_end_addr); +- while (blk_start_addr < region_end_addr) { +- const size_t size = block_size(blk_start_addr); +- if (block_is_obj(blk_start_addr)) { +- last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr); +- } else { +- last_was_obj_array = false; +- } +- blk_start_addr += size; +- } +- if (!last_was_obj_array) { +- assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()), +- "Should be within (closed) used space"); +- assert(blk_start_addr > prev, "Invariant"); +- cl->set_previous(blk_start_addr); // min address for next time +- } +-} +- +-// Callers of this iterator beware: The closure application should +-// be robust in the face of uninitialized objects and should (always) +-// return a correct size so that the next addr + size below gives us a +-// valid block boundary. [See for instance, +-// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful() +-// in ConcurrentMarkSweepGeneration.cpp.] +-HeapWord* +-CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr, +- ObjectClosureCareful* cl) { +- assert_lock_strong(freelistLock()); +- // Can't use used_region() below because it may not necessarily +- // be the same as [bottom(),end()); although we could +- // use [used_region().start(),align_up(used_region().end(),CardSize)), +- // that appears too cumbersome, so we just do the simpler check +- // in the assertion below. +- assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr), +- "mr should be non-empty and within used space"); +- HeapWord *addr, *end; +- size_t size; +- for (addr = block_start_careful(mr.start()), end = mr.end(); +- addr < end; addr += size) { +- FreeChunk* fc = (FreeChunk*)addr; +- if (fc->is_free()) { +- // Since we hold the free list lock, which protects direct +- // allocation in this generation by mutators, a free object +- // will remain free throughout this iteration code. +- size = fc->size(); +- } else { +- // Note that the object need not necessarily be initialized, +- // because (for instance) the free list lock does NOT protect +- // object initialization. The closure application below must +- // therefore be correct in the face of uninitialized objects. +- size = cl->do_object_careful_m(oop(addr), mr); +- if (size == 0) { +- // An unparsable object found. Signal early termination. +- return addr; +- } +- } +- } +- return NULL; +-} +- +- +-HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const { +- NOT_PRODUCT(verify_objects_initialized()); +- return _bt.block_start(p); +-} +- +-HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const { +- return _bt.block_start_careful(p); +-} +- +-size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { +- NOT_PRODUCT(verify_objects_initialized()); +- // This must be volatile, or else there is a danger that the compiler +- // will compile the code below into a sometimes-infinite loop, by keeping +- // the value read the first time in a register. +- while (true) { +- // We must do this until we get a consistent view of the object. +- if (FreeChunk::indicatesFreeChunk(p)) { +- volatile FreeChunk* fc = (volatile FreeChunk*)p; +- size_t res = fc->size(); +- +- // Bugfix for systems with weak memory model (PPC64/IA64). The +- // block's free bit was set and we have read the size of the +- // block. Acquire and check the free bit again. If the block is +- // still free, the read size is correct. +- OrderAccess::acquire(); +- +- // If the object is still a free chunk, return the size, else it +- // has been allocated so try again. +- if (FreeChunk::indicatesFreeChunk(p)) { +- assert(res != 0, "Block size should not be 0"); +- return res; +- } +- } else { +- // Ensure klass read before size. +- Klass* k = oop(p)->klass_or_null_acquire(); +- if (k != NULL) { +- assert(k->is_klass(), "Should really be klass oop."); +- oop o = (oop)p; +- assert(oopDesc::is_oop(o, true /* ignore mark word */), "Should be an oop."); +- +- size_t res = o->size_given_klass(k); +- res = adjustObjectSize(res); +- assert(res != 0, "Block size should not be 0"); +- return res; +- } +- } +- } +-} +- +-// TODO: Now that is_parsable is gone, we should combine these two functions. +-// A variant of the above that uses the Printezis bits for +-// unparsable but allocated objects. This avoids any possible +-// stalls waiting for mutators to initialize objects, and is +-// thus potentially faster than the variant above. However, +-// this variant may return a zero size for a block that is +-// under mutation and for which a consistent size cannot be +-// inferred without stalling; see CMSCollector::block_size_if_printezis_bits(). +-size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p, +- const CMSCollector* c) +-const { +- assert(MemRegion(bottom(), end()).contains(p), "p not in space"); +- // This must be volatile, or else there is a danger that the compiler +- // will compile the code below into a sometimes-infinite loop, by keeping +- // the value read the first time in a register. +- DEBUG_ONLY(uint loops = 0;) +- while (true) { +- // We must do this until we get a consistent view of the object. +- if (FreeChunk::indicatesFreeChunk(p)) { +- volatile FreeChunk* fc = (volatile FreeChunk*)p; +- size_t res = fc->size(); +- +- // Bugfix for systems with weak memory model (PPC64/IA64). The +- // free bit of the block was set and we have read the size of +- // the block. Acquire and check the free bit again. If the +- // block is still free, the read size is correct. +- OrderAccess::acquire(); +- +- if (FreeChunk::indicatesFreeChunk(p)) { +- assert(res != 0, "Block size should not be 0"); +- assert(loops == 0, "Should be 0"); +- return res; +- } +- } else { +- // Ensure klass read before size. +- Klass* k = oop(p)->klass_or_null_acquire(); +- if (k != NULL) { +- assert(k->is_klass(), "Should really be klass oop."); +- oop o = (oop)p; +- assert(oopDesc::is_oop(o), "Should be an oop"); +- +- size_t res = o->size_given_klass(k); +- res = adjustObjectSize(res); +- assert(res != 0, "Block size should not be 0"); +- return res; +- } else { +- // May return 0 if P-bits not present. +- return c->block_size_if_printezis_bits(p); +- } +- } +- assert(loops == 0, "Can loop at most once"); +- DEBUG_ONLY(loops++;) +- } +-} +- +-size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const { +- NOT_PRODUCT(verify_objects_initialized()); +- assert(MemRegion(bottom(), end()).contains(p), "p not in space"); +- FreeChunk* fc = (FreeChunk*)p; +- if (fc->is_free()) { +- return fc->size(); +- } else { +- // Ignore mark word because this may be a recently promoted +- // object whose mark word is used to chain together grey +- // objects (the last one would have a null value). +- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); +- return adjustObjectSize(oop(p)->size()); +- } +-} +- +-// This implementation assumes that the property of "being an object" is +-// stable. But being a free chunk may not be (because of parallel +-// promotion.) +-bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const { +- FreeChunk* fc = (FreeChunk*)p; +- assert(is_in_reserved(p), "Should be in space"); +- if (FreeChunk::indicatesFreeChunk(p)) return false; +- Klass* k = oop(p)->klass_or_null_acquire(); +- if (k != NULL) { +- // Ignore mark word because it may have been used to +- // chain together promoted objects (the last one +- // would have a null value). +- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); +- return true; +- } else { +- return false; // Was not an object at the start of collection. +- } +-} +- +-// Check if the object is alive. This fact is checked either by consulting +-// the main marking bitmap in the sweeping phase or, if it's a permanent +-// generation and we're not in the sweeping phase, by checking the +-// perm_gen_verify_bit_map where we store the "deadness" information if +-// we did not sweep the perm gen in the most recent previous GC cycle. +-bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const { +- assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(), +- "Else races are possible"); +- assert(block_is_obj(p), "The address should point to an object"); +- +- // If we're sweeping, we use object liveness information from the main bit map +- // for both perm gen and old gen. +- // We don't need to lock the bitmap (live_map or dead_map below), because +- // EITHER we are in the middle of the sweeping phase, and the +- // main marking bit map (live_map below) is locked, +- // OR we're in other phases and perm_gen_verify_bit_map (dead_map below) +- // is stable, because it's mutated only in the sweeping phase. +- // NOTE: This method is also used by jmap where, if class unloading is +- // off, the results can return "false" for legitimate perm objects, +- // when we are not in the midst of a sweeping phase, which can result +- // in jmap not reporting certain perm gen objects. This will be moot +- // if/when the perm gen goes away in the future. +- if (_collector->abstract_state() == CMSCollector::Sweeping) { +- CMSBitMap* live_map = _collector->markBitMap(); +- return live_map->par_isMarked((HeapWord*) p); +- } +- return true; +-} +- +-bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const { +- FreeChunk* fc = (FreeChunk*)p; +- assert(is_in_reserved(p), "Should be in space"); +- assert(_bt.block_start(p) == p, "Should be a block boundary"); +- if (!fc->is_free()) { +- // Ignore mark word because it may have been used to +- // chain together promoted objects (the last one +- // would have a null value). +- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); +- return true; +- } +- return false; +-} +- +-// "MT-safe but not guaranteed MT-precise" (TM); you may get an +-// approximate answer if you don't hold the freelistlock when you call this. +-size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const { +- size_t size = 0; +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- debug_only( +- // We may be calling here without the lock in which case we +- // won't do this modest sanity check. +- if (freelistLock()->owned_by_self()) { +- size_t total_list_size = 0; +- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; +- fc = fc->next()) { +- total_list_size += i; +- } +- assert(total_list_size == i * _indexedFreeList[i].count(), +- "Count in list is incorrect"); +- } +- ) +- size += i * _indexedFreeList[i].count(); +- } +- return size; +-} +- +-HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) { +- MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); +- return allocate(size); +-} +- +-HeapWord* +-CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) { +- return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size); +-} +- +-HeapWord* CompactibleFreeListSpace::allocate(size_t size) { +- assert_lock_strong(freelistLock()); +- HeapWord* res = NULL; +- assert(size == adjustObjectSize(size), +- "use adjustObjectSize() before calling into allocate()"); +- +- res = allocate_adaptive_freelists(size); +- +- if (res != NULL) { +- // check that res does lie in this space! +- assert(is_in_reserved(res), "Not in this space!"); +- assert(is_aligned((void*)res), "alignment check"); +- +- FreeChunk* fc = (FreeChunk*)res; +- fc->markNotFree(); +- assert(!fc->is_free(), "shouldn't be marked free"); +- assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized"); +- // Verify that the block offset table shows this to +- // be a single block, but not one which is unallocated. +- _bt.verify_single_block(res, size); +- _bt.verify_not_unallocated(res, size); +- // mangle a just allocated object with a distinct pattern. +- debug_only(fc->mangleAllocated(size)); +- } +- +- // During GC we do not need to recalculate the stable used value for +- // every allocation in old gen. It is done once at the end of GC instead +- // for performance reasons. +- if (!CMSHeap::heap()->is_gc_active()) { +- recalculate_used_stable(); +- } +- +- return res; +-} +- +-HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) { +- assert_lock_strong(freelistLock()); +- HeapWord* res = NULL; +- assert(size == adjustObjectSize(size), +- "use adjustObjectSize() before calling into allocate()"); +- +- // Strategy +- // if small +- // exact size from small object indexed list if small +- // small or large linear allocation block (linAB) as appropriate +- // take from lists of greater sized chunks +- // else +- // dictionary +- // small or large linear allocation block if it has the space +- // Try allocating exact size from indexTable first +- if (size < IndexSetSize) { +- res = (HeapWord*) getChunkFromIndexedFreeList(size); +- if(res != NULL) { +- assert(res != (HeapWord*)_indexedFreeList[size].head(), +- "Not removed from free list"); +- // no block offset table adjustment is necessary on blocks in +- // the indexed lists. +- +- // Try allocating from the small LinAB +- } else if (size < _smallLinearAllocBlock._allocation_size_limit && +- (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) { +- // if successful, the above also adjusts block offset table +- // Note that this call will refill the LinAB to +- // satisfy the request. This is different that +- // evm. +- // Don't record chunk off a LinAB? smallSplitBirth(size); +- } else { +- // Raid the exact free lists larger than size, even if they are not +- // overpopulated. +- res = (HeapWord*) getChunkFromGreater(size); +- } +- } else { +- // Big objects get allocated directly from the dictionary. +- res = (HeapWord*) getChunkFromDictionaryExact(size); +- if (res == NULL) { +- // Try hard not to fail since an allocation failure will likely +- // trigger a synchronous GC. Try to get the space from the +- // allocation blocks. +- res = getChunkFromSmallLinearAllocBlockRemainder(size); +- } +- } +- +- return res; +-} +- +-// A worst-case estimate of the space required (in HeapWords) to expand the heap +-// when promoting obj. +-size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const { +- // Depending on the object size, expansion may require refilling either a +- // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize +- // is added because the dictionary may over-allocate to avoid fragmentation. +- size_t space = obj_size; +- space += _promoInfo.refillSize() + 2 * MinChunkSize; +- return space; +-} +- +-FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) { +- FreeChunk* ret; +- +- assert(numWords >= MinChunkSize, "Size is less than minimum"); +- assert(linearAllocationWouldFail() || bestFitFirst(), +- "Should not be here"); +- +- size_t i; +- size_t currSize = numWords + MinChunkSize; +- assert(is_object_aligned(currSize), "currSize should be aligned"); +- for (i = currSize; i < IndexSetSize; i += IndexSetStride) { +- AdaptiveFreeList* fl = &_indexedFreeList[i]; +- if (fl->head()) { +- ret = getFromListGreater(fl, numWords); +- assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); +- return ret; +- } +- } +- +- currSize = MAX2((size_t)SmallForDictionary, +- (size_t)(numWords + MinChunkSize)); +- +- /* Try to get a chunk that satisfies request, while avoiding +- fragmentation that can't be handled. */ +- { +- ret = dictionary()->get_chunk(currSize); +- if (ret != NULL) { +- assert(ret->size() - numWords >= MinChunkSize, +- "Chunk is too small"); +- _bt.allocated((HeapWord*)ret, ret->size()); +- /* Carve returned chunk. */ +- (void) splitChunkAndReturnRemainder(ret, numWords); +- /* Label this as no longer a free chunk. */ +- assert(ret->is_free(), "This chunk should be free"); +- ret->link_prev(NULL); +- } +- assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); +- return ret; +- } +- ShouldNotReachHere(); +-} +- +-bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { +- assert(fc->size() < IndexSetSize, "Size of chunk is too large"); +- return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc); +-} +- +-bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { +- assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || +- (_smallLinearAllocBlock._word_size == fc->size()), +- "Linear allocation block shows incorrect size"); +- return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && +- (_smallLinearAllocBlock._word_size == fc->size())); +-} +- +-// Check if the purported free chunk is present either as a linear +-// allocation block, the size-indexed table of (smaller) free blocks, +-// or the larger free blocks kept in the binary tree dictionary. +-bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const { +- if (verify_chunk_is_linear_alloc_block(fc)) { +- return true; +- } else if (fc->size() < IndexSetSize) { +- return verifyChunkInIndexedFreeLists(fc); +- } else { +- return dictionary()->verify_chunk_in_free_list(fc); +- } +-} +- +-#ifndef PRODUCT +-void CompactibleFreeListSpace::assert_locked() const { +- CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock()); +-} +- +-void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const { +- CMSLockVerifier::assert_locked(lock); +-} +-#endif +- +-FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { +- // In the parallel case, the main thread holds the free list lock +- // on behalf the parallel threads. +- FreeChunk* fc; +- { +- // If GC is parallel, this might be called by several threads. +- // This should be rare enough that the locking overhead won't affect +- // the sequential code. +- MutexLockerEx x(parDictionaryAllocLock(), +- Mutex::_no_safepoint_check_flag); +- fc = getChunkFromDictionary(size); +- } +- if (fc != NULL) { +- fc->dontCoalesce(); +- assert(fc->is_free(), "Should be free, but not coalescable"); +- // Verify that the block offset table shows this to +- // be a single block, but not one which is unallocated. +- _bt.verify_single_block((HeapWord*)fc, fc->size()); +- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); +- } +- return fc; +-} +- +-oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) { +- assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); +- assert_locked(); +- +- // if we are tracking promotions, then first ensure space for +- // promotion (including spooling space for saving header if necessary). +- // then allocate and copy, then track promoted info if needed. +- // When tracking (see PromotionInfo::track()), the mark word may +- // be displaced and in this case restoration of the mark word +- // occurs in the (oop_since_save_marks_)iterate phase. +- if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) { +- return NULL; +- } +- // Call the allocate(size_t, bool) form directly to avoid the +- // additional call through the allocate(size_t) form. Having +- // the compile inline the call is problematic because allocate(size_t) +- // is a virtual method. +- HeapWord* res = allocate(adjustObjectSize(obj_size)); +- if (res != NULL) { +- Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size); +- // if we should be tracking promotions, do so. +- if (_promoInfo.tracking()) { +- _promoInfo.track((PromotedObject*)res); +- } +- } +- return oop(res); +-} +- +-HeapWord* +-CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) { +- assert_locked(); +- assert(size >= MinChunkSize, "minimum chunk size"); +- assert(size < _smallLinearAllocBlock._allocation_size_limit, +- "maximum from smallLinearAllocBlock"); +- return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size); +-} +- +-HeapWord* +-CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk, +- size_t size) { +- assert_locked(); +- assert(size >= MinChunkSize, "too small"); +- HeapWord* res = NULL; +- // Try to do linear allocation from blk, making sure that +- if (blk->_word_size == 0) { +- // We have probably been unable to fill this either in the prologue or +- // when it was exhausted at the last linear allocation. Bail out until +- // next time. +- assert(blk->_ptr == NULL, "consistency check"); +- return NULL; +- } +- assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check"); +- res = getChunkFromLinearAllocBlockRemainder(blk, size); +- if (res != NULL) return res; +- +- // about to exhaust this linear allocation block +- if (blk->_word_size == size) { // exactly satisfied +- res = blk->_ptr; +- _bt.allocated(res, blk->_word_size); +- } else if (size + MinChunkSize <= blk->_refillSize) { +- size_t sz = blk->_word_size; +- // Update _unallocated_block if the size is such that chunk would be +- // returned to the indexed free list. All other chunks in the indexed +- // free lists are allocated from the dictionary so that _unallocated_block +- // has already been adjusted for them. Do it here so that the cost +- // for all chunks added back to the indexed free lists. +- if (sz < SmallForDictionary) { +- _bt.allocated(blk->_ptr, sz); +- } +- // Return the chunk that isn't big enough, and then refill below. +- addChunkToFreeLists(blk->_ptr, sz); +- split_birth(sz); +- // Don't keep statistics on adding back chunk from a LinAB. +- } else { +- // A refilled block would not satisfy the request. +- return NULL; +- } +- +- blk->_ptr = NULL; blk->_word_size = 0; +- refillLinearAllocBlock(blk); +- assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, +- "block was replenished"); +- if (res != NULL) { +- split_birth(size); +- repairLinearAllocBlock(blk); +- } else if (blk->_ptr != NULL) { +- res = blk->_ptr; +- size_t blk_size = blk->_word_size; +- blk->_word_size -= size; +- blk->_ptr += size; +- split_birth(size); +- repairLinearAllocBlock(blk); +- // Update BOT last so that other (parallel) GC threads see a consistent +- // view of the BOT and free blocks. +- // Above must occur before BOT is updated below. +- OrderAccess::storestore(); +- _bt.split_block(res, blk_size, size); // adjust block offset table +- } +- return res; +-} +- +-HeapWord* CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder( +- LinearAllocBlock* blk, +- size_t size) { +- assert_locked(); +- assert(size >= MinChunkSize, "too small"); +- +- HeapWord* res = NULL; +- // This is the common case. Keep it simple. +- if (blk->_word_size >= size + MinChunkSize) { +- assert(blk->_ptr != NULL, "consistency check"); +- res = blk->_ptr; +- // Note that the BOT is up-to-date for the linAB before allocation. It +- // indicates the start of the linAB. The split_block() updates the +- // BOT for the linAB after the allocation (indicates the start of the +- // next chunk to be allocated). +- size_t blk_size = blk->_word_size; +- blk->_word_size -= size; +- blk->_ptr += size; +- split_birth(size); +- repairLinearAllocBlock(blk); +- // Update BOT last so that other (parallel) GC threads see a consistent +- // view of the BOT and free blocks. +- // Above must occur before BOT is updated below. +- OrderAccess::storestore(); +- _bt.split_block(res, blk_size, size); // adjust block offset table +- _bt.allocated(res, size); +- } +- return res; +-} +- +-FreeChunk* +-CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) { +- assert_locked(); +- assert(size < SmallForDictionary, "just checking"); +- FreeChunk* res; +- res = _indexedFreeList[size].get_chunk_at_head(); +- if (res == NULL) { +- res = getChunkFromIndexedFreeListHelper(size); +- } +- _bt.verify_not_unallocated((HeapWord*) res, size); +- assert(res == NULL || res->size() == size, "Incorrect block size"); +- return res; +-} +- +-FreeChunk* +-CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, +- bool replenish) { +- assert_locked(); +- FreeChunk* fc = NULL; +- if (size < SmallForDictionary) { +- assert(_indexedFreeList[size].head() == NULL || +- _indexedFreeList[size].surplus() <= 0, +- "List for this size should be empty or under populated"); +- // Try best fit in exact lists before replenishing the list +- if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) { +- // Replenish list. +- // +- // Things tried that failed. +- // Tried allocating out of the two LinAB's first before +- // replenishing lists. +- // Tried small linAB of size 256 (size in indexed list) +- // and replenishing indexed lists from the small linAB. +- // +- FreeChunk* newFc = NULL; +- const size_t replenish_size = CMSIndexedFreeListReplenish * size; +- if (replenish_size < SmallForDictionary) { +- // Do not replenish from an underpopulated size. +- if (_indexedFreeList[replenish_size].surplus() > 0 && +- _indexedFreeList[replenish_size].head() != NULL) { +- newFc = _indexedFreeList[replenish_size].get_chunk_at_head(); +- } else if (bestFitFirst()) { +- newFc = bestFitSmall(replenish_size); +- } +- } +- if (newFc == NULL && replenish_size > size) { +- assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant"); +- newFc = getChunkFromIndexedFreeListHelper(replenish_size, false); +- } +- // Note: The stats update re split-death of block obtained above +- // will be recorded below precisely when we know we are going to +- // be actually splitting it into more than one pieces below. +- if (newFc != NULL) { +- if (replenish || CMSReplenishIntermediate) { +- // Replenish this list and return one block to caller. +- size_t i; +- FreeChunk *curFc, *nextFc; +- size_t num_blk = newFc->size() / size; +- assert(num_blk >= 1, "Smaller than requested?"); +- assert(newFc->size() % size == 0, "Should be integral multiple of request"); +- if (num_blk > 1) { +- // we are sure we will be splitting the block just obtained +- // into multiple pieces; record the split-death of the original +- splitDeath(replenish_size); +- } +- // carve up and link blocks 0, ..., num_blk - 2 +- // The last chunk is not added to the lists but is returned as the +- // free chunk. +- for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), +- i = 0; +- i < (num_blk - 1); +- curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), +- i++) { +- curFc->set_size(size); +- // Don't record this as a return in order to try and +- // determine the "returns" from a GC. +- _bt.verify_not_unallocated((HeapWord*) fc, size); +- _indexedFreeList[size].return_chunk_at_tail(curFc, false); +- _bt.mark_block((HeapWord*)curFc, size); +- split_birth(size); +- // Don't record the initial population of the indexed list +- // as a split birth. +- } +- +- // check that the arithmetic was OK above +- assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, +- "inconsistency in carving newFc"); +- curFc->set_size(size); +- _bt.mark_block((HeapWord*)curFc, size); +- split_birth(size); +- fc = curFc; +- } else { +- // Return entire block to caller +- fc = newFc; +- } +- } +- } +- } else { +- // Get a free chunk from the free chunk dictionary to be returned to +- // replenish the indexed free list. +- fc = getChunkFromDictionaryExact(size); +- } +- // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk"); +- return fc; +-} +- +-FreeChunk* +-CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { +- assert_locked(); +- FreeChunk* fc = _dictionary->get_chunk(size); +- if (fc == NULL) { +- return NULL; +- } +- _bt.allocated((HeapWord*)fc, fc->size()); +- if (fc->size() >= size + MinChunkSize) { +- fc = splitChunkAndReturnRemainder(fc, size); +- } +- assert(fc->size() >= size, "chunk too small"); +- assert(fc->size() < size + MinChunkSize, "chunk too big"); +- _bt.verify_single_block((HeapWord*)fc, fc->size()); +- return fc; +-} +- +-FreeChunk* +-CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { +- assert_locked(); +- FreeChunk* fc = _dictionary->get_chunk(size); +- if (fc == NULL) { +- return fc; +- } +- _bt.allocated((HeapWord*)fc, fc->size()); +- if (fc->size() == size) { +- _bt.verify_single_block((HeapWord*)fc, size); +- return fc; +- } +- assert(fc->size() > size, "get_chunk() guarantee"); +- if (fc->size() < size + MinChunkSize) { +- // Return the chunk to the dictionary and go get a bigger one. +- returnChunkToDictionary(fc); +- fc = _dictionary->get_chunk(size + MinChunkSize); +- if (fc == NULL) { +- return NULL; +- } +- _bt.allocated((HeapWord*)fc, fc->size()); +- } +- assert(fc->size() >= size + MinChunkSize, "tautology"); +- fc = splitChunkAndReturnRemainder(fc, size); +- assert(fc->size() == size, "chunk is wrong size"); +- _bt.verify_single_block((HeapWord*)fc, size); +- return fc; +-} +- +-void +-CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { +- assert_locked(); +- +- size_t size = chunk->size(); +- _bt.verify_single_block((HeapWord*)chunk, size); +- // adjust _unallocated_block downward, as necessary +- _bt.freed((HeapWord*)chunk, size); +- _dictionary->return_chunk(chunk); +-#ifndef PRODUCT +- if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { +- TreeChunk >* tc = TreeChunk >::as_TreeChunk(chunk); +- TreeList >* tl = tc->list(); +- tl->verify_stats(); +- } +-#endif // PRODUCT +-} +- +-void +-CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { +- assert_locked(); +- size_t size = fc->size(); +- _bt.verify_single_block((HeapWord*) fc, size); +- _bt.verify_not_unallocated((HeapWord*) fc, size); +- _indexedFreeList[size].return_chunk_at_tail(fc); +-#ifndef PRODUCT +- if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { +- _indexedFreeList[size].verify_stats(); +- } +-#endif // PRODUCT +-} +- +-// Add chunk to end of last block -- if it's the largest +-// block -- and update BOT and census data. We would +-// of course have preferred to coalesce it with the +-// last block, but it's currently less expensive to find the +-// largest block than it is to find the last. +-void +-CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats( +- HeapWord* chunk, size_t size) { +- // check that the chunk does lie in this space! +- assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); +- // One of the parallel gc task threads may be here +- // whilst others are allocating. +- Mutex* lock = &_parDictionaryAllocLock; +- FreeChunk* ec; +- { +- MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); +- ec = dictionary()->find_largest_dict(); // get largest block +- if (ec != NULL && ec->end() == (uintptr_t*) chunk) { +- // It's a coterminal block - we can coalesce. +- size_t old_size = ec->size(); +- coalDeath(old_size); +- removeChunkFromDictionary(ec); +- size += old_size; +- } else { +- ec = (FreeChunk*)chunk; +- } +- } +- ec->set_size(size); +- debug_only(ec->mangleFreed(size)); +- if (size < SmallForDictionary) { +- lock = _indexedFreeListParLocks[size]; +- } +- MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); +- addChunkAndRepairOffsetTable((HeapWord*)ec, size, true); +- // record the birth under the lock since the recording involves +- // manipulation of the list on which the chunk lives and +- // if the chunk is allocated and is the last on the list, +- // the list can go away. +- coalBirth(size); +-} +- +-void +-CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk, +- size_t size) { +- // check that the chunk does lie in this space! +- assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); +- assert_locked(); +- _bt.verify_single_block(chunk, size); +- +- FreeChunk* fc = (FreeChunk*) chunk; +- fc->set_size(size); +- debug_only(fc->mangleFreed(size)); +- if (size < SmallForDictionary) { +- returnChunkToFreeList(fc); +- } else { +- returnChunkToDictionary(fc); +- } +-} +- +-void +-CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk, +- size_t size, bool coalesced) { +- assert_locked(); +- assert(chunk != NULL, "null chunk"); +- if (coalesced) { +- // repair BOT +- _bt.single_block(chunk, size); +- } +- addChunkToFreeLists(chunk, size); +-} +- +-// We _must_ find the purported chunk on our free lists; +-// we assert if we don't. +-void +-CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) { +- size_t size = fc->size(); +- assert_locked(); +- debug_only(verifyFreeLists()); +- if (size < SmallForDictionary) { +- removeChunkFromIndexedFreeList(fc); +- } else { +- removeChunkFromDictionary(fc); +- } +- _bt.verify_single_block((HeapWord*)fc, size); +- debug_only(verifyFreeLists()); +-} +- +-void +-CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) { +- size_t size = fc->size(); +- assert_locked(); +- assert(fc != NULL, "null chunk"); +- _bt.verify_single_block((HeapWord*)fc, size); +- _dictionary->remove_chunk(fc); +- // adjust _unallocated_block upward, as necessary +- _bt.allocated((HeapWord*)fc, size); +-} +- +-void +-CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) { +- assert_locked(); +- size_t size = fc->size(); +- _bt.verify_single_block((HeapWord*)fc, size); +- NOT_PRODUCT( +- if (FLSVerifyIndexTable) { +- verifyIndexedFreeList(size); +- } +- ) +- _indexedFreeList[size].remove_chunk(fc); +- NOT_PRODUCT( +- if (FLSVerifyIndexTable) { +- verifyIndexedFreeList(size); +- } +- ) +-} +- +-FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) { +- /* A hint is the next larger size that has a surplus. +- Start search at a size large enough to guarantee that +- the excess is >= MIN_CHUNK. */ +- size_t start = align_object_size(numWords + MinChunkSize); +- if (start < IndexSetSize) { +- AdaptiveFreeList* it = _indexedFreeList; +- size_t hint = _indexedFreeList[start].hint(); +- while (hint < IndexSetSize) { +- assert(is_object_aligned(hint), "hint should be aligned"); +- AdaptiveFreeList *fl = &_indexedFreeList[hint]; +- if (fl->surplus() > 0 && fl->head() != NULL) { +- // Found a list with surplus, reset original hint +- // and split out a free chunk which is returned. +- _indexedFreeList[start].set_hint(hint); +- FreeChunk* res = getFromListGreater(fl, numWords); +- assert(res == NULL || res->is_free(), +- "Should be returning a free chunk"); +- return res; +- } +- hint = fl->hint(); /* keep looking */ +- } +- /* None found. */ +- it[start].set_hint(IndexSetSize); +- } +- return NULL; +-} +- +-/* Requires fl->size >= numWords + MinChunkSize */ +-FreeChunk* CompactibleFreeListSpace::getFromListGreater(AdaptiveFreeList* fl, +- size_t numWords) { +- FreeChunk *curr = fl->head(); +- size_t oldNumWords = curr->size(); +- assert(numWords >= MinChunkSize, "Word size is too small"); +- assert(curr != NULL, "List is empty"); +- assert(oldNumWords >= numWords + MinChunkSize, +- "Size of chunks in the list is too small"); +- +- fl->remove_chunk(curr); +- // recorded indirectly by splitChunkAndReturnRemainder - +- // smallSplit(oldNumWords, numWords); +- FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); +- // Does anything have to be done for the remainder in terms of +- // fixing the card table? +- assert(new_chunk == NULL || new_chunk->is_free(), +- "Should be returning a free chunk"); +- return new_chunk; +-} +- +-FreeChunk* +-CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk, +- size_t new_size) { +- assert_locked(); +- size_t size = chunk->size(); +- assert(size > new_size, "Split from a smaller block?"); +- assert(is_aligned(chunk), "alignment problem"); +- assert(size == adjustObjectSize(size), "alignment problem"); +- size_t rem_sz = size - new_size; +- assert(rem_sz == adjustObjectSize(rem_sz), "alignment problem"); +- assert(rem_sz >= MinChunkSize, "Free chunk smaller than minimum"); +- FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); +- assert(is_aligned(ffc), "alignment problem"); +- ffc->set_size(rem_sz); +- ffc->link_next(NULL); +- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. +- // Above must occur before BOT is updated below. +- // adjust block offset table +- OrderAccess::storestore(); +- assert(chunk->is_free() && ffc->is_free(), "Error"); +- _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); +- if (rem_sz < SmallForDictionary) { +- // The freeList lock is held, but multiple GC task threads might be executing in parallel. +- bool is_par = Thread::current()->is_GC_task_thread(); +- if (is_par) _indexedFreeListParLocks[rem_sz]->lock(); +- returnChunkToFreeList(ffc); +- split(size, rem_sz); +- if (is_par) _indexedFreeListParLocks[rem_sz]->unlock(); +- } else { +- returnChunkToDictionary(ffc); +- split(size, rem_sz); +- } +- chunk->set_size(new_size); +- return chunk; +-} +- +-void +-CompactibleFreeListSpace::sweep_completed() { +- // Now that space is probably plentiful, refill linear +- // allocation blocks as needed. +- refillLinearAllocBlocksIfNeeded(); +-} +- +-void +-CompactibleFreeListSpace::gc_prologue() { +- assert_locked(); +- reportFreeListStatistics("Before GC:"); +- refillLinearAllocBlocksIfNeeded(); +-} +- +-void +-CompactibleFreeListSpace::gc_epilogue() { +- assert_locked(); +- assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); +- _promoInfo.stopTrackingPromotions(); +- repairLinearAllocationBlocks(); +- reportFreeListStatistics("After GC:"); +-} +- +-// Iteration support, mostly delegated from a CMS generation +- +-void CompactibleFreeListSpace::save_marks() { +- assert(Thread::current()->is_VM_thread(), +- "Global variable should only be set when single-threaded"); +- // Mark the "end" of the used space at the time of this call; +- // note, however, that promoted objects from this point +- // on are tracked in the _promoInfo below. +- set_saved_mark_word(unallocated_block()); +-#ifdef ASSERT +- // Check the sanity of save_marks() etc. +- MemRegion ur = used_region(); +- MemRegion urasm = used_region_at_save_marks(); +- assert(ur.contains(urasm), +- " Error at save_marks(): [" PTR_FORMAT "," PTR_FORMAT ")" +- " should contain [" PTR_FORMAT "," PTR_FORMAT ")", +- p2i(ur.start()), p2i(ur.end()), p2i(urasm.start()), p2i(urasm.end())); +-#endif +- // inform allocator that promotions should be tracked. +- assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); +- _promoInfo.startTrackingPromotions(); +-} +- +-bool CompactibleFreeListSpace::no_allocs_since_save_marks() { +- assert(_promoInfo.tracking(), "No preceding save_marks?"); +- return _promoInfo.noPromotions(); +-} +- +-bool CompactibleFreeListSpace::linearAllocationWouldFail() const { +- return _smallLinearAllocBlock._word_size == 0; +-} +- +-void CompactibleFreeListSpace::repairLinearAllocationBlocks() { +- // Fix up linear allocation blocks to look like free blocks +- repairLinearAllocBlock(&_smallLinearAllocBlock); +-} +- +-void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) { +- assert_locked(); +- if (blk->_ptr != NULL) { +- assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize, +- "Minimum block size requirement"); +- FreeChunk* fc = (FreeChunk*)(blk->_ptr); +- fc->set_size(blk->_word_size); +- fc->link_prev(NULL); // mark as free +- fc->dontCoalesce(); +- assert(fc->is_free(), "just marked it free"); +- assert(fc->cantCoalesce(), "just marked it uncoalescable"); +- } +-} +- +-void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() { +- assert_locked(); +- if (_smallLinearAllocBlock._ptr == NULL) { +- assert(_smallLinearAllocBlock._word_size == 0, +- "Size of linAB should be zero if the ptr is NULL"); +- // Reset the linAB refill and allocation size limit. +- _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc); +- } +- refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock); +-} +- +-void +-CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) { +- assert_locked(); +- assert((blk->_ptr == NULL && blk->_word_size == 0) || +- (blk->_ptr != NULL && blk->_word_size >= MinChunkSize), +- "blk invariant"); +- if (blk->_ptr == NULL) { +- refillLinearAllocBlock(blk); +- } +-} +- +-void +-CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) { +- assert_locked(); +- assert(blk->_word_size == 0 && blk->_ptr == NULL, +- "linear allocation block should be empty"); +- FreeChunk* fc; +- if (blk->_refillSize < SmallForDictionary && +- (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) { +- // A linAB's strategy might be to use small sizes to reduce +- // fragmentation but still get the benefits of allocation from a +- // linAB. +- } else { +- fc = getChunkFromDictionary(blk->_refillSize); +- } +- if (fc != NULL) { +- blk->_ptr = (HeapWord*)fc; +- blk->_word_size = fc->size(); +- fc->dontCoalesce(); // to prevent sweeper from sweeping us up +- } +-} +- +-// Support for compaction +-void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { +- scan_and_forward(this, cp, false); +- // of the free lists doesn't work after. +- // Prepare_for_compaction() uses the space between live objects +- // so that later phase can skip dead space quickly. So verification +- // of the free lists doesn't work after. +-} +- +-void CompactibleFreeListSpace::adjust_pointers() { +- // In other versions of adjust_pointers(), a bail out +- // based on the amount of live data in the generation +- // (i.e., if 0, bail out) may be used. +- // Cannot test used() == 0 here because the free lists have already +- // been mangled by the compaction. +- +- scan_and_adjust_pointers(this); +- // See note about verification in prepare_for_compaction(). +-} +- +-void CompactibleFreeListSpace::compact() { +- scan_and_compact(this, false); +-} +- +-// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2] +-// where fbs is free block sizes +-double CompactibleFreeListSpace::flsFrag() const { +- size_t itabFree = totalSizeInIndexedFreeLists(); +- double frag = 0.0; +- size_t i; +- +- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- double sz = i; +- frag += _indexedFreeList[i].count() * (sz * sz); +- } +- +- double totFree = itabFree + +- _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); +- if (totFree > 0) { +- frag = ((frag + _dictionary->sum_of_squared_block_sizes()) / +- (totFree * totFree)); +- frag = (double)1.0 - frag; +- } else { +- assert(frag == 0.0, "Follows from totFree == 0"); +- } +- return frag; +-} +- +-void CompactibleFreeListSpace::beginSweepFLCensus( +- float inter_sweep_current, +- float inter_sweep_estimate, +- float intra_sweep_estimate) { +- assert_locked(); +- size_t i; +- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- AdaptiveFreeList* fl = &_indexedFreeList[i]; +- log_trace(gc, freelist)("size[" SIZE_FORMAT "] : ", i); +- fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); +- fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); +- fl->set_before_sweep(fl->count()); +- fl->set_bfr_surp(fl->surplus()); +- } +- _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent, +- inter_sweep_current, +- inter_sweep_estimate, +- intra_sweep_estimate); +-} +- +-void CompactibleFreeListSpace::setFLSurplus() { +- assert_locked(); +- size_t i; +- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- AdaptiveFreeList *fl = &_indexedFreeList[i]; +- fl->set_surplus(fl->count() - +- (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); +- } +-} +- +-void CompactibleFreeListSpace::setFLHints() { +- assert_locked(); +- size_t i; +- size_t h = IndexSetSize; +- for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { +- AdaptiveFreeList *fl = &_indexedFreeList[i]; +- fl->set_hint(h); +- if (fl->surplus() > 0) { +- h = i; +- } +- } +-} +- +-void CompactibleFreeListSpace::clearFLCensus() { +- assert_locked(); +- size_t i; +- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- AdaptiveFreeList *fl = &_indexedFreeList[i]; +- fl->set_prev_sweep(fl->count()); +- fl->set_coal_births(0); +- fl->set_coal_deaths(0); +- fl->set_split_births(0); +- fl->set_split_deaths(0); +- } +-} +- +-void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { +- log_debug(gc, freelist)("CMS: Large block " PTR_FORMAT, p2i(dictionary()->find_largest_dict())); +- setFLSurplus(); +- setFLHints(); +- printFLCensus(sweep_count); +- clearFLCensus(); +- assert_locked(); +- _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); +-} +- +-bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { +- if (size < SmallForDictionary) { +- AdaptiveFreeList *fl = &_indexedFreeList[size]; +- return (fl->coal_desired() < 0) || +- ((int)fl->count() > fl->coal_desired()); +- } else { +- return dictionary()->coal_dict_over_populated(size); +- } +-} +- +-void CompactibleFreeListSpace::smallCoalBirth(size_t size) { +- assert(size < SmallForDictionary, "Size too large for indexed list"); +- AdaptiveFreeList *fl = &_indexedFreeList[size]; +- fl->increment_coal_births(); +- fl->increment_surplus(); +-} +- +-void CompactibleFreeListSpace::smallCoalDeath(size_t size) { +- assert(size < SmallForDictionary, "Size too large for indexed list"); +- AdaptiveFreeList *fl = &_indexedFreeList[size]; +- fl->increment_coal_deaths(); +- fl->decrement_surplus(); +-} +- +-void CompactibleFreeListSpace::coalBirth(size_t size) { +- if (size < SmallForDictionary) { +- smallCoalBirth(size); +- } else { +- dictionary()->dict_census_update(size, +- false /* split */, +- true /* birth */); +- } +-} +- +-void CompactibleFreeListSpace::coalDeath(size_t size) { +- if(size < SmallForDictionary) { +- smallCoalDeath(size); +- } else { +- dictionary()->dict_census_update(size, +- false /* split */, +- false /* birth */); +- } +-} +- +-void CompactibleFreeListSpace::smallSplitBirth(size_t size) { +- assert(size < SmallForDictionary, "Size too large for indexed list"); +- AdaptiveFreeList *fl = &_indexedFreeList[size]; +- fl->increment_split_births(); +- fl->increment_surplus(); +-} +- +-void CompactibleFreeListSpace::smallSplitDeath(size_t size) { +- assert(size < SmallForDictionary, "Size too large for indexed list"); +- AdaptiveFreeList *fl = &_indexedFreeList[size]; +- fl->increment_split_deaths(); +- fl->decrement_surplus(); +-} +- +-void CompactibleFreeListSpace::split_birth(size_t size) { +- if (size < SmallForDictionary) { +- smallSplitBirth(size); +- } else { +- dictionary()->dict_census_update(size, +- true /* split */, +- true /* birth */); +- } +-} +- +-void CompactibleFreeListSpace::splitDeath(size_t size) { +- if (size < SmallForDictionary) { +- smallSplitDeath(size); +- } else { +- dictionary()->dict_census_update(size, +- true /* split */, +- false /* birth */); +- } +-} +- +-void CompactibleFreeListSpace::split(size_t from, size_t to1) { +- size_t to2 = from - to1; +- splitDeath(from); +- split_birth(to1); +- split_birth(to2); +-} +- +-void CompactibleFreeListSpace::print() const { +- print_on(tty); +-} +- +-void CompactibleFreeListSpace::prepare_for_verify() { +- assert_locked(); +- repairLinearAllocationBlocks(); +- // Verify that the SpoolBlocks look like free blocks of +- // appropriate sizes... To be done ... +-} +- +-class VerifyAllBlksClosure: public BlkClosure { +- private: +- const CompactibleFreeListSpace* _sp; +- const MemRegion _span; +- HeapWord* _last_addr; +- size_t _last_size; +- bool _last_was_obj; +- bool _last_was_live; +- +- public: +- VerifyAllBlksClosure(const CompactibleFreeListSpace* sp, +- MemRegion span) : _sp(sp), _span(span), +- _last_addr(NULL), _last_size(0), +- _last_was_obj(false), _last_was_live(false) { } +- +- virtual size_t do_blk(HeapWord* addr) { +- size_t res; +- bool was_obj = false; +- bool was_live = false; +- if (_sp->block_is_obj(addr)) { +- was_obj = true; +- oop p = oop(addr); +- guarantee(oopDesc::is_oop(p), "Should be an oop"); +- res = _sp->adjustObjectSize(p->size()); +- if (_sp->obj_is_alive(addr)) { +- was_live = true; +- p->verify(); +- } +- } else { +- FreeChunk* fc = (FreeChunk*)addr; +- res = fc->size(); +- if (FLSVerifyLists && !fc->cantCoalesce()) { +- guarantee(_sp->verify_chunk_in_free_list(fc), +- "Chunk should be on a free list"); +- } +- } +- if (res == 0) { +- Log(gc, verify) log; +- log.error("Livelock: no rank reduction!"); +- log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n" +- " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n", +- p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false", +- p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false"); +- LogStream ls(log.error()); +- _sp->print_on(&ls); +- guarantee(false, "Verification failed."); +- } +- _last_addr = addr; +- _last_size = res; +- _last_was_obj = was_obj; +- _last_was_live = was_live; +- return res; +- } +-}; +- +-class VerifyAllOopsClosure: public BasicOopIterateClosure { +- private: +- const CMSCollector* _collector; +- const CompactibleFreeListSpace* _sp; +- const MemRegion _span; +- const bool _past_remark; +- const CMSBitMap* _bit_map; +- +- protected: +- void do_oop(void* p, oop obj) { +- if (_span.contains(obj)) { // the interior oop points into CMS heap +- if (!_span.contains(p)) { // reference from outside CMS heap +- // Should be a valid object; the first disjunct below allows +- // us to sidestep an assertion in block_is_obj() that insists +- // that p be in _sp. Note that several generations (and spaces) +- // are spanned by _span (CMS heap) above. +- guarantee(!_sp->is_in_reserved(obj) || +- _sp->block_is_obj((HeapWord*)obj), +- "Should be an object"); +- guarantee(oopDesc::is_oop(obj), "Should be an oop"); +- obj->verify(); +- if (_past_remark) { +- // Remark has been completed, the object should be marked +- _bit_map->isMarked((HeapWord*)obj); +- } +- } else { // reference within CMS heap +- if (_past_remark) { +- // Remark has been completed -- so the referent should have +- // been marked, if referring object is. +- if (_bit_map->isMarked(_collector->block_start(p))) { +- guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?"); +- } +- } +- } +- } else if (_sp->is_in_reserved(p)) { +- // the reference is from FLS, and points out of FLS +- guarantee(oopDesc::is_oop(obj), "Should be an oop"); +- obj->verify(); +- } +- } +- +- template void do_oop_work(T* p) { +- T heap_oop = RawAccess<>::oop_load(p); +- if (!CompressedOops::is_null(heap_oop)) { +- oop obj = CompressedOops::decode_not_null(heap_oop); +- do_oop(p, obj); +- } +- } +- +- public: +- VerifyAllOopsClosure(const CMSCollector* collector, +- const CompactibleFreeListSpace* sp, MemRegion span, +- bool past_remark, CMSBitMap* bit_map) : +- _collector(collector), _sp(sp), _span(span), +- _past_remark(past_remark), _bit_map(bit_map) { } +- +- virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); } +- virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); } +-}; +- +-void CompactibleFreeListSpace::verify() const { +- assert_lock_strong(&_freelistLock); +- verify_objects_initialized(); +- MemRegion span = _collector->_span; +- bool past_remark = (_collector->abstract_state() == +- CMSCollector::Sweeping); +- +- ResourceMark rm; +- HandleMark hm; +- +- // Check integrity of CFL data structures +- _promoInfo.verify(); +- _dictionary->verify(); +- if (FLSVerifyIndexTable) { +- verifyIndexedFreeLists(); +- } +- // Check integrity of all objects and free blocks in space +- { +- VerifyAllBlksClosure cl(this, span); +- ((CompactibleFreeListSpace*)this)->blk_iterate(&cl); // cast off const +- } +- // Check that all references in the heap to FLS +- // are to valid objects in FLS or that references in +- // FLS are to valid objects elsewhere in the heap +- if (FLSVerifyAllHeapReferences) +- { +- VerifyAllOopsClosure cl(_collector, this, span, past_remark, +- _collector->markBitMap()); +- +- // Iterate over all oops in the heap. +- CMSHeap::heap()->oop_iterate(&cl); +- } +- +- if (VerifyObjectStartArray) { +- // Verify the block offset table +- _bt.verify(); +- } +-} +- +-#ifndef PRODUCT +-void CompactibleFreeListSpace::verifyFreeLists() const { +- if (FLSVerifyLists) { +- _dictionary->verify(); +- verifyIndexedFreeLists(); +- } else { +- if (FLSVerifyDictionary) { +- _dictionary->verify(); +- } +- if (FLSVerifyIndexTable) { +- verifyIndexedFreeLists(); +- } +- } +-} +-#endif +- +-void CompactibleFreeListSpace::verifyIndexedFreeLists() const { +- size_t i = 0; +- for (; i < IndexSetStart; i++) { +- guarantee(_indexedFreeList[i].head() == NULL, "should be NULL"); +- } +- for (; i < IndexSetSize; i++) { +- verifyIndexedFreeList(i); +- } +-} +- +-void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { +- FreeChunk* fc = _indexedFreeList[size].head(); +- FreeChunk* tail = _indexedFreeList[size].tail(); +- size_t num = _indexedFreeList[size].count(); +- size_t n = 0; +- guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, +- "Slot should have been empty"); +- for (; fc != NULL; fc = fc->next(), n++) { +- guarantee(fc->size() == size, "Size inconsistency"); +- guarantee(fc->is_free(), "!free?"); +- guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); +- guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); +- } +- guarantee(n == num, "Incorrect count"); +-} +- +-#ifndef PRODUCT +-void CompactibleFreeListSpace::check_free_list_consistency() const { +- assert((TreeChunk >::min_size() <= IndexSetSize), +- "Some sizes can't be allocated without recourse to" +- " linear allocation buffers"); +- assert((TreeChunk >::min_size()*HeapWordSize == sizeof(TreeChunk >)), +- "else MIN_TREE_CHUNK_SIZE is wrong"); +- assert(IndexSetStart != 0, "IndexSetStart not initialized"); +- assert(IndexSetStride != 0, "IndexSetStride not initialized"); +-} +-#endif +- +-void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { +- assert_lock_strong(&_freelistLock); +- LogTarget(Debug, gc, freelist, census) log; +- if (!log.is_enabled()) { +- return; +- } +- AdaptiveFreeList total; +- log.print("end sweep# " SIZE_FORMAT, sweep_count); +- ResourceMark rm; +- LogStream ls(log); +- outputStream* out = &ls; +- AdaptiveFreeList::print_labels_on(out, "size"); +- size_t total_free = 0; +- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { +- const AdaptiveFreeList *fl = &_indexedFreeList[i]; +- total_free += fl->count() * fl->size(); +- if (i % (40*IndexSetStride) == 0) { +- AdaptiveFreeList::print_labels_on(out, "size"); +- } +- fl->print_on(out); +- total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); +- total.set_surplus( total.surplus() + fl->surplus() ); +- total.set_desired( total.desired() + fl->desired() ); +- total.set_prev_sweep( total.prev_sweep() + fl->prev_sweep() ); +- total.set_before_sweep(total.before_sweep() + fl->before_sweep()); +- total.set_count( total.count() + fl->count() ); +- total.set_coal_births( total.coal_births() + fl->coal_births() ); +- total.set_coal_deaths( total.coal_deaths() + fl->coal_deaths() ); +- total.set_split_births(total.split_births() + fl->split_births()); +- total.set_split_deaths(total.split_deaths() + fl->split_deaths()); +- } +- total.print_on(out, "TOTAL"); +- log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free); +- log.print("growth: %8.5f deficit: %8.5f", +- (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ +- (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), +- (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); +- _dictionary->print_dict_census(out); +-} +- +-/////////////////////////////////////////////////////////////////////////// +-// CompactibleFreeListSpaceLAB +-/////////////////////////////////////////////////////////////////////////// +- +-#define VECTOR_257(x) \ +- /* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \ +- { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ +- x } +- +-// Initialize with default setting for CMS, _not_ +-// generic OldPLABSize, whose static default is different; if overridden at the +-// command-line, this will get reinitialized via a call to +-// modify_initialization() below. +-AdaptiveWeightedAverage CompactibleFreeListSpaceLAB::_blocks_to_claim[] = +- VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CompactibleFreeListSpaceLAB::_default_dynamic_old_plab_size)); +-size_t CompactibleFreeListSpaceLAB::_global_num_blocks[] = VECTOR_257(0); +-uint CompactibleFreeListSpaceLAB::_global_num_workers[] = VECTOR_257(0); +- +-CompactibleFreeListSpaceLAB::CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls) : +- _cfls(cfls) +-{ +- assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above"); +- for (size_t i = CompactibleFreeListSpace::IndexSetStart; +- i < CompactibleFreeListSpace::IndexSetSize; +- i += CompactibleFreeListSpace::IndexSetStride) { +- _indexedFreeList[i].set_size(i); +- _num_blocks[i] = 0; +- } +-} +- +-static bool _CFLS_LAB_modified = false; +- +-void CompactibleFreeListSpaceLAB::modify_initialization(size_t n, unsigned wt) { +- assert(!_CFLS_LAB_modified, "Call only once"); +- _CFLS_LAB_modified = true; +- for (size_t i = CompactibleFreeListSpace::IndexSetStart; +- i < CompactibleFreeListSpace::IndexSetSize; +- i += CompactibleFreeListSpace::IndexSetStride) { +- _blocks_to_claim[i].modify(n, wt, true /* force */); +- } +-} +- +-HeapWord* CompactibleFreeListSpaceLAB::alloc(size_t word_sz) { +- FreeChunk* res; +- assert(word_sz == _cfls->adjustObjectSize(word_sz), "Error"); +- if (word_sz >= CompactibleFreeListSpace::IndexSetSize) { +- // This locking manages sync with other large object allocations. +- MutexLockerEx x(_cfls->parDictionaryAllocLock(), +- Mutex::_no_safepoint_check_flag); +- res = _cfls->getChunkFromDictionaryExact(word_sz); +- if (res == NULL) return NULL; +- } else { +- AdaptiveFreeList* fl = &_indexedFreeList[word_sz]; +- if (fl->count() == 0) { +- // Attempt to refill this local free list. +- get_from_global_pool(word_sz, fl); +- // If it didn't work, give up. +- if (fl->count() == 0) return NULL; +- } +- res = fl->get_chunk_at_head(); +- assert(res != NULL, "Why was count non-zero?"); +- } +- res->markNotFree(); +- assert(!res->is_free(), "shouldn't be marked free"); +- assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); +- // mangle a just allocated object with a distinct pattern. +- debug_only(res->mangleAllocated(word_sz)); +- return (HeapWord*)res; +-} +- +-// Get a chunk of blocks of the right size and update related +-// book-keeping stats +-void CompactibleFreeListSpaceLAB::get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl) { +- // Get the #blocks we want to claim +- size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); +- assert(n_blks > 0, "Error"); +- assert(ResizeOldPLAB || n_blks == OldPLABSize, "Error"); +- // In some cases, when the application has a phase change, +- // there may be a sudden and sharp shift in the object survival +- // profile, and updating the counts at the end of a scavenge +- // may not be quick enough, giving rise to large scavenge pauses +- // during these phase changes. It is beneficial to detect such +- // changes on-the-fly during a scavenge and avoid such a phase-change +- // pothole. The following code is a heuristic attempt to do that. +- // It is protected by a product flag until we have gained +- // enough experience with this heuristic and fine-tuned its behavior. +- // WARNING: This might increase fragmentation if we overreact to +- // small spikes, so some kind of historical smoothing based on +- // previous experience with the greater reactivity might be useful. +- // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by +- // default. +- if (ResizeOldPLAB && CMSOldPLABResizeQuicker) { +- // +- // On a 32-bit VM, the denominator can become zero because of integer overflow, +- // which is why there is a cast to double. +- // +- size_t multiple = (size_t) (_num_blocks[word_sz]/(((double)CMSOldPLABToleranceFactor)*CMSOldPLABNumRefills*n_blks)); +- n_blks += CMSOldPLABReactivityFactor*multiple*n_blks; +- n_blks = MIN2(n_blks, CMSOldPLABMax); +- } +- assert(n_blks > 0, "Error"); +- _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl); +- // Update stats table entry for this block size +- _num_blocks[word_sz] += fl->count(); +-} +- +-void CompactibleFreeListSpaceLAB::compute_desired_plab_size() { +- for (size_t i = CompactibleFreeListSpace::IndexSetStart; +- i < CompactibleFreeListSpace::IndexSetSize; +- i += CompactibleFreeListSpace::IndexSetStride) { +- assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0), +- "Counter inconsistency"); +- if (_global_num_workers[i] > 0) { +- // Need to smooth wrt historical average +- if (ResizeOldPLAB) { +- _blocks_to_claim[i].sample( +- MAX2(CMSOldPLABMin, +- MIN2(CMSOldPLABMax, +- _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills))); +- } +- // Reset counters for next round +- _global_num_workers[i] = 0; +- _global_num_blocks[i] = 0; +- log_trace(gc, plab)("[" SIZE_FORMAT "]: " SIZE_FORMAT, i, (size_t)_blocks_to_claim[i].average()); +- } +- } +-} +- +-// If this is changed in the future to allow parallel +-// access, one would need to take the FL locks and, +-// depending on how it is used, stagger access from +-// parallel threads to reduce contention. +-void CompactibleFreeListSpaceLAB::retire(int tid) { +- // We run this single threaded with the world stopped; +- // so no need for locks and such. +- NOT_PRODUCT(Thread* t = Thread::current();) +- assert(Thread::current()->is_VM_thread(), "Error"); +- for (size_t i = CompactibleFreeListSpace::IndexSetStart; +- i < CompactibleFreeListSpace::IndexSetSize; +- i += CompactibleFreeListSpace::IndexSetStride) { +- assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), +- "Can't retire more than what we obtained"); +- if (_num_blocks[i] > 0) { +- size_t num_retire = _indexedFreeList[i].count(); +- assert(_num_blocks[i] > num_retire, "Should have used at least one"); +- { +- // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], +- // Mutex::_no_safepoint_check_flag); +- +- // Update globals stats for num_blocks used +- _global_num_blocks[i] += (_num_blocks[i] - num_retire); +- _global_num_workers[i]++; +- assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); +- if (num_retire > 0) { +- _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); +- // Reset this list. +- _indexedFreeList[i] = AdaptiveFreeList(); +- _indexedFreeList[i].set_size(i); +- } +- } +- log_trace(gc, plab)("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT, +- tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); +- // Reset stats for next round +- _num_blocks[i] = 0; +- } +- } +-} +- +-// Used by par_get_chunk_of_blocks() for the chunks from the +-// indexed_free_lists. Looks for a chunk with size that is a multiple +-// of "word_sz" and if found, splits it into "word_sz" chunks and add +-// to the free list "fl". "n" is the maximum number of chunks to +-// be added to "fl". +-bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl) { +- +- // We'll try all multiples of word_sz in the indexed set, starting with +- // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, +- // then try getting a big chunk and splitting it. +- { +- bool found; +- int k; +- size_t cur_sz; +- for (k = 1, cur_sz = k * word_sz, found = false; +- (cur_sz < CompactibleFreeListSpace::IndexSetSize) && +- (CMSSplitIndexedFreeListBlocks || k <= 1); +- k++, cur_sz = k * word_sz) { +- AdaptiveFreeList fl_for_cur_sz; // Empty. +- fl_for_cur_sz.set_size(cur_sz); +- { +- MutexLockerEx x(_indexedFreeListParLocks[cur_sz], +- Mutex::_no_safepoint_check_flag); +- AdaptiveFreeList* gfl = &_indexedFreeList[cur_sz]; +- if (gfl->count() != 0) { +- // nn is the number of chunks of size cur_sz that +- // we'd need to split k-ways each, in order to create +- // "n" chunks of size word_sz each. +- const size_t nn = MAX2(n/k, (size_t)1); +- gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); +- found = true; +- if (k > 1) { +- // Update split death stats for the cur_sz-size blocks list: +- // we increment the split death count by the number of blocks +- // we just took from the cur_sz-size blocks list and which +- // we will be splitting below. +- ssize_t deaths = gfl->split_deaths() + +- fl_for_cur_sz.count(); +- gfl->set_split_deaths(deaths); +- } +- } +- } +- // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. +- if (found) { +- if (k == 1) { +- fl->prepend(&fl_for_cur_sz); +- } else { +- // Divide each block on fl_for_cur_sz up k ways. +- FreeChunk* fc; +- while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) { +- // Must do this in reverse order, so that anybody attempting to +- // access the main chunk sees it as a single free block until we +- // change it. +- size_t fc_size = fc->size(); +- assert(fc->is_free(), "Error"); +- for (int i = k-1; i >= 0; i--) { +- FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); +- assert((i != 0) || +- ((fc == ffc) && ffc->is_free() && +- (ffc->size() == k*word_sz) && (fc_size == word_sz)), +- "Counting error"); +- ffc->set_size(word_sz); +- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. +- ffc->link_next(NULL); +- // Above must occur before BOT is updated below. +- OrderAccess::storestore(); +- // splitting from the right, fc_size == i * word_sz +- _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); +- fc_size -= word_sz; +- assert(fc_size == i*word_sz, "Error"); +- _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); +- _bt.verify_single_block((HeapWord*)fc, fc_size); +- _bt.verify_single_block((HeapWord*)ffc, word_sz); +- // Push this on "fl". +- fl->return_chunk_at_head(ffc); +- } +- // TRAP +- assert(fl->tail()->next() == NULL, "List invariant."); +- } +- } +- // Update birth stats for this block size. +- size_t num = fl->count(); +- MutexLockerEx x(_indexedFreeListParLocks[word_sz], +- Mutex::_no_safepoint_check_flag); +- ssize_t births = _indexedFreeList[word_sz].split_births() + num; +- _indexedFreeList[word_sz].set_split_births(births); +- return true; +- } +- } +- return found; +- } +-} +- +-FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { +- +- FreeChunk* fc = NULL; +- FreeChunk* rem_fc = NULL; +- size_t rem; +- { +- MutexLockerEx x(parDictionaryAllocLock(), +- Mutex::_no_safepoint_check_flag); +- while (n > 0) { +- fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size())); +- if (fc != NULL) { +- break; +- } else { +- n--; +- } +- } +- if (fc == NULL) return NULL; +- // Otherwise, split up that block. +- assert((ssize_t)n >= 1, "Control point invariant"); +- assert(fc->is_free(), "Error: should be a free block"); +- _bt.verify_single_block((HeapWord*)fc, fc->size()); +- const size_t nn = fc->size() / word_sz; +- n = MIN2(nn, n); +- assert((ssize_t)n >= 1, "Control point invariant"); +- rem = fc->size() - n * word_sz; +- // If there is a remainder, and it's too small, allocate one fewer. +- if (rem > 0 && rem < MinChunkSize) { +- n--; rem += word_sz; +- } +- // Note that at this point we may have n == 0. +- assert((ssize_t)n >= 0, "Control point invariant"); +- +- // If n is 0, the chunk fc that was found is not large +- // enough to leave a viable remainder. We are unable to +- // allocate even one block. Return fc to the +- // dictionary and return, leaving "fl" empty. +- if (n == 0) { +- returnChunkToDictionary(fc); +- return NULL; +- } +- +- _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk +- dictionary()->dict_census_update(fc->size(), +- true /*split*/, +- false /*birth*/); +- +- // First return the remainder, if any. +- // Note that we hold the lock until we decide if we're going to give +- // back the remainder to the dictionary, since a concurrent allocation +- // may otherwise see the heap as empty. (We're willing to take that +- // hit if the block is a small block.) +- if (rem > 0) { +- size_t prefix_size = n * word_sz; +- rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); +- rem_fc->set_size(rem); +- rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. +- rem_fc->link_next(NULL); +- // Above must occur before BOT is updated below. +- assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); +- OrderAccess::storestore(); +- _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); +- assert(fc->is_free(), "Error"); +- fc->set_size(prefix_size); +- if (rem >= IndexSetSize) { +- returnChunkToDictionary(rem_fc); +- dictionary()->dict_census_update(rem, true /*split*/, true /*birth*/); +- rem_fc = NULL; +- } +- // Otherwise, return it to the small list below. +- } +- } +- if (rem_fc != NULL) { +- MutexLockerEx x(_indexedFreeListParLocks[rem], +- Mutex::_no_safepoint_check_flag); +- _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); +- _indexedFreeList[rem].return_chunk_at_head(rem_fc); +- smallSplitBirth(rem); +- } +- assert(n * word_sz == fc->size(), +- "Chunk size " SIZE_FORMAT " is not exactly splittable by " +- SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, +- fc->size(), n, word_sz); +- return fc; +-} +- +-void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList* fl) { +- +- FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); +- +- if (fc == NULL) { +- return; +- } +- +- size_t n = fc->size() / word_sz; +- +- assert((ssize_t)n > 0, "Consistency"); +- // Now do the splitting up. +- // Must do this in reverse order, so that anybody attempting to +- // access the main chunk sees it as a single free block until we +- // change it. +- size_t fc_size = n * word_sz; +- // All but first chunk in this loop +- for (ssize_t i = n-1; i > 0; i--) { +- FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); +- ffc->set_size(word_sz); +- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. +- ffc->link_next(NULL); +- // Above must occur before BOT is updated below. +- OrderAccess::storestore(); +- // splitting from the right, fc_size == (n - i + 1) * wordsize +- _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); +- fc_size -= word_sz; +- _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); +- _bt.verify_single_block((HeapWord*)ffc, ffc->size()); +- _bt.verify_single_block((HeapWord*)fc, fc_size); +- // Push this on "fl". +- fl->return_chunk_at_head(ffc); +- } +- // First chunk +- assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block"); +- // The blocks above should show their new sizes before the first block below +- fc->set_size(word_sz); +- fc->link_prev(NULL); // idempotent wrt free-ness, see assert above +- fc->link_next(NULL); +- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); +- _bt.verify_single_block((HeapWord*)fc, fc->size()); +- fl->return_chunk_at_head(fc); +- +- assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); +- { +- // Update the stats for this block size. +- MutexLockerEx x(_indexedFreeListParLocks[word_sz], +- Mutex::_no_safepoint_check_flag); +- const ssize_t births = _indexedFreeList[word_sz].split_births() + n; +- _indexedFreeList[word_sz].set_split_births(births); +- // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; +- // _indexedFreeList[word_sz].set_surplus(new_surplus); +- } +- +- // TRAP +- assert(fl->tail()->next() == NULL, "List invariant."); +-} +- +-void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { +- assert(fl->count() == 0, "Precondition."); +- assert(word_sz < CompactibleFreeListSpace::IndexSetSize, +- "Precondition"); +- +- if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { +- // Got it +- return; +- } +- +- // Otherwise, we'll split a block from the dictionary. +- par_get_chunk_of_blocks_dictionary(word_sz, n, fl); +-} +- +-const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { +- const size_t ergo_max = _old_gen->reserved().word_size() / (CardTable::card_size_in_words * BitsPerWord); +- return ergo_max; +-} +- +-// Set up the space's par_seq_tasks structure for work claiming +-// for parallel rescan. See CMSParRemarkTask where this is currently used. +-// XXX Need to suitably abstract and generalize this and the next +-// method into one. +-void +-CompactibleFreeListSpace:: +-initialize_sequential_subtasks_for_rescan(int n_threads) { +- // The "size" of each task is fixed according to rescan_task_size. +- assert(n_threads > 0, "Unexpected n_threads argument"); +- const size_t task_size = rescan_task_size(); +- size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size; +- assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect"); +- assert(n_tasks == 0 || +- ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) && +- (used_region().start() + n_tasks*task_size >= used_region().end())), +- "n_tasks calculation incorrect"); +- SequentialSubTasksDone* pst = conc_par_seq_tasks(); +- assert(!pst->valid(), "Clobbering existing data?"); +- // Sets the condition for completion of the subtask (how many threads +- // need to finish in order to be done). +- pst->set_n_threads(n_threads); +- pst->set_n_tasks((int)n_tasks); +-} +- +-// Set up the space's par_seq_tasks structure for work claiming +-// for parallel concurrent marking. See CMSConcMarkTask where this is currently used. +-void +-CompactibleFreeListSpace:: +-initialize_sequential_subtasks_for_marking(int n_threads, +- HeapWord* low) { +- // The "size" of each task is fixed according to rescan_task_size. +- assert(n_threads > 0, "Unexpected n_threads argument"); +- const size_t task_size = marking_task_size(); +- assert(task_size > CardTable::card_size_in_words && +- (task_size % CardTable::card_size_in_words == 0), +- "Otherwise arithmetic below would be incorrect"); +- MemRegion span = _old_gen->reserved(); +- if (low != NULL) { +- if (span.contains(low)) { +- // Align low down to a card boundary so that +- // we can use block_offset_careful() on span boundaries. +- HeapWord* aligned_low = align_down(low, CardTable::card_size); +- // Clip span prefix at aligned_low +- span = span.intersection(MemRegion(aligned_low, span.end())); +- } else if (low > span.end()) { +- span = MemRegion(low, low); // Null region +- } // else use entire span +- } +- assert(span.is_empty() || +- ((uintptr_t)span.start() % CardTable::card_size == 0), +- "span should start at a card boundary"); +- size_t n_tasks = (span.word_size() + task_size - 1)/task_size; +- assert((n_tasks == 0) == span.is_empty(), "Inconsistency"); +- assert(n_tasks == 0 || +- ((span.start() + (n_tasks - 1)*task_size < span.end()) && +- (span.start() + n_tasks*task_size >= span.end())), +- "n_tasks calculation incorrect"); +- SequentialSubTasksDone* pst = conc_par_seq_tasks(); +- assert(!pst->valid(), "Clobbering existing data?"); +- // Sets the condition for completion of the subtask (how many threads +- // need to finish in order to be done). +- pst->set_n_threads(n_threads); +- pst->set_n_tasks((int)n_tasks); +-} +diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp +deleted file mode 100644 +index 9fd2ea58320..00000000000 +--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp ++++ /dev/null +@@ -1,759 +0,0 @@ +-/* +- * Copyright (c) 2001, 2018, 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_CMS_COMPACTIBLEFREELISTSPACE_HPP +-#define SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP +- +-#include "gc/cms/adaptiveFreeList.hpp" +-#include "gc/cms/promotionInfo.hpp" +-#include "gc/shared/blockOffsetTable.hpp" +-#include "gc/shared/cardTable.hpp" +-#include "gc/shared/space.hpp" +-#include "logging/log.hpp" +-#include "memory/binaryTreeDictionary.hpp" +-#include "memory/freeList.hpp" +- +-// Classes in support of keeping track of promotions into a non-Contiguous +-// space, in this case a CompactibleFreeListSpace. +- +-// Forward declarations +-class CMSCollector; +-class CompactibleFreeListSpace; +-class ConcurrentMarkSweepGeneration; +-class BlkClosure; +-class BlkClosureCareful; +-class FreeChunk; +-class UpwardsObjectClosure; +-class ObjectClosureCareful; +-class Klass; +- +-class AFLBinaryTreeDictionary : public BinaryTreeDictionary > { +- public: +- AFLBinaryTreeDictionary(MemRegion mr) +- : BinaryTreeDictionary >(mr) {} +- +- // Find the list with size "size" in the binary tree and update +- // the statistics in the list according to "split" (chunk was +- // split or coalesce) and "birth" (chunk was added or removed). +- void dict_census_update(size_t size, bool split, bool birth); +- // Return true if the dictionary is overpopulated (more chunks of +- // this size than desired) for size "size". +- bool coal_dict_over_populated(size_t size); +- // Methods called at the beginning of a sweep to prepare the +- // statistics for the sweep. +- void begin_sweep_dict_census(double coalSurplusPercent, +- float inter_sweep_current, +- float inter_sweep_estimate, +- float intra_sweep_estimate); +- // Methods called after the end of a sweep to modify the +- // statistics for the sweep. +- void end_sweep_dict_census(double splitSurplusPercent); +- // Accessors for statistics +- void set_tree_surplus(double splitSurplusPercent); +- void set_tree_hints(void); +- // Reset statistics for all the lists in the tree. +- void clear_tree_census(void); +- // Print the statistics for all the lists in the tree. Also may +- // print out summaries. +- void print_dict_census(outputStream* st) const; +-}; +- +-class LinearAllocBlock { +- public: +- LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), +- _allocation_size_limit(0) {} +- void set(HeapWord* ptr, size_t word_size, size_t refill_size, +- size_t allocation_size_limit) { +- _ptr = ptr; +- _word_size = word_size; +- _refillSize = refill_size; +- _allocation_size_limit = allocation_size_limit; +- } +- HeapWord* _ptr; +- size_t _word_size; +- size_t _refillSize; +- size_t _allocation_size_limit; // Largest size that will be allocated +- +- void print_on(outputStream* st) const; +-}; +- +-// Concrete subclass of CompactibleSpace that implements +-// a free list space, such as used in the concurrent mark sweep +-// generation. +- +-class CompactibleFreeListSpace: public CompactibleSpace { +- friend class VMStructs; +- friend class ConcurrentMarkSweepGeneration; +- friend class CMSCollector; +- // Local alloc buffer for promotion into this space. +- friend class CompactibleFreeListSpaceLAB; +- // Allow scan_and_* functions to call (private) overrides of the auxiliary functions on this class +- template +- friend void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space); +- template +- friend void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run); +- template +- friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); +- template +- friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); +- +- // "Size" of chunks of work (executed during parallel remark phases +- // of CMS collection); this probably belongs in CMSCollector, although +- // it's cached here because it's used in +- // initialize_sequential_subtasks_for_rescan() which modifies +- // par_seq_tasks which also lives in Space. XXX +- const size_t _rescan_task_size; +- const size_t _marking_task_size; +- +- // Yet another sequential tasks done structure. This supports +- // CMS GC, where we have threads dynamically +- // claiming sub-tasks from a larger parallel task. +- SequentialSubTasksDone _conc_par_seq_tasks; +- +- BlockOffsetArrayNonContigSpace _bt; +- +- CMSCollector* _collector; +- ConcurrentMarkSweepGeneration* _old_gen; +- +- // Data structures for free blocks (used during allocation/sweeping) +- +- // Allocation is done linearly from two different blocks depending on +- // whether the request is small or large, in an effort to reduce +- // fragmentation. We assume that any locking for allocation is done +- // by the containing generation. Thus, none of the methods in this +- // space are re-entrant. +- enum SomeConstants { +- SmallForLinearAlloc = 16, // size < this then use _sLAB +- SmallForDictionary = 257, // size < this then use _indexedFreeList +- IndexSetSize = SmallForDictionary // keep this odd-sized +- }; +- static size_t IndexSetStart; +- static size_t IndexSetStride; +- static size_t _min_chunk_size_in_bytes; +- +- private: +- enum FitStrategyOptions { +- FreeBlockStrategyNone = 0, +- FreeBlockBestFitFirst +- }; +- +- PromotionInfo _promoInfo; +- +- // Helps to impose a global total order on freelistLock ranks; +- // assumes that CFLSpace's are allocated in global total order +- static int _lockRank; +- +- // A lock protecting the free lists and free blocks; +- // mutable because of ubiquity of locking even for otherwise const methods +- mutable Mutex _freelistLock; +- +- // Locking verifier convenience function +- void assert_locked() const PRODUCT_RETURN; +- void assert_locked(const Mutex* lock) const PRODUCT_RETURN; +- +- // Linear allocation blocks +- LinearAllocBlock _smallLinearAllocBlock; +- +- AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks +- +- // Indexed array for small size blocks +- AdaptiveFreeList _indexedFreeList[IndexSetSize]; +- +- // Allocation strategy +- bool _fitStrategy; // Use best fit strategy +- +- // This is an address close to the largest free chunk in the heap. +- // It is currently assumed to be at the end of the heap. Free +- // chunks with addresses greater than nearLargestChunk are coalesced +- // in an effort to maintain a large chunk at the end of the heap. +- HeapWord* _nearLargestChunk; +- +- // Used to keep track of limit of sweep for the space +- HeapWord* _sweep_limit; +- +- // Stable value of used(). +- size_t _used_stable; +- +- // Used to make the young collector update the mod union table +- MemRegionClosure* _preconsumptionDirtyCardClosure; +- +- // Support for compacting cms +- HeapWord* cross_threshold(HeapWord* start, HeapWord* end); +- HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); +- HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); +- +- // Initialization helpers. +- void initializeIndexedFreeListArray(); +- +- // Extra stuff to manage promotion parallelism. +- +- // A lock protecting the dictionary during par promotion allocation. +- mutable Mutex _parDictionaryAllocLock; +- Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } +- +- // Locks protecting the exact lists during par promotion allocation. +- Mutex* _indexedFreeListParLocks[IndexSetSize]; +- +- // Attempt to obtain up to "n" blocks of the size "word_sz" (which is +- // required to be smaller than "IndexSetSize".) If successful, +- // adds them to "fl", which is required to be an empty free list. +- // If the count of "fl" is negative, it's absolute value indicates a +- // number of free chunks that had been previously "borrowed" from global +- // list of size "word_sz", and must now be decremented. +- void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl); +- +- // Used by par_get_chunk_of_blocks() for the chunks from the +- // indexed_free_lists. +- bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl); +- +- // Used by par_get_chunk_of_blocks_dictionary() to get a chunk +- // evenly splittable into "n" "word_sz" chunks. Returns that +- // evenly splittable chunk. May split a larger chunk to get the +- // evenly splittable chunk. +- FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); +- +- // Used by par_get_chunk_of_blocks() for the chunks from the +- // dictionary. +- void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList* fl); +- +- // Allocation helper functions +- // Allocate using a strategy that takes from the indexed free lists +- // first. This allocation strategy assumes a companion sweeping +- // strategy that attempts to keep the needed number of chunks in each +- // indexed free lists. +- HeapWord* allocate_adaptive_freelists(size_t size); +- +- // Gets a chunk from the linear allocation block (LinAB). If there +- // is not enough space in the LinAB, refills it. +- HeapWord* getChunkFromLinearAllocBlock(LinearAllocBlock* blk, size_t size); +- HeapWord* getChunkFromSmallLinearAllocBlock(size_t size); +- // Get a chunk from the space remaining in the linear allocation block. Do +- // not attempt to refill if the space is not available, return NULL. Do the +- // repairs on the linear allocation block as appropriate. +- HeapWord* getChunkFromLinearAllocBlockRemainder(LinearAllocBlock* blk, size_t size); +- inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); +- +- // Helper function for getChunkFromIndexedFreeList. +- // Replenish the indexed free list for this "size". Do not take from an +- // underpopulated size. +- FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); +- +- // Get a chunk from the indexed free list. If the indexed free list +- // does not have a free chunk, try to replenish the indexed free list +- // then get the free chunk from the replenished indexed free list. +- inline FreeChunk* getChunkFromIndexedFreeList(size_t size); +- +- // The returned chunk may be larger than requested (or null). +- FreeChunk* getChunkFromDictionary(size_t size); +- // The returned chunk is the exact size requested (or null). +- FreeChunk* getChunkFromDictionaryExact(size_t size); +- +- // Find a chunk in the indexed free list that is the best +- // fit for size "numWords". +- FreeChunk* bestFitSmall(size_t numWords); +- // For free list "fl" of chunks of size > numWords, +- // remove a chunk, split off a chunk of size numWords +- // and return it. The split off remainder is returned to +- // the free lists. The old name for getFromListGreater +- // was lookInListGreater. +- FreeChunk* getFromListGreater(AdaptiveFreeList* fl, size_t numWords); +- // Get a chunk in the indexed free list or dictionary, +- // by considering a larger chunk and splitting it. +- FreeChunk* getChunkFromGreater(size_t numWords); +- // Verify that the given chunk is in the indexed free lists. +- bool verifyChunkInIndexedFreeLists(FreeChunk* fc) const; +- // Remove the specified chunk from the indexed free lists. +- void removeChunkFromIndexedFreeList(FreeChunk* fc); +- // Remove the specified chunk from the dictionary. +- void removeChunkFromDictionary(FreeChunk* fc); +- // Split a free chunk into a smaller free chunk of size "new_size". +- // Return the smaller free chunk and return the remainder to the +- // free lists. +- FreeChunk* splitChunkAndReturnRemainder(FreeChunk* chunk, size_t new_size); +- // Add a chunk to the free lists. +- void addChunkToFreeLists(HeapWord* chunk, size_t size); +- // Add a chunk to the free lists, preferring to suffix it +- // to the last free chunk at end of space if possible, and +- // updating the block census stats as well as block offset table. +- // Take any locks as appropriate if we are multithreaded. +- void addChunkToFreeListsAtEndRecordingStats(HeapWord* chunk, size_t size); +- // Add a free chunk to the indexed free lists. +- void returnChunkToFreeList(FreeChunk* chunk); +- // Add a free chunk to the dictionary. +- void returnChunkToDictionary(FreeChunk* chunk); +- +- // Functions for maintaining the linear allocation buffers (LinAB). +- // Repairing a linear allocation block refers to operations +- // performed on the remainder of a LinAB after an allocation +- // has been made from it. +- void repairLinearAllocationBlocks(); +- void repairLinearAllocBlock(LinearAllocBlock* blk); +- void refillLinearAllocBlock(LinearAllocBlock* blk); +- void refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk); +- void refillLinearAllocBlocksIfNeeded(); +- +- void verify_objects_initialized() const; +- +- // Statistics reporting helper functions +- void reportFreeListStatistics(const char* title) const; +- void reportIndexedFreeListStatistics(outputStream* st) const; +- size_t maxChunkSizeInIndexedFreeLists() const; +- size_t numFreeBlocksInIndexedFreeLists() const; +- // Accessor +- HeapWord* unallocated_block() const { +- if (BlockOffsetArrayUseUnallocatedBlock) { +- HeapWord* ub = _bt.unallocated_block(); +- assert(ub >= bottom() && +- ub <= end(), "space invariant"); +- return ub; +- } else { +- return end(); +- } +- } +- void freed(HeapWord* start, size_t size) { +- _bt.freed(start, size); +- } +- +- // Auxiliary functions for scan_and_{forward,adjust_pointers,compact} support. +- // See comments for CompactibleSpace for more information. +- inline HeapWord* scan_limit() const { +- return end(); +- } +- +- inline bool scanned_block_is_obj(const HeapWord* addr) const { +- return CompactibleFreeListSpace::block_is_obj(addr); // Avoid virtual call +- } +- +- inline size_t scanned_block_size(const HeapWord* addr) const { +- return CompactibleFreeListSpace::block_size(addr); // Avoid virtual call +- } +- +- inline size_t adjust_obj_size(size_t size) const { +- return adjustObjectSize(size); +- } +- +- inline size_t obj_size(const HeapWord* addr) const; +- +- protected: +- // Reset the indexed free list to its initial empty condition. +- void resetIndexedFreeListArray(); +- // Reset to an initial state with a single free block described +- // by the MemRegion parameter. +- void reset(MemRegion mr); +- // Return the total number of words in the indexed free lists. +- size_t totalSizeInIndexedFreeLists() const; +- +- public: +- // Constructor +- CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); +- // Accessors +- bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } +- AFLBinaryTreeDictionary* dictionary() const { return _dictionary; } +- HeapWord* nearLargestChunk() const { return _nearLargestChunk; } +- void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; } +- +- // Set CMS global values. +- static void set_cms_values(); +- +- // Return the free chunk at the end of the space. If no such +- // chunk exists, return NULL. +- FreeChunk* find_chunk_at_end(); +- +- void set_collector(CMSCollector* collector) { _collector = collector; } +- +- // Support for parallelization of rescan and marking. +- const size_t rescan_task_size() const { return _rescan_task_size; } +- const size_t marking_task_size() const { return _marking_task_size; } +- // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. +- const size_t max_flag_size_for_task_size() const; +- SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } +- void initialize_sequential_subtasks_for_rescan(int n_threads); +- void initialize_sequential_subtasks_for_marking(int n_threads, +- HeapWord* low = NULL); +- +- virtual MemRegionClosure* preconsumptionDirtyCardClosure() const { +- return _preconsumptionDirtyCardClosure; +- } +- +- void setPreconsumptionDirtyCardClosure(MemRegionClosure* cl) { +- _preconsumptionDirtyCardClosure = cl; +- } +- +- // Space enquiries +- size_t used() const; +- size_t free() const; +- size_t max_alloc_in_words() const; +- // XXX: should have a less conservative used_region() than that of +- // Space; we could consider keeping track of highest allocated +- // address and correcting that at each sweep, as the sweeper +- // goes through the entire allocated part of the generation. We +- // could also use that information to keep the sweeper from +- // sweeping more than is necessary. The allocator and sweeper will +- // of course need to synchronize on this, since the sweeper will +- // try to bump down the address and the allocator will try to bump it up. +- // For now, however, we'll just use the default used_region() +- // which overestimates the region by returning the entire +- // committed region (this is safe, but inefficient). +- +- // Returns monotonically increasing stable used space bytes for CMS. +- // This is required for jstat and other memory monitoring tools +- // that might otherwise see inconsistent used space values during a garbage +- // collection, promotion or allocation into compactibleFreeListSpace. +- // The value returned by this function might be smaller than the +- // actual value. +- size_t used_stable() const; +- // Recalculate and cache the current stable used() value. Only to be called +- // in places where we can be sure that the result is stable. +- void recalculate_used_stable(); +- +- // Returns a subregion of the space containing all the objects in +- // the space. +- MemRegion used_region() const { +- return MemRegion(bottom(), +- BlockOffsetArrayUseUnallocatedBlock ? +- unallocated_block() : end()); +- } +- +- virtual bool is_free_block(const HeapWord* p) const; +- +- // Resizing support +- void set_end(HeapWord* value); // override +- +- // Never mangle CompactibleFreeListSpace +- void mangle_unused_area() {} +- void mangle_unused_area_complete() {} +- +- // Mutual exclusion support +- Mutex* freelistLock() const { return &_freelistLock; } +- +- // Iteration support +- void oop_iterate(OopIterateClosure* cl); +- +- void object_iterate(ObjectClosure* blk); +- // Apply the closure to each object in the space whose references +- // point to objects in the heap. The usage of CompactibleFreeListSpace +- // by the ConcurrentMarkSweepGeneration for concurrent GC's allows +- // objects in the space with references to objects that are no longer +- // valid. For example, an object may reference another object +- // that has already been sweep up (collected). This method uses +- // obj_is_alive() to determine whether it is safe to iterate of +- // an object. +- void safe_object_iterate(ObjectClosure* blk); +- +- // Iterate over all objects that intersect with mr, calling "cl->do_object" +- // on each. There is an exception to this: if this closure has already +- // been invoked on an object, it may skip such objects in some cases. This is +- // Most likely to happen in an "upwards" (ascending address) iteration of +- // MemRegions. +- void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); +- +- // Requires that "mr" be entirely within the space. +- // Apply "cl->do_object" to all objects that intersect with "mr". +- // If the iteration encounters an unparseable portion of the region, +- // terminate the iteration and return the address of the start of the +- // subregion that isn't done. Return of "NULL" indicates that the +- // iteration completed. +- HeapWord* object_iterate_careful_m(MemRegion mr, +- ObjectClosureCareful* cl); +- +- // Override: provides a DCTO_CL specific to this kind of space. +- DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, +- CardTable::PrecisionStyle precision, +- HeapWord* boundary, +- bool parallel); +- +- void blk_iterate(BlkClosure* cl); +- void blk_iterate_careful(BlkClosureCareful* cl); +- HeapWord* block_start_const(const void* p) const; +- HeapWord* block_start_careful(const void* p) const; +- size_t block_size(const HeapWord* p) const; +- size_t block_size_no_stall(HeapWord* p, const CMSCollector* c) const; +- bool block_is_obj(const HeapWord* p) const; +- bool obj_is_alive(const HeapWord* p) const; +- size_t block_size_nopar(const HeapWord* p) const; +- bool block_is_obj_nopar(const HeapWord* p) const; +- +- // Iteration support for promotion +- void save_marks(); +- bool no_allocs_since_save_marks(); +- +- // Iteration support for sweeping +- void save_sweep_limit() { +- _sweep_limit = BlockOffsetArrayUseUnallocatedBlock ? +- unallocated_block() : end(); +- log_develop_trace(gc, sweep)(">>>>> Saving sweep limit " PTR_FORMAT +- " for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<", +- p2i(_sweep_limit), p2i(bottom()), p2i(end())); +- } +- NOT_PRODUCT( +- void clear_sweep_limit() { _sweep_limit = NULL; } +- ) +- HeapWord* sweep_limit() { return _sweep_limit; } +- +- // Apply "blk->do_oop" to the addresses of all reference fields in objects +- // promoted into this generation since the most recent save_marks() call. +- // Fields in objects allocated by applications of the closure +- // *are* included in the iteration. Thus, when the iteration completes +- // there should be no further such objects remaining. +- template +- void oop_since_save_marks_iterate(OopClosureType* blk); +- +- // Allocation support +- HeapWord* allocate(size_t size); +- HeapWord* par_allocate(size_t size); +- +- oop promote(oop obj, size_t obj_size); +- void gc_prologue(); +- void gc_epilogue(); +- +- // This call is used by a containing CMS generation / collector +- // to inform the CFLS space that a sweep has been completed +- // and that the space can do any related house-keeping functions. +- void sweep_completed(); +- +- // For an object in this space, the mark-word's two +- // LSB's having the value [11] indicates that it has been +- // promoted since the most recent call to save_marks() on +- // this generation and has not subsequently been iterated +- // over (using oop_since_save_marks_iterate() above). +- // This property holds only for single-threaded collections, +- // and is typically used for Cheney scans; for MT scavenges, +- // the property holds for all objects promoted during that +- // scavenge for the duration of the scavenge and is used +- // by card-scanning to avoid scanning objects (being) promoted +- // during that scavenge. +- bool obj_allocated_since_save_marks(const oop obj) const { +- assert(is_in_reserved(obj), "Wrong space?"); +- return ((PromotedObject*)obj)->hasPromotedMark(); +- } +- +- // A worst-case estimate of the space required (in HeapWords) to expand the +- // heap when promoting an obj of size obj_size. +- size_t expansionSpaceRequired(size_t obj_size) const; +- +- FreeChunk* allocateScratch(size_t size); +- +- // Returns true if either the small or large linear allocation buffer is empty. +- bool linearAllocationWouldFail() const; +- +- // Adjust the chunk for the minimum size. This version is called in +- // most cases in CompactibleFreeListSpace methods. +- inline static size_t adjustObjectSize(size_t size) { +- return align_object_size(MAX2(size, (size_t)MinChunkSize)); +- } +- // This is a virtual version of adjustObjectSize() that is called +- // only occasionally when the compaction space changes and the type +- // of the new compaction space is is only known to be CompactibleSpace. +- size_t adjust_object_size_v(size_t size) const { +- return adjustObjectSize(size); +- } +- // Minimum size of a free block. +- virtual size_t minimum_free_block_size() const { return MinChunkSize; } +- void removeFreeChunkFromFreeLists(FreeChunk* chunk); +- void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, +- bool coalesced); +- +- // Support for compaction. +- void prepare_for_compaction(CompactPoint* cp); +- void adjust_pointers(); +- void compact(); +- // Reset the space to reflect the fact that a compaction of the +- // space has been done. +- virtual void reset_after_compaction(); +- +- // Debugging support. +- void print() const; +- void print_on(outputStream* st) const; +- void prepare_for_verify(); +- void verify() const; +- void verifyFreeLists() const PRODUCT_RETURN; +- void verifyIndexedFreeLists() const; +- void verifyIndexedFreeList(size_t size) const; +- // Verify that the given chunk is in the free lists: +- // i.e. either the binary tree dictionary, the indexed free lists +- // or the linear allocation block. +- bool verify_chunk_in_free_list(FreeChunk* fc) const; +- // Verify that the given chunk is the linear allocation block. +- bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; +- // Do some basic checks on the the free lists. +- void check_free_list_consistency() const PRODUCT_RETURN; +- +- // Printing support +- void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); +- void print_indexed_free_lists(outputStream* st) const; +- void print_dictionary_free_lists(outputStream* st) const; +- void print_promo_info_blocks(outputStream* st) const; +- +- NOT_PRODUCT ( +- void initializeIndexedFreeListArrayReturnedBytes(); +- size_t sumIndexedFreeListArrayReturnedBytes(); +- // Return the total number of chunks in the indexed free lists. +- size_t totalCountInIndexedFreeLists() const; +- // Return the total number of chunks in the space. +- size_t totalCount(); +- ) +- +- // The census consists of counts of the quantities such as +- // the current count of the free chunks, number of chunks +- // created as a result of the split of a larger chunk or +- // coalescing of smaller chucks, etc. The counts in the +- // census is used to make decisions on splitting and +- // coalescing of chunks during the sweep of garbage. +- +- // Print the statistics for the free lists. +- void printFLCensus(size_t sweep_count) const; +- +- // Statistics functions +- // Initialize census for lists before the sweep. +- void beginSweepFLCensus(float inter_sweep_current, +- float inter_sweep_estimate, +- float intra_sweep_estimate); +- // Set the surplus for each of the free lists. +- void setFLSurplus(); +- // Set the hint for each of the free lists. +- void setFLHints(); +- // Clear the census for each of the free lists. +- void clearFLCensus(); +- // Perform functions for the census after the end of the sweep. +- void endSweepFLCensus(size_t sweep_count); +- // Return true if the count of free chunks is greater +- // than the desired number of free chunks. +- bool coalOverPopulated(size_t size); +- +-// Record (for each size): +-// +-// split-births = #chunks added due to splits in (prev-sweep-end, +-// this-sweep-start) +-// split-deaths = #chunks removed for splits in (prev-sweep-end, +-// this-sweep-start) +-// num-curr = #chunks at start of this sweep +-// num-prev = #chunks at end of previous sweep +-// +-// The above are quantities that are measured. Now define: +-// +-// num-desired := num-prev + split-births - split-deaths - num-curr +-// +-// Roughly, num-prev + split-births is the supply, +-// split-deaths is demand due to other sizes +-// and num-curr is what we have left. +-// +-// Thus, num-desired is roughly speaking the "legitimate demand" +-// for blocks of this size and what we are striving to reach at the +-// end of the current sweep. +-// +-// For a given list, let num-len be its current population. +-// Define, for a free list of a given size: +-// +-// coal-overpopulated := num-len >= num-desired * coal-surplus +-// (coal-surplus is set to 1.05, i.e. we allow a little slop when +-// coalescing -- we do not coalesce unless we think that the current +-// supply has exceeded the estimated demand by more than 5%). +-// +-// For the set of sizes in the binary tree, which is neither dense nor +-// closed, it may be the case that for a particular size we have never +-// had, or do not now have, or did not have at the previous sweep, +-// chunks of that size. We need to extend the definition of +-// coal-overpopulated to such sizes as well: +-// +-// For a chunk in/not in the binary tree, extend coal-overpopulated +-// defined above to include all sizes as follows: +-// +-// . a size that is non-existent is coal-overpopulated +-// . a size that has a num-desired <= 0 as defined above is +-// coal-overpopulated. +-// +-// Also define, for a chunk heap-offset C and mountain heap-offset M: +-// +-// close-to-mountain := C >= 0.99 * M +-// +-// Now, the coalescing strategy is: +-// +-// Coalesce left-hand chunk with right-hand chunk if and +-// only if: +-// +-// EITHER +-// . left-hand chunk is of a size that is coal-overpopulated +-// OR +-// . right-hand chunk is close-to-mountain +- void smallCoalBirth(size_t size); +- void smallCoalDeath(size_t size); +- void coalBirth(size_t size); +- void coalDeath(size_t size); +- void smallSplitBirth(size_t size); +- void smallSplitDeath(size_t size); +- void split_birth(size_t size); +- void splitDeath(size_t size); +- void split(size_t from, size_t to1); +- +- double flsFrag() const; +-}; +- +-// A parallel-GC-thread-local allocation buffer for allocation into a +-// CompactibleFreeListSpace. +-class CompactibleFreeListSpaceLAB : public CHeapObj { +- // The space that this buffer allocates into. +- CompactibleFreeListSpace* _cfls; +- +- // Our local free lists. +- AdaptiveFreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; +- +- // Initialized from a command-line arg. +- +- // Allocation statistics in support of dynamic adjustment of +- // #blocks to claim per get_from_global_pool() call below. +- static AdaptiveWeightedAverage +- _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; +- static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; +- static uint _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; +- size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; +- +- // Internal work method +- void get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl); +- +-public: +- static const int _default_dynamic_old_plab_size = 16; +- static const int _default_static_old_plab_size = 50; +- +- CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls); +- +- // Allocate and return a block of the given size, or else return NULL. +- HeapWord* alloc(size_t word_sz); +- +- // Return any unused portions of the buffer to the global pool. +- void retire(int tid); +- +- // Dynamic OldPLABSize sizing +- static void compute_desired_plab_size(); +- // When the settings are modified from default static initialization +- static void modify_initialization(size_t n, unsigned wt); +-}; +- +-size_t PromotionInfo::refillSize() const { +- const size_t CMSSpoolBlockSize = 256; +- const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) +- * CMSSpoolBlockSize); +- return CompactibleFreeListSpace::adjustObjectSize(sz); +-} +- +-#endif // SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch b/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch new file mode 100644 index 000000000000..077e41ca256c --- /dev/null +++ b/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch @@ -0,0 +1,183 @@ +From 1d682efa88c716e1849163d5abff3a3367581d16 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Mon, 16 Nov 2020 21:11:19 +0100 +Subject: [PATCH 18/34] pre dcevm15 - fix GC spaces originally in removed CMS + patch + +--- + src/hotspot/share/gc/shared/space.cpp | 16 ++++++++-------- + src/hotspot/share/gc/shared/space.hpp | 6 +++--- + src/hotspot/share/gc/shared/space.inline.hpp | 14 ++++++++------ + .../share/prims/jvmtiEnhancedRedefineClasses.cpp | 6 ++---- + 4 files changed, 21 insertions(+), 21 deletions(-) + +diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp +index 875a6dc854f..9772c32c42e 100644 +--- a/src/hotspot/share/gc/shared/space.cpp ++++ b/src/hotspot/share/gc/shared/space.cpp +@@ -375,11 +375,11 @@ HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, H + } + + HeapWord* CompactibleSpace::forward(oop q, size_t size, +- CompactPoint* cp, HeapWord* compact_top) { ++ CompactPoint* cp, HeapWord* compact_top, bool force_forward) { + compact_top = forward_compact_top(size, cp, compact_top); + + // store the forwarding pointer into the mark word +- if (cast_from_oop(q) != compact_top || (size_t)q->size() != size) { ++ if (force_forward || cast_from_oop(q) != compact_top || (size_t)q->size() != size) { + q->forward_to(oop(compact_top)); + assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); + } else { +@@ -501,7 +501,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { + + } else { + assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces"); +- if (tenured_gen->is_in_reserved(new_obj)) { ++ if (new_in_tenured) { + // Must never rescue when moving from the new into the old generation. + assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); + assert(space_index(old_obj) > space_index(new_obj), "must be"); +@@ -824,14 +824,14 @@ void OffsetTableContigSpace::verify() const { + // Compute the forward sizes and leave out objects whose position could + // possibly overlap other objects. + HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, +- CompactPoint* cp, HeapWord* compact_top) { ++ CompactPoint* cp, HeapWord* compact_top, bool force_forward) { + size_t forward_size = size; + + // (DCEVM) There is a new version of the class of q => different size + if (oop(q)->klass()->new_version() != NULL) { + + size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); +- assert(size != new_size, "instances without changed size have to be updated prior to GC run"); ++ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); + forward_size = new_size; + } + +@@ -845,7 +845,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, + return compact_top; + } + +- return forward(oop(q), forward_size, cp, compact_top); ++ return forward(oop(q), forward_size, cp, compact_top, force_forward); + } + + // Compute the forwarding addresses for the objects that need to be rescued. +@@ -861,11 +861,11 @@ HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_ + // (DCEVM) There is a new version of the class of q => different size + if (oop(q)->klass()->new_version() != NULL) { + size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); +- assert(size != new_size, "instances without changed size have to be updated prior to GC run"); ++ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); + size = new_size; + } + +- compact_top = cp->space->forward(oop(q), size, cp, compact_top); ++ compact_top = cp->space->forward(oop(q), size, cp, compact_top, true); + assert(compact_top <= end(), "must not write over end of space!"); + } + MarkSweep::_rescued_oops->clear(); +diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp +index c9bfc365f0f..f7648995454 100644 +--- a/src/hotspot/share/gc/shared/space.hpp ++++ b/src/hotspot/share/gc/shared/space.hpp +@@ -405,7 +405,7 @@ public: + virtual void prepare_for_compaction(CompactPoint* cp) = 0; + // MarkSweep support phase3 + DEBUG_ONLY(int space_index(oop obj)); +- bool must_rescue(oop old_obj, oop new_obj); ++ virtual bool must_rescue(oop old_obj, oop new_obj); + HeapWord* rescue(HeapWord* old_obj); + virtual void adjust_pointers(); + // MarkSweep support phase4 +@@ -436,11 +436,11 @@ public: + // function of the then-current compaction space, and updates "cp->threshold + // accordingly". + virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, +- HeapWord* compact_top); ++ HeapWord* compact_top, bool force_forward); + // (DCEVM) same as forwad, but can rescue objects. Invoked only during + // redefinition runs + HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp, +- HeapWord* compact_top); ++ HeapWord* compact_top, bool force_forward); + + HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top); + +diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp +index 5a93e93471b..fa645423685 100644 +--- a/src/hotspot/share/gc/shared/space.inline.hpp ++++ b/src/hotspot/share/gc/shared/space.inline.hpp +@@ -163,6 +163,8 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + HeapWord* cur_obj = space->bottom(); + HeapWord* scan_limit = space->scan_limit(); + ++ bool force_forward = false; ++ + while (cur_obj < scan_limit) { + assert(!space->scanned_block_is_obj(cur_obj) || + oop(cur_obj)->mark_raw().is_marked() || oop(cur_obj)->mark_raw().is_unlocked() || +@@ -174,14 +176,15 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + size_t size = space->scanned_block_size(cur_obj); + + if (redefinition_run) { +- compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top); ++ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top, force_forward); + if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) { + /* Was moved (otherwise, forward would reset mark), + set first_dead to here */ + first_dead = cur_obj; ++ force_forward = true; + } + } else { +- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); ++ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top, false); + } + + cur_obj += size; +@@ -197,9 +200,9 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c + + // see if we might want to pretend this object is alive so that + // we don't have to compact quite as often. +- if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { ++ if (!redefinition_run && cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { + oop obj = oop(cur_obj); +- compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); ++ compact_top = cp->space->forward(obj, obj->size(), cp, compact_top, force_forward); + end_of_live = end; + } else { + // otherwise, it really is a free region. +@@ -362,8 +365,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti + Prefetch::write(compaction_top, copy_interval); + + // copy object and reinit its mark +- assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL, +- "everything in this pass should be moving"); ++ assert(redefinition_run || cur_obj != compaction_top, "everything in this pass should be moving"); + if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) { + Klass* new_version = oop(cur_obj)->klass()->new_version(); + if (new_version->update_information() == NULL) { +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 718426f2819..1da6661dd3e 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -431,13 +431,11 @@ public: + Klass* new_klass = obj->klass()->new_version(); + + if (new_klass->update_information() != NULL) { +- int size_diff = obj->size() - obj->size_given_klass(new_klass); +- +- // Either new size is bigger or gap is to small to be filled +- if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) { ++ if (obj->size() - obj->size_given_klass(new_klass) != 0) { + // We need an instance update => set back to old klass + _needs_instance_update = true; + } else { ++ // Either new size is bigger or gap is to small to be filled + oop src = obj; + if (new_klass->is_copying_backwards()) { + copy_to_tmp(obj); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch b/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch new file mode 100644 index 000000000000..2644ed0f716f --- /dev/null +++ b/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch @@ -0,0 +1,942 @@ +From 297f564f6af79fb824f5b4e9119f1d3d0c827fb0 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Mon, 16 Nov 2020 20:20:12 +0100 +Subject: [PATCH 19/34] dcevm15 - fix java15 patch compilation issues + +--- + .../share/classfile/classFileParser.hpp | 8 +- + .../share/classfile/classLoaderData.cpp | 2 +- + src/hotspot/share/classfile/dictionary.hpp | 10 +- + src/hotspot/share/classfile/javaClasses.hpp | 2 + + .../share/gc/g1/g1FullGCCompactTask.cpp | 4 +- + .../share/gc/g1/g1FullGCCompactionPoint.cpp | 8 +- + .../share/gc/g1/g1FullGCPrepareTask.cpp | 4 +- + src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 14 +- + src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 2 +- + src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- + src/hotspot/share/gc/shared/space.cpp | 4 +- + .../share/interpreter/linkResolver.cpp | 2 +- + src/hotspot/share/oops/instanceKlass.cpp | 17 ++- + src/hotspot/share/oops/instanceKlass.hpp | 1 + + src/hotspot/share/oops/klass.cpp | 8 +- + src/hotspot/share/prims/jvm.cpp | 2 + + .../prims/jvmtiEnhancedRedefineClasses.cpp | 129 +++++++++--------- + .../prims/jvmtiEnhancedRedefineClasses.hpp | 14 +- + src/hotspot/share/prims/jvmtiEnv.cpp | 11 +- + .../share/prims/jvmtiRedefineClasses.cpp | 1 + + src/hotspot/share/prims/methodHandles.hpp | 3 + + src/hotspot/share/runtime/arguments.cpp | 22 +-- + src/hotspot/share/runtime/mutexLocker.cpp | 2 +- + 23 files changed, 159 insertions(+), 113 deletions(-) + +diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp +index e5761e61767..0d266b9047e 100644 +--- a/src/hotspot/share/classfile/classFileParser.hpp ++++ b/src/hotspot/share/classfile/classFileParser.hpp +@@ -150,9 +150,6 @@ class ClassFileParser { + const intArray* _method_ordering; + GrowableArray* _all_mirandas; + +- // Enhanced class redefinition +- const bool _pick_newest; +- + enum { fixed_buffer_size = 128 }; + u_char _linenumbertable_buffer[fixed_buffer_size]; + +@@ -206,6 +203,9 @@ class ClassFileParser { + bool _has_vanilla_constructor; + int _max_bootstrap_specifier_index; // detects BSS values + ++ // (DCEVM) Enhanced class redefinition ++ const bool _pick_newest; ++ + void parse_stream(const ClassFileStream* const stream, TRAPS); + + void mangle_hidden_class_name(InstanceKlass* const ik); +@@ -582,7 +582,7 @@ class ClassFileParser { + ClassLoaderData* loader_data() const { return _loader_data; } + const Symbol* class_name() const { return _class_name; } + const InstanceKlass* super_klass() const { return _super_klass; } +- Array* local_interfaces() const { return _local_interfaces; } ++ Array* local_interfaces() const { return _local_interfaces; } + + ReferenceType reference_type() const { return _rt; } + AccessFlags access_flags() const { return _access_flags; } +diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp +index 4d64c6b454a..aadcd50ef4a 100644 +--- a/src/hotspot/share/classfile/classLoaderData.cpp ++++ b/src/hotspot/share/classfile/classLoaderData.cpp +@@ -597,7 +597,7 @@ void ClassLoaderData::exchange_holders(ClassLoaderData* cld) { + oop holder_oop = _holder.peek(); + _holder.replace(cld->_holder.peek()); + cld->_holder.replace(holder_oop); +- WeakHandle exchange = _holder; ++ WeakHandle exchange = _holder; + _holder = cld->_holder; + cld->_holder = exchange; + } +diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp +index 114a983e783..a50f4ff84d2 100644 +--- a/src/hotspot/share/classfile/dictionary.hpp ++++ b/src/hotspot/share/classfile/dictionary.hpp +@@ -84,6 +84,11 @@ public: + void print_on(outputStream* st) const; + void verify(); + ++ // (DCEVM) Enhanced class redefinition ++ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); ++ ++ void rollback_redefinition(); ++ + private: + DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass); + +@@ -106,11 +111,6 @@ public: + + void free_entry(DictionaryEntry* entry); + +- // Enhanced class redefinition +- bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); +- +- void rollback_redefinition(); +- + // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k" + static InstanceKlass* old_if_redefined(InstanceKlass* k) { + return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; +diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp +index a68c5139151..9abf2e1d105 100644 +--- a/src/hotspot/share/classfile/javaClasses.hpp ++++ b/src/hotspot/share/classfile/javaClasses.hpp +@@ -255,7 +255,9 @@ class java_lang_Class : AllStatic { + static void set_init_lock(oop java_class, oop init_lock); + static void set_protection_domain(oop java_class, oop protection_domain); + static void set_class_loader(oop java_class, oop class_loader); ++ public: // DCEVM + static void set_component_mirror(oop java_class, oop comp_mirror); ++ private: + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS); + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +index f70f4606dc8..a22ed48560d 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp +@@ -157,14 +157,14 @@ void G1FullGCCompactTask::serial_compaction_dcevm() { + + size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) { + size_t size = obj->size(); +- HeapWord* destination = (HeapWord*)obj->forwardee(); ++ HeapWord* destination = cast_from_oop(obj->forwardee()); + if (destination == NULL) { + // Object not moving + return size; + } + + // copy object and reinit its mark +- HeapWord* obj_addr = (HeapWord*) obj; ++ HeapWord* obj_addr = cast_from_oop(obj); + + if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) { + ++(*_rescue_oops_it); +diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +index 1e49571c999..755935a2c91 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp +@@ -174,7 +174,7 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_ + assert(_current_region != NULL, "Must have been initialized"); + + // Store a forwarding pointer if the object should be moved. +- if ((HeapWord*)object != _compaction_top || force_forward) { ++ if (cast_from_oop(object) != _compaction_top || force_forward) { + object->forward_to(oop(_compaction_top)); + } else { + if (object->forwardee() != NULL) { +@@ -188,11 +188,11 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_ + } else { + // Make sure object has the correct mark-word set or that it will be + // fixed when restoring the preserved marks. +- assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark +- object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet ++ assert(object->mark_raw() == markWord::prototype_for_klass(object->klass()) || // Correct mark ++ object->mark_must_be_preserved() || // Will be restored by PreservedMarksSet + (UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking + "should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT, +- p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object))); ++ p2i(object), object->mark_raw().value(), markWord::prototype_for_klass(object->klass()).value()); + } + assert(object->forwardee() == NULL, "should be forwarded to NULL"); + } +diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +index a45681b60cf..2f06b9617e4 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +@@ -269,7 +269,7 @@ size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object) + HeapWord* compact_top = _cp->forward_compact_top(forward_size); + + if (compact_top == NULL || must_rescue(object, oop(compact_top))) { +- _cp->rescued_oops()->append((HeapWord*)object); ++ _cp->rescued_oops()->append(cast_from_oop(object)); + } else { + _cp->forward_dcevm(object, forward_size, (size != forward_size)); + } +@@ -295,7 +295,7 @@ bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_ + int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); + int original_size = old_obj->size(); + +- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); ++ bool overlap = (cast_from_oop(old_obj) + original_size < cast_from_oop(new_obj) + new_size); + + return overlap; + } +diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp +index 803e645f843..3dee097f1d3 100644 +--- a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp ++++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp +@@ -58,10 +58,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_ + DcevmSharedGC::update_fields(rescued_obj, new_obj); + } else { + rescued_obj->set_klass(new_klass); +- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); ++ Copy::aligned_disjoint_words(cast_from_oop(rescued_obj), cast_from_oop(new_obj), size); + } + } else { +- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); ++ Copy::aligned_disjoint_words(cast_from_oop(rescued_obj), cast_from_oop(new_obj), size); + } + + new_obj->init_mark_raw(); +@@ -111,11 +111,11 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) { + + // Save object somewhere, there is an overlap in fields + if (new_klass_oop->is_copying_backwards()) { +- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || +- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { ++ if ((cast_from_oop(q) >= cast_from_oop(new_location) && cast_from_oop(q) < cast_from_oop(new_location) + new_size) || ++ (cast_from_oop(new_location) >= cast_from_oop(q) && cast_from_oop(new_location) < cast_from_oop(q) + size)) { + tmp = NEW_RESOURCE_ARRAY(HeapWord, size); + q = (oop) tmp; +- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); ++ Copy::aligned_disjoint_words(cast_from_oop(tmp_obj), cast_from_oop(q), size); + } + } + +@@ -131,13 +131,13 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) { + + void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) { + assert(cur != NULL, "just checking"); +- char* to = (char*)(HeapWord*)new_location; ++ char* to = (char*)cast_from_oop(new_location); + while (*cur != 0) { + int size = *cur; + if (size > 0) { + cur++; + int offset = *cur; +- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); ++ HeapWord* from = (HeapWord*)(((char *)cast_from_oop(tmp_obj)) + offset); + if (size == HeapWordSize) { + *((HeapWord*)to) = *from; + } else if (size == HeapWordSize * 2) { +diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp +index e2ef0171fb2..a4e27e00280 100644 +--- a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp ++++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp +@@ -29,7 +29,7 @@ + #include "gc/shared/genOopClosures.hpp" + #include "gc/shared/taskqueue.hpp" + #include "memory/iterator.hpp" +-#include "oops/markOop.hpp" ++#include "oops/markWord.hpp" + #include "oops/oop.hpp" + #include "runtime/timer.hpp" + #include "utilities/growableArray.hpp" +diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp +index f01d64d1434..5c1a09390f1 100644 +--- a/src/hotspot/share/gc/shared/gcConfig.cpp ++++ b/src/hotspot/share/gc/shared/gcConfig.cpp +@@ -100,7 +100,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { + void GCConfig::select_gc_ergonomically() { + if (AllowEnhancedClassRedefinition && !UseG1GC) { + // Enhanced class redefinition only supports serial GC at the moment +- FLAG_SET_ERGO(bool, UseSerialGC, true); ++ FLAG_SET_ERGO(UseSerialGC, true); + } else if (os::is_server_class_machine()) { + #if INCLUDE_G1GC + FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); +diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp +index 9772c32c42e..e8e3d7884c2 100644 +--- a/src/hotspot/share/gc/shared/space.cpp ++++ b/src/hotspot/share/gc/shared/space.cpp +@@ -440,7 +440,7 @@ int CompactibleSpace::space_index(oop obj) { + index++; + } + +- tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj); ++ tty->print_cr("could not compute space_index for %08xh", cast_from_oop(obj)); + index = 0; + + Generation* gen = heap->old_gen(); +@@ -485,7 +485,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { + bool new_in_tenured = tenured_gen->is_in_reserved(new_obj); + if (old_in_tenured == new_in_tenured) { + // Rescue if object may overlap with a higher memory address. +- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); ++ bool overlap = (cast_from_oop(old_obj) + original_size < cast_from_oop(new_obj) + new_size); + if (old_in_tenured) { + // Old and new address are in same space, so just compare the address. + // Must rescue if object moves towards the top of the space. +diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp +index b2f24ddbeda..9daeeb70b34 100644 +--- a/src/hotspot/share/interpreter/linkResolver.cpp ++++ b/src/hotspot/share/interpreter/linkResolver.cpp +@@ -1031,7 +1031,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, + assert(m != NULL, "information about the current method must be available for 'put' bytecodes"); + bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic && + fd.is_static() && +- !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name())); ++ !(m->is_static_initializer() || m->name() == vmSymbols::ha_class_initializer_name())); + bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) && + !fd.is_static() && + !m->is_object_initializer()); +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index f8e60941046..5e40d78a87e 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -1316,7 +1316,7 @@ void InstanceKlass::init_implementor() { + // (DCEVM) - init_implementor() for dcevm + void InstanceKlass::init_implementor_from_redefine() { + assert(is_interface(), "not interface"); +- Klass** addr = adr_implementor(); ++ Klass* volatile* addr = adr_implementor(); + assert(addr != NULL, "null addr"); + if (addr != NULL) { + *addr = NULL; +@@ -1659,6 +1659,21 @@ void InstanceKlass::methods_do(void f(Method* method)) { + } + } + ++void InstanceKlass::methods_do(void f(Method* method, TRAPS), TRAPS) { ++ // Methods aren't stable until they are loaded. This can be read outside ++ // a lock through the ClassLoaderData for profiling ++ if (!is_loaded()) { ++ return; ++ } ++ ++ int len = methods()->length(); ++ for (int index = 0; index < len; index++) { ++ Method* m = methods()->at(index); ++ assert(m->is_method(), "must be method"); ++ f(m, CHECK); ++ } ++} ++ + // (DCEVM) Update information contains mapping of fields from old class to the new class. + // Info is stored on HEAP, you need to call clear_update_information to free the space. + void InstanceKlass::store_update_information(GrowableArray &values) { +diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp +index 6ead9426728..b56d42cb177 100644 +--- a/src/hotspot/share/oops/instanceKlass.hpp ++++ b/src/hotspot/share/oops/instanceKlass.hpp +@@ -1069,6 +1069,7 @@ public: + void clear_update_information(); + + void methods_do(void f(Method* method)); ++ void methods_do(void f(Method* method, TRAPS), TRAPS); + void array_klasses_do(void f(Klass* k)); + void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); + +diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp +index 352d8f84631..88f5ec9ba4a 100644 +--- a/src/hotspot/share/oops/klass.cpp ++++ b/src/hotspot/share/oops/klass.cpp +@@ -200,13 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word + Klass::Klass(KlassID id) : _id(id), + _java_mirror(NULL), + _prototype_header(markWord::prototype()), +- _shared_class_path_index(-1), +- _new_version(NULL), + _old_version(NULL), ++ _new_version(NULL), ++ _redefinition_flags(Klass::NoRedefinition), + _is_redefining(false), ++ _update_information(NULL), + _is_copying_backwards(false), +- _redefinition_flags(Klass::NoRedefinition), +- _update_information(NULL) { ++ _shared_class_path_index(-1) { + CDS_ONLY(_shared_class_flags = 0;) + CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;) + _primary_supers[0] = this; +diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp +index 333b65ccfc1..13bcac352fb 100644 +--- a/src/hotspot/share/prims/jvm.cpp ++++ b/src/hotspot/share/prims/jvm.cpp +@@ -1054,6 +1054,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na + class_loader, + protection_domain, + &st, ++ NULL, + CHECK_NULL); + + if (log_is_enabled(Debug, class, resolve) && defined_k != NULL) { +@@ -1074,6 +1075,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na + class_loader, + &st, + cl_info, ++ NULL, + CHECK_NULL); + if (defined_k == NULL) { + THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a hidden class"); +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 1da6661dd3e..619e3988e3a 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -24,11 +24,14 @@ + + #include "precompiled.hpp" + #include "aot/aotLoader.hpp" ++#include "classfile/classFileParser.hpp" + #include "classfile/classFileStream.hpp" + #include "classfile/metadataOnStackMark.hpp" + #include "classfile/systemDictionary.hpp" + #include "classfile/verifier.hpp" + #include "classfile/dictionary.hpp" ++#include "classfile/classLoaderDataGraph.hpp" ++#include "interpreter/linkResolver.hpp" + #include "interpreter/oopMapCache.hpp" + #include "interpreter/rewriter.hpp" + #include "logging/logStream.hpp" +@@ -37,17 +40,22 @@ + #include "memory/resourceArea.hpp" + #include "memory/iterator.inline.hpp" + #include "oops/fieldStreams.hpp" ++#include "oops/fieldStreams.inline.hpp" + #include "oops/klassVtable.hpp" + #include "oops/oop.inline.hpp" + #include "oops/constantPool.inline.hpp" ++#include "oops/metadata.hpp" ++#include "oops/methodData.hpp" + #include "prims/jvmtiImpl.hpp" + #include "prims/jvmtiClassFileReconstituter.hpp" + #include "prims/jvmtiEnhancedRedefineClasses.hpp" + #include "prims/methodComparator.hpp" + #include "prims/resolvedMethodTable.hpp" ++#include "prims/methodHandles.hpp" + #include "runtime/deoptimization.hpp" + #include "runtime/jniHandles.inline.hpp" + #include "runtime/relocator.hpp" ++#include "runtime/fieldDescriptor.hpp" + #include "runtime/fieldDescriptor.inline.hpp" + #include "utilities/bitMap.inline.hpp" + #include "prims/jvmtiThreadState.inline.hpp" +@@ -55,6 +63,8 @@ + #include "oops/constantPool.inline.hpp" + #include "gc/g1/g1CollectedHeap.hpp" + #include "gc/shared/dcevmSharedGC.hpp" ++#include "gc/shared/scavengableNMethods.hpp" ++#include "ci/ciObjectFactory.hpp" + + Array* VM_EnhancedRedefineClasses::_old_methods = NULL; + Array* VM_EnhancedRedefineClasses::_new_methods = NULL; +@@ -66,6 +76,7 @@ int VM_EnhancedRedefineClasses::_matching_methods_length = 0; + int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; + int VM_EnhancedRedefineClasses::_added_methods_length = 0; + Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; ++u8 VM_EnhancedRedefineClasses::_id_counter = 0; + + // + // Create new instance of enhanced class redefiner. +@@ -88,6 +99,7 @@ VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const j + _class_load_kind = class_load_kind; + _res = JVMTI_ERROR_NONE; + _any_class_has_resolved_methods = false; ++ _id = next_id(); + } + + static inline InstanceKlass* get_ik(jclass def) { +@@ -211,9 +223,7 @@ class FieldCopier : public FieldClosure { + + // TODO: review... + void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { +- if (!nm->on_scavenge_root_list()) { +- CodeCache::add_scavenge_root_nmethod(nm); +- } ++ ScavengableNMethods::register_nmethod(nm); + } + + void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { +@@ -414,7 +424,7 @@ public: + _tmp_obj_size = size; + _tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize); + } +- Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size); ++ Copy::aligned_disjoint_words(cast_from_oop(o), cast_from_oop(_tmp_obj), size); + } + + virtual void do_object(oop obj) { +@@ -505,9 +515,6 @@ void VM_EnhancedRedefineClasses::doit() { + ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); + ClassLoaderDataGraph::classes_do(&clear_cpool_cache); + +- +- // SystemDictionary::methods_do(fix_invoke_method); +- + // JSR-292 support + if (_any_class_has_resolved_methods) { + bool trace_name_printed = false; +@@ -564,8 +571,8 @@ void VM_EnhancedRedefineClasses::doit() { + InstanceKlass* old = InstanceKlass::cast(cur->old_version()); + + // Swap marks to have same hashcodes +- markOop cur_mark = cur->prototype_header(); +- markOop old_mark = old->prototype_header(); ++ markWord cur_mark = cur->prototype_header(); ++ markWord old_mark = old->prototype_header(); + cur->set_prototype_header(old_mark); + old->set_prototype_header(cur_mark); + +@@ -579,14 +586,14 @@ void VM_EnhancedRedefineClasses::doit() { + // Revert pool holder for old version of klass (it was updated by one of ours closure!) + old->constants()->set_pool_holder(old); + +- Klass* array_klasses = old->array_klasses(); ++ ObjArrayKlass* array_klasses = old->array_klasses(); + if (array_klasses != NULL) { + assert(cur->array_klasses() == NULL, "just checking"); + + // Transfer the array classes, otherwise we might get cast exceptions when casting array types. + // Also, set array klasses element klass. + cur->set_array_klasses(array_klasses); +- ObjArrayKlass::cast(array_klasses)->set_element_klass(cur); ++ array_klasses->set_element_klass(cur); + java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses); + java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror()); + } +@@ -641,11 +648,15 @@ void VM_EnhancedRedefineClasses::doit() { + //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); + + // Disable any dependent concurrent compilations +- SystemDictionary::notice_modification(); ++ // SystemDictionary::notice_modification(); ++ ++ JvmtiExport::increment_redefinition_count(); + + // Set flag indicating that some invariants are no longer true. + // See jvmtiExport.hpp for detailed explanation. +- JvmtiExport::set_has_redefined_a_class(); ++ ++ // dcevm15: handled by _redefinition_count ++ // JvmtiExport::set_has_redefined_a_class(); + + #ifdef PRODUCT + if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { +@@ -718,7 +729,7 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { + } + + // Cannot redefine or retransform an anonymous class. +- if (InstanceKlass::cast(k)->is_anonymous()) { ++ if (InstanceKlass::cast(k)->is_unsafe_anonymous()) { + return false; + } + return true; +@@ -804,22 +815,30 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + + InstanceKlass* k; + +- if (InstanceKlass::cast(the_class)->is_anonymous()) { +- const InstanceKlass* host_class = the_class->host_klass(); ++ if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) { ++ const InstanceKlass* host_class = the_class->unsafe_anonymous_host(); + + // Make sure it's the real host class, not another anonymous class. +- while (host_class != NULL && host_class->is_anonymous()) { +- host_class = host_class->host_klass(); ++ while (host_class != NULL && host_class->is_unsafe_anonymous()) { ++ host_class = host_class->unsafe_anonymous_host(); + } + ++ ClassLoadInfo cl_info(protection_domain, ++ host_class, ++ NULL, // dynamic_nest_host ++ NULL, // cp_patches ++ Handle(), // classData ++ false, // is_hidden ++ false, // is_strong_hidden ++ true); // FIXME: check if correct. can_access_vm_annotations ++ + k = SystemDictionary::parse_stream(the_class_sym, + the_class_loader, +- protection_domain, + &st, +- host_class, ++ cl_info, + the_class, +- NULL, + THREAD); ++ + k->class_loader_data()->exchange_holders(the_class->class_loader_data()); + the_class->class_loader_data()->inc_keep_alive(); + } else { +@@ -966,7 +985,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ + // Check interfaces + + // Interfaces removed? +- Array* old_interfaces = the_class->transitive_interfaces(); ++ Array* old_interfaces = the_class->transitive_interfaces(); + for (i = 0; i < old_interfaces->length(); i++) { + InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i)); + if (!new_class->implements_interface_any_version(old_interface)) { +@@ -976,7 +995,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ + } + + // Interfaces added? +- Array* new_interfaces = new_class->transitive_interfaces(); ++ Array* new_interfaces = new_class->transitive_interfaces(); + for (i = 0; ilength(); i++) { + if (!the_class->implements_interface_any_version(new_interfaces->at(i))) { + result = result | Klass::ModifyClass; +@@ -1389,8 +1408,8 @@ void VM_EnhancedRedefineClasses::rollback() { + // Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp + // The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not + // do that, they assume that cache entry is resolved already. +-void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { +- RawBytecodeStream bcs(method); ++void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method, TRAPS) { ++ RawBytecodeStream bcs(methodHandle(THREAD, method)); + Bytecodes::Code code; + Bytecodes::Code java_code; + while (!bcs.is_last_bytecode()) { +@@ -1454,11 +1473,11 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + HandleMark hm(_thread); + InstanceKlass *ik = InstanceKlass::cast(k); + +- constantPoolHandle other_cp = constantPoolHandle(ik->constants()); ++ constantPoolHandle other_cp = constantPoolHandle(_thread, ik->constants()); + + // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. +- if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { +- ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); ++ if (ik->is_unsafe_anonymous() && ik->unsafe_anonymous_host()->new_version() != NULL) { ++ ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version())); + } + + // Update implementor if there is only one, in this case implementor() can reference old class +@@ -1492,7 +1511,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + + // If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries + if (RewriteBytecodes) { +- ik->methods_do(unpatch_bytecode); ++ ik->methods_do(unpatch_bytecode, _thread); ++ } ++} ++ ++u8 VM_EnhancedRedefineClasses::next_id() { ++ while (true) { ++ u8 id = _id_counter; ++ u8 next_id = id + 1; ++ u8 result = Atomic::cmpxchg(&_id_counter, id, next_id); ++ if (result == id) { ++ return next_id; ++ } + } + } + +@@ -1512,31 +1542,8 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { + } + } + +-void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) { +- +- constantPoolHandle other_cp = constantPoolHandle(method->constants()); +- +- for (int i = 0; i < other_cp->length(); i++) { +- if (other_cp->tag_at(i).is_klass()) { +- Klass* klass = other_cp->resolved_klass_at(i); +- if (klass->new_version() != NULL) { +- // Constant pool entry points to redefined class -- update to the new version +- other_cp->klass_at_put(i, klass->newest_version()); +- } +- assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); +- } +- } +- +- ConstantPoolCache* cp_cache = other_cp->cache(); +- if (cp_cache != NULL) { +- cp_cache->clear_entries(); +- } +- +-} +- + +- +-void VM_EnhancedRedefineClasses::update_jmethod_ids() { ++void VM_EnhancedRedefineClasses::update_jmethod_ids(TRAPS) { + for (int j = 0; j < _matching_methods_length; ++j) { + Method* old_method = _matching_old_methods[j]; + jmethodID jmid = old_method->find_jmethod_id_or_null(); +@@ -1547,10 +1554,10 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() { + + if (jmid != NULL) { + // There is a jmethodID, change it to point to the new method +- methodHandle new_method_h(_matching_new_methods[j]); ++ methodHandle new_method_h(THREAD, _matching_new_methods[j]); + + if (old_method->new_version() == NULL) { +- methodHandle old_method_h(_matching_old_methods[j]); ++ methodHandle old_method_h(THREAD, _matching_old_methods[j]); + jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h()); + bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id); + } else { +@@ -1887,7 +1894,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + + // track number of methods that are EMCP for add_previous_version() call below + check_methods_and_mark_as_obsolete(); +- update_jmethod_ids(); ++ update_jmethod_ids(THREAD); + + _any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods; + +@@ -2119,12 +2126,12 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { + + Handle protection_domain(THREAD, klass->protection_domain()); + ++ ClassLoadInfo cl_info(protection_domain); ++ + ClassFileParser parser(&st, + klass->name(), + klass->class_loader_data(), +- protection_domain, +- NULL, // host_klass +- NULL, // cp_patches ++ &cl_info, + ClassFileParser::INTERNAL, // publicity level + true, + THREAD); +@@ -2134,7 +2141,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { + links.append(KlassPair(super_klass, klass)); + } + +- Array* local_interfaces = parser.local_interfaces(); ++ Array* local_interfaces = parser.local_interfaces(); + for (int j = 0; j < local_interfaces->length(); j++) { + Klass* iface = local_interfaces->at(j); + if (iface != NULL && _affected_klasses->contains(iface)) { +@@ -2157,7 +2164,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { + links.append(KlassPair(super_klass, klass)); + } + +- Array* local_interfaces = klass->local_interfaces(); ++ Array* local_interfaces = klass->local_interfaces(); + for (int j = 0; j < local_interfaces->length(); j++) { + Klass* interfaceKlass = local_interfaces->at(j); + if (_affected_klasses->contains(interfaceKlass)) { +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index 4c0412d343d..0066088b3b0 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -32,7 +32,7 @@ + #include "memory/resourceArea.hpp" + #include "oops/objArrayKlass.hpp" + #include "oops/objArrayOop.hpp" +-#include "gc/shared/vmGCOperations.hpp" ++#include "gc/shared/gcVMOperations.hpp" + #include "../../../java.base/unix/native/include/jni_md.h" + + // +@@ -59,6 +59,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + static int _deleted_methods_length; + static int _added_methods_length; + static Klass* _the_class_oop; ++ static u8 _id_counter; + + // The instance fields are used to pass information from + // doit_prologue() to doit() and doit_epilogue(). +@@ -91,6 +92,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + elapsedTimer _timer_heap_iterate; + elapsedTimer _timer_heap_full_gc; + ++ // Redefinition id used by JFR ++ u8 _id; ++ + // These routines are roughly in call order unless otherwise noted. + + // Load and link new classes (either redefined or affected by redefinition - subclass, ...) +@@ -118,15 +122,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + static void mark_as_scavengable(nmethod* nm); + static void unregister_nmethod_g1(nmethod* nm); + static void register_nmethod_g1(nmethod* nm); +- static void unpatch_bytecode(Method* method); +- static void fix_invoke_method(Method* method); ++ static void unpatch_bytecode(Method* method, TRAPS); + + // Figure out which new methods match old methods in name and signature, + // which methods have been added, and which are no longer present + void compute_added_deleted_matching_methods(); + + // Change jmethodIDs to point to the new methods +- void update_jmethod_ids(); ++ void update_jmethod_ids(TRAPS); + + // marking methods as old and/or obsolete + void check_methods_and_mark_as_obsolete(); +@@ -141,6 +144,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + + void flush_dependent_code(InstanceKlass* k_h, TRAPS); + ++ u8 next_id(); ++ + static void check_class(InstanceKlass* k_oop, TRAPS); + + static void dump_methods(); +@@ -181,6 +186,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + + bool allow_nested_vm_operations() const { return true; } + jvmtiError check_error() { return _res; } ++ u8 id() { return _id; } + + // Modifiable test must be shared between IsModifiableClass query + // and redefine implementation +diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp +index b6838ac034d..fba0f48abd7 100644 +--- a/src/hotspot/share/prims/jvmtiEnv.cpp ++++ b/src/hotspot/share/prims/jvmtiEnv.cpp +@@ -456,20 +456,23 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { + + EventRetransformClasses event; + jvmtiError error; ++ u8 op_id; + + if (AllowEnhancedClassRedefinition) { + MutexLocker sd_mutex(EnhancedRedefineClasses_lock); + VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); + VMThread::execute(&op); ++ op_id = op.id(); + error = (op.check_error()); + } else { + VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); + VMThread::execute(&op); ++ op_id = op.id(); + error = op.check_error(); + } + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); +- event.set_redefinitionId(op.id()); ++ event.set_redefinitionId(op_id); + event.commit(); + } + return error; +@@ -484,19 +487,23 @@ JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_de + EventRedefineClasses event; + jvmtiError error; + ++ u8 op_id; ++ + if (AllowEnhancedClassRedefinition) { + MutexLocker sd_mutex(EnhancedRedefineClasses_lock); + VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); + VMThread::execute(&op); ++ op_id = op.id(); + error = (op.check_error()); + } else { + VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); + VMThread::execute(&op); ++ op_id = op.id(); + error = op.check_error(); + } + if (error == JVMTI_ERROR_NONE) { + event.set_classCount(class_count); +- event.set_redefinitionId(op.id()); ++ event.set_redefinitionId(op_id); + event.commit(); + } + return error; +diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +index a7840848e10..346eac7c431 100644 +--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +@@ -1271,6 +1271,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { + the_class_loader, + &st, + cl_info, ++ NULL, + THREAD); + // Clear class_being_redefined just to be sure. + state->clear_class_being_redefined(); +diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp +index 54f36202a5f..917d31efd77 100644 +--- a/src/hotspot/share/prims/methodHandles.hpp ++++ b/src/hotspot/share/prims/methodHandles.hpp +@@ -180,6 +180,9 @@ public: + assert(ref_kind_is_valid(ref_kind), ""); + return (ref_kind & 1) != 0; + } ++ static bool ref_kind_is_static(int ref_kind) { ++ return !ref_kind_has_receiver(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial); ++ } + + static int ref_kind_to_flags(int ref_kind); + +diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp +index d05a2893498..3a92b8869dc 100644 +--- a/src/hotspot/share/runtime/arguments.cpp ++++ b/src/hotspot/share/runtime/arguments.cpp +@@ -2128,13 +2128,15 @@ bool Arguments::check_gc_consistency() { + // of collectors. + uint i = 0; + if (UseSerialGC) i++; +- if (UseConcMarkSweepGC) i++; +- if (UseParallelGC || UseParallelOldGC) i++; ++ if (UseParallelGC) i++; + if (UseG1GC) i++; ++ if (UseEpsilonGC) i++; ++ if (UseZGC) i++; ++ if (UseShenandoahGC) i++; + if (AllowEnhancedClassRedefinition) { + // Must use serial GC. This limitation applies because the instance size changing GC modifications + // are only built into the mark and compact algorithm. +- if ((!UseSerialGC && !UseG1GC) && i >= 1) { ++ if (!UseSerialGC && !UseG1GC && i >= 1) { + jio_fprintf(defaultStream::error_stream(), + "Must use the Serial or G1 GC with enhanced class redefinition.\n"); + return false; +@@ -4494,18 +4496,18 @@ void Arguments::setup_hotswap_agent() { + + // TODO: open it only for org.hotswap.agent module + // Use to access java.lang.reflect.Proxy/proxyCache +- create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); + // Class of field java.lang.reflect.Proxy/proxyCache +- create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); + // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream +- create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); + // java.beans.Introspector access +- create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); + // java.beans.Introspector access +- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); + // com.sun.beans.introspect.ClassInfo access +- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); + // com.sun.beans.introspect.util.Cache access +- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); ++ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); + + } +diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp +index 6f982072909..14a3ed730fe 100644 +--- a/src/hotspot/share/runtime/mutexLocker.cpp ++++ b/src/hotspot/share/runtime/mutexLocker.cpp +@@ -287,7 +287,7 @@ void mutex_init() { + def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never); + def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never); + def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); +- def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel ++ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, _safepoint_check_always); // for ensuring that class redefinition is not done in parallel + def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions + def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always); + +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch b/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch new file mode 100644 index 000000000000..07669d9f157c --- /dev/null +++ b/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch @@ -0,0 +1,25 @@ +From 336cab4f72c6e642e3077ea8d1a4860de33f5a4d Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Tue, 17 Nov 2020 17:40:24 +0100 +Subject: [PATCH 20/34] dcevm15 - G1 fixes + +--- + src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +index 2f06b9617e4..476728a5d26 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp ++++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp +@@ -240,7 +240,7 @@ void G1FullGCPrepareTask::prepare_serial_compaction_dcevm() { + + // collect remaining, not forwarded rescued oops using serial compact point + while (cp->last_rescued_oop() < cp->rescued_oops()->length()) { +- HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, false, true); ++ HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, HeapRegionType::Eden, true, G1NUMA::AnyNodeIndex); + if (hr == NULL) { + vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "G1 - not enough of free regions after redefinition."); + } +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch b/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch new file mode 100644 index 000000000000..a3f5e53ea123 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch @@ -0,0 +1,133 @@ +From cea4e2cca3c37233c728be7235f8f9d8be136cb5 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Tue, 17 Nov 2020 18:52:57 +0100 +Subject: [PATCH 21/34] dcevm15 - Fix flush dependent code + +--- + .../prims/jvmtiEnhancedRedefineClasses.cpp | 57 +++++++------------ + .../prims/jvmtiEnhancedRedefineClasses.hpp | 4 +- + 2 files changed, 25 insertions(+), 36 deletions(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 619e3988e3a..efaf11e1666 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -508,7 +508,7 @@ void VM_EnhancedRedefineClasses::doit() { + + // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) + // if (_max_redefinition_flags > Klass::ModifyClass) { +- flush_dependent_code(NULL, thread); ++ flush_dependent_code(thread); + // } + + // Adjust constantpool caches for all classes that reference methods of the evolved class. +@@ -647,17 +647,8 @@ void VM_EnhancedRedefineClasses::doit() { + //MethodDataCleaner clean_weak_method_links; + //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); + +- // Disable any dependent concurrent compilations +- // SystemDictionary::notice_modification(); +- + JvmtiExport::increment_redefinition_count(); + +- // Set flag indicating that some invariants are no longer true. +- // See jvmtiExport.hpp for detailed explanation. +- +- // dcevm15: handled by _redefinition_count +- // JvmtiExport::set_has_redefined_a_class(); +- + #ifdef PRODUCT + if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { + #endif +@@ -1746,6 +1737,18 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst + transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); + } + ++// First step is to walk the code cache for each class redefined and mark ++// dependent methods. Wait until all classes are processed to deoptimize everything. ++void VM_EnhancedRedefineClasses::mark_dependent_code(InstanceKlass* ik) { ++ assert_locked_or_safepoint(Compile_lock); ++ ++ // All dependencies have been recorded from startup or this is a second or ++ // subsequent use of RedefineClasses ++ if (0 && JvmtiExport::all_dependencies_are_recorded()) { ++ CodeCache::mark_for_evol_deoptimization(ik); ++ } ++} ++ + // DCEVM - it always deoptimizes everything! (because it is very difficult to find only correct dependencies) + // Deoptimize all compiled code that depends on this class. + // +@@ -1762,33 +1765,21 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst + // subsequent calls to RedefineClasses need only throw away code + // that depends on the class. + // +-void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) { ++void VM_EnhancedRedefineClasses::flush_dependent_code(TRAPS) { + assert_locked_or_safepoint(Compile_lock); + + // All dependencies have been recorded from startup or this is a second or + // subsequent use of RedefineClasses + // FIXME: for now, deoptimize all! +- if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) { +- CodeCache::flush_evol_dependents_on(k_h); +- Klass* superCl = k_h->super(); +- // Deoptimize super classes since redefined class can has a new method override +- while (superCl != NULL && !superCl->is_redefining()) { +- CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl)); +- superCl = superCl->super(); ++ if (0 && JvmtiExport::all_dependencies_are_recorded()) { ++ int deopt = CodeCache::mark_dependents_for_evol_deoptimization(); ++ log_debug(redefine, class, nmethod)("Marked %d dependent nmethods for deopt", deopt); ++ if (deopt != 0) { ++ CodeCache::flush_evol_dependents(); + } + } else { +- CodeCache::mark_all_nmethods_for_deoptimization(); +- +- ResourceMark rm(THREAD); +- DeoptimizationMarker dm; +- +- // Deoptimize all activations depending on marked nmethods +- Deoptimization::deoptimize_dependents(); +- +- // Make the dependent methods not entrant +- CodeCache::make_marked_nmethods_not_entrant(); +- +- // From now on we know that the dependency information is complete ++ CodeCache::mark_all_nmethods_for_evol_deoptimization(); ++ CodeCache::flush_evol_dependents(); + JvmtiExport::set_all_dependencies_are_recorded(true); + } + } +@@ -1881,11 +1872,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ + JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); + jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); + +- // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined +- // Deoptimize all compiled code that depends on this class +-// if (_max_redefinition_flags <= Klass::ModifyClass) { +-// flush_dependent_code(the_class, THREAD); +-// } ++ mark_dependent_code(the_class); + + _old_methods = the_class->methods(); + _new_methods = new_class->methods(); +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index 0066088b3b0..bd5e7d153be 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -142,7 +142,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // and in all direct and indirect subclasses. + void increment_class_counter(InstanceKlass *ik, TRAPS); + +- void flush_dependent_code(InstanceKlass* k_h, TRAPS); ++ void mark_dependent_code(InstanceKlass* ik); ++ ++ void flush_dependent_code(TRAPS); + + u8 next_id(); + +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch b/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch new file mode 100644 index 000000000000..bacf2ee70262 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch @@ -0,0 +1,211 @@ +From 4f88dcec830d39452f69d1117729469fdb768a8f Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 22 Nov 2020 12:05:26 +0100 +Subject: [PATCH 22/34] dcevm15 - fix ResolvedMethodTable + +--- + src/hotspot/share/classfile/javaClasses.cpp | 5 - + src/hotspot/share/classfile/javaClasses.hpp | 1 - + .../share/prims/resolvedMethodTable.cpp | 139 +++++++++++------- + 3 files changed, 84 insertions(+), 61 deletions(-) + +diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp +index 9b086a241f7..9a627786d0f 100644 +--- a/src/hotspot/share/classfile/javaClasses.cpp ++++ b/src/hotspot/share/classfile/javaClasses.cpp +@@ -3996,11 +3996,6 @@ void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop + resolved_method->obj_field_put(_vmholder_offset, holder); + } + +-void java_lang_invoke_ResolvedMethodName::set_vmholder_offset(oop resolved_method, Method* m) { +- assert(is_instance(resolved_method), "wrong type"); +- resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror()); +-} +- + oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) { + const Method* method = m(); + +diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp +index 9abf2e1d105..8f5993b7225 100644 +--- a/src/hotspot/share/classfile/javaClasses.hpp ++++ b/src/hotspot/share/classfile/javaClasses.hpp +@@ -1107,7 +1107,6 @@ class java_lang_invoke_ResolvedMethodName : AllStatic { + + static Method* vmtarget(oop resolved_method); + static void set_vmtarget(oop resolved_method, Method* method); +- static void set_vmholder_offset(oop resolved_method, Method* method); + + static void set_vmholder(oop resolved_method, oop holder); + +diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp +index eb9fcda44f3..d0f1667b967 100644 +--- a/src/hotspot/share/prims/resolvedMethodTable.cpp ++++ b/src/hotspot/share/prims/resolvedMethodTable.cpp +@@ -375,6 +375,67 @@ public: + } + }; + ++class AdjustMethodEntriesDcevm : public StackObj { ++ bool* _trace_name_printed; ++ GrowableArray* _oops_to_add; ++public: ++ AdjustMethodEntriesDcevm(GrowableArray* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {}; ++ bool operator()(WeakHandle* entry) { ++ oop mem_name = entry->peek(); ++ if (mem_name == NULL) { ++ // Removed ++ return true; ++ } ++ ++ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); ++ ++ if (old_method->is_old()) { ++ ++ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); ++ Method* newer_method; ++ ++ // Method* new_method; ++ if (old_method->is_deleted()) { ++ newer_method = Universe::throw_no_such_method_error(); ++ } else { ++ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); ++ ++ log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); ++ ++ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); ++ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); ++ assert(old_method != newer_method, "sanity check"); ++ ++ Thread* thread = Thread::current(); ++ ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method); ++ ResolvedMethodGet rmg(thread, newer_method); ++ ++ if (_local_table->get(thread, lookup, rmg)) { ++ // old method was already adjusted if new method exists in _the_table ++ return true; ++ } ++ } ++ ++ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); ++ java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror()); ++ ++ newer_klass->set_has_resolved_methods(); ++ _oops_to_add->append(mem_name); ++ ++ ResourceMark rm; ++ if (!(*_trace_name_printed)) { ++ log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); ++ *_trace_name_printed = true; ++ } ++ log_debug(redefine, class, update, constantpool) ++ ("ResolvedMethod method update: %s(%s)", ++ newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); ++ } ++ ++ return true; ++ } ++}; ++ + // It is called at safepoint only for RedefineClasses + void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); +@@ -382,73 +443,41 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { + AdjustMethodEntries adjust(trace_name_printed); + _local_table->do_safepoint_scan(adjust); + } +-#endif // INCLUDE_JVMTI + +-// (DCEVM) It is called at safepoint only for RedefineClasses ++// It is called at safepoint only for RedefineClasses + void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) { + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); + // For each entry in RMT, change to new method +- GrowableArray* oops_to_add = new GrowableArray(); +- +- for (int i = 0; i < _the_table->table_size(); ++i) { +- for (ResolvedMethodEntry* entry = _the_table->bucket(i); +- entry != NULL; +- entry = entry->next()) { +- +- oop mem_name = entry->object_no_keepalive(); +- // except ones removed +- if (mem_name == NULL) { +- continue; +- } +- Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); +- +- if (old_method->is_old()) { +- +- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); +- Method* newer_method; +- +- // Method* new_method; +- if (old_method->is_deleted()) { +- newer_method = Universe::throw_no_such_method_error(); +- } else { +- newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); +- +- log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); +- +- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); +- assert(newer_method != NULL, "method_with_idnum() should not be NULL"); +- assert(old_method != newer_method, "sanity check"); +- +- if (_the_table->lookup(newer_method) != NULL) { +- // old method was already adjusted if new method exists in _the_table +- continue; +- } +- } ++ GrowableArray oops_to_add(0); ++ AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed); ++ _local_table->do_safepoint_scan(adjust); ++ Thread* thread = Thread::current(); ++ for (int i = 0; i < oops_to_add.length(); i++) { ++ oop mem_name = oops_to_add.at(i); ++ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); + +- java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); +- java_lang_invoke_ResolvedMethodName::set_vmholder_offset(mem_name, newer_method); ++ // The hash table takes ownership of the WeakHandle, even if it's not inserted. + +- newer_klass->set_has_resolved_methods(); +- oops_to_add->append(mem_name); ++ ResolvedMethodTableLookup lookup(thread, method_hash(method), method); ++ ResolvedMethodGet rmg(thread, method); + +- ResourceMark rm; +- if (!(*trace_name_printed)) { +- log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); +- *trace_name_printed = true; +- } +- log_debug(redefine, class, update, constantpool) +- ("ResolvedMethod method update: %s(%s)", +- newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); ++ while (true) { ++ if (_local_table->get(thread, lookup, rmg)) { ++ break; ++ } ++ WeakHandle wh = WeakHandle::create(Handle(thread, mem_name)); ++ // The hash table takes ownership of the WeakHandle, even if it's not inserted. ++ if (_local_table->insert(thread, lookup, wh)) { ++ log_insert(method); ++ wh.resolve(); ++ break; + } +- } +- for (int i = 0; i < oops_to_add->length(); i++) { +- oop mem_name = oops_to_add->at(i); +- Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); +- _the_table->basic_add(method, Handle(Thread::current(), mem_name)); + } + } + } + ++#endif // INCLUDE_JVMTI ++ + // Verification + class VerifyResolvedMethod : StackObj { + public: +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch b/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch new file mode 100644 index 000000000000..7d07940541a2 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch @@ -0,0 +1,88 @@ +From 5379e56465d3d3930ec7ea91b1c64db2cdf70170 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 22 Nov 2020 12:05:50 +0100 +Subject: [PATCH 23/34] dcevm15 - fix Universe::root_oops_do + +--- + src/hotspot/share/memory/universe.cpp | 38 +++++++++------------------ + 1 file changed, 12 insertions(+), 26 deletions(-) + +diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp +index f6e4253b5a5..8dad437bd51 100644 +--- a/src/hotspot/share/memory/universe.cpp ++++ b/src/hotspot/share/memory/universe.cpp +@@ -39,6 +39,7 @@ + #include "gc/shared/gcConfig.hpp" + #include "gc/shared/gcLogPrecious.hpp" + #include "gc/shared/gcTraceTime.inline.hpp" ++#include "gc/shared/weakProcessor.hpp" + #include "interpreter/interpreter.hpp" + #include "logging/log.hpp" + #include "logging/logStream.hpp" +@@ -75,6 +76,7 @@ + #include "runtime/thread.inline.hpp" + #include "runtime/timerTrace.hpp" + #include "runtime/vmOperations.hpp" ++#include "services/management.hpp" + #include "services/memoryService.hpp" + #include "utilities/align.hpp" + #include "utilities/copy.hpp" +@@ -180,45 +182,29 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { + + // FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects. + void Universe::root_oops_do(OopClosure *oopClosure) { +- +- class AlwaysTrueClosure: public BoolObjectClosure { +- public: +- void do_object(oop p) { ShouldNotReachHere(); } +- bool do_object_b(oop p) { return true; } +- }; +- AlwaysTrueClosure always_true; +- + Universe::oops_do(oopClosure); + // ReferenceProcessor::oops_do(oopClosure); (tw) check why no longer there + JNIHandles::oops_do(oopClosure); // Global (strong) JNI handles + Threads::oops_do(oopClosure, NULL); + ObjectSynchronizer::oops_do(oopClosure); +- // TODO: review, flat profiler was removed in j10 +- // FlatProfiler::oops_do(oopClosure); +- JvmtiExport::oops_do(oopClosure); ++ // (DCEVM) TODO: Check if this is correct? ++ Management::oops_do(oopClosure); ++ OopStorageSet::vm_global()->oops_do(oopClosure); ++ CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); ++ ClassLoaderDataGraph::cld_do(&cld_closure); + + // Now adjust pointers in remaining weak roots. (All of which should + // have been cleared if they pointed to non-surviving objects.) + // Global (weak) JNI handles +- JNIHandles::weak_oops_do(&always_true, oopClosure); ++ WeakProcessor::oops_do(oopClosure); + + CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); + CodeCache::blobs_do(&blobClosure); +- StringTable::oops_do(oopClosure); ++ AOT_ONLY(AOTLoader::oops_do(oopClosure);) ++ // StringTable::oops_do was removed in j15 ++ // StringTable::oops_do(oopClosure); + +- // (DCEVM) TODO: Check if this is correct? +- //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); +- //Management::oops_do(oopClosure); +- //ref_processor()->weak_oops_do(&oopClosure); +- //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); +- +-#if INCLUDE_AOT +- if (UseAOT) { +- AOTLoader::oops_do(oopClosure); +- } +-#endif +- // SO_AllClasses +- SystemDictionary::oops_do(oopClosure); ++ // PSScavenge::reference_processor()->weak_oops_do(oopClosure); + } + + void Universe::oops_do(OopClosure* f) { +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch b/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch new file mode 100644 index 000000000000..1034569627ee --- /dev/null +++ b/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch @@ -0,0 +1,67 @@ +From c6ea68e66d37d70739f7b0ee74131322b4526a68 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 22 Nov 2020 12:03:32 +0100 +Subject: [PATCH 24/34] Cleanup dcevm comments + +--- + src/hotspot/share/classfile/classLoaderDataGraph.hpp | 2 +- + src/hotspot/share/classfile/systemDictionary.hpp | 2 +- + src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- + src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp +index f380aa3fa34..8ce94cccb47 100644 +--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp ++++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp +@@ -104,7 +104,7 @@ class ClassLoaderDataGraph : public AllStatic { + + static void dictionary_classes_do(KlassClosure* klass_closure); + +- // Enhanced class redefinition ++ // (DCEVM) Enhanced class redefinition + static void rollback_redefinition(); + + // VM_CounterDecay iteration support +diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp +index 931e655d631..1019dbd0d04 100644 +--- a/src/hotspot/share/classfile/systemDictionary.hpp ++++ b/src/hotspot/share/classfile/systemDictionary.hpp +@@ -455,7 +455,7 @@ public: + static bool is_well_known_klass(Symbol* class_name); + #endif + +- // Enhanced class redefinition ++ // (DCEVM) Enhanced class redefinition + static void remove_from_hierarchy(InstanceKlass* k); + static void update_constraints_after_redefinition(); + +diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp +index 5c1a09390f1..23fbf715378 100644 +--- a/src/hotspot/share/gc/shared/gcConfig.cpp ++++ b/src/hotspot/share/gc/shared/gcConfig.cpp +@@ -99,7 +99,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { + + void GCConfig::select_gc_ergonomically() { + if (AllowEnhancedClassRedefinition && !UseG1GC) { +- // Enhanced class redefinition only supports serial GC at the moment ++ // (DCEVM) Enhanced class redefinition only supports serial GC at the moment + FLAG_SET_ERGO(UseSerialGC, true); + } else if (os::is_server_class_machine()) { + #if INCLUDE_G1GC +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +index bd5e7d153be..5de375fb888 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp +@@ -78,7 +78,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { + // have any entries. + bool _any_class_has_resolved_methods; + +- // Enhanced class redefinition, affected klasses contain all classes which should be redefined ++ // (DCEVM) Enhanced class redefinition, affected klasses contain all classes which should be redefined + // either because of redefine, class hierarchy or interface change + GrowableArray* _affected_klasses; + +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch b/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch new file mode 100644 index 000000000000..dbc33ff000be --- /dev/null +++ b/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch @@ -0,0 +1,43 @@ +From 507d97966c7145d0ae2533459cc504c7b0d6d5b6 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 22 Nov 2020 18:49:05 +0100 +Subject: [PATCH 25/34] Fix cpCache in not AllowEnhancedClassRedefinition mode + +--- + src/hotspot/share/oops/cpCache.hpp | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp +index 121a13b1dda..64dcf6223f5 100644 +--- a/src/hotspot/share/oops/cpCache.hpp ++++ b/src/hotspot/share/oops/cpCache.hpp +@@ -148,13 +148,13 @@ class ConstantPoolCacheEntry { + void set_bytecode_2(Bytecodes::Code code); + void set_f1(Metadata* f1) { + Metadata* existing_f1 = _f1; // read once +- //assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); ++ assert(AllowEnhancedClassRedefinition || existing_f1 == NULL || existing_f1 == f1, "illegal field change"); + _f1 = f1; + } + void release_set_f1(Metadata* f1); + void set_f2(intx f2) { + intx existing_f2 = _f2; // read once +- //assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); ++ assert(AllowEnhancedClassRedefinition || existing_f2 == 0 || existing_f2 == f2, "illegal field change"); + _f2 = f2; + } + void set_f2_as_vfinal_method(Method* f2) { +@@ -215,7 +215,9 @@ class ConstantPoolCacheEntry { + void initialize_resolved_reference_index(int ref_index) { + assert(_f2 == 0, "set once"); // note: ref_index might be zero also + _f2 = ref_index; +- _flags = 1 << is_resolved_ref_shift; ++ if (AllowEnhancedClassRedefinition) { ++ _flags = 1 << is_resolved_ref_shift; ++ } + } + + void set_field( // sets entry to resolved field state +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch b/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch new file mode 100644 index 000000000000..09c62476de4f --- /dev/null +++ b/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch @@ -0,0 +1,32 @@ +From b516b615c20fafa2094dfb9f4cb08245b26418d0 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 22 Nov 2020 19:51:46 +0100 +Subject: [PATCH 26/34] dcevm15 - add ClassLoaderDataGraph_lock on + ClassLoaderDataGraph::classes_do + +ClassLoaderDataGraph::classes_do need safepoint or lock, +find_sorted_affected_classes is not in safepoint therefore it must be +locked +--- + src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index efaf11e1666..197e1c0029f 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -2063,7 +2063,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { + AffectedKlassClosure closure(_affected_klasses); + // Updated in j10, from original SystemDictionary::classes_do + +- ClassLoaderDataGraph::classes_do(&closure); ++ { ++ MutexLocker mcld(ClassLoaderDataGraph_lock); ++ ClassLoaderDataGraph::classes_do(&closure); ++ } + //ClassLoaderDataGraph::dictionary_classes_do(&closure); + + log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch b/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch new file mode 100644 index 000000000000..9454776c0d92 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch @@ -0,0 +1,29 @@ +From c6498946006879314bdc6218ee72da5d9c88f237 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sat, 28 Nov 2020 19:29:42 +0100 +Subject: [PATCH 27/34] dcevm15 - check if has_nestmate_access_to has newest + host class + +--- + src/hotspot/share/oops/instanceKlass.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp +index 5e40d78a87e..1d9623f2446 100644 +--- a/src/hotspot/share/oops/instanceKlass.cpp ++++ b/src/hotspot/share/oops/instanceKlass.cpp +@@ -445,6 +445,11 @@ bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) { + return false; + } + ++ if (AllowEnhancedClassRedefinition) { ++ // TODO: (DCEVM) check if it correct. It fix problems with lambdas (hidden) ++ cur_host = InstanceKlass::cast(cur_host->newest_version()); ++ } ++ + Klass* k_nest_host = k->nest_host(CHECK_false); + if (k_nest_host == NULL) { + return false; +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch b/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch new file mode 100644 index 000000000000..c2f943ec75aa --- /dev/null +++ b/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch @@ -0,0 +1,24 @@ +From 86c27155386c1c40642c99c63a242d1f5d8601a5 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sat, 28 Nov 2020 19:31:08 +0100 +Subject: [PATCH 28/34] Remove unused fieldType + +--- + src/hotspot/share/classfile/vmSymbols.hpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp +index 6a3b234b222..eb06684a288 100644 +--- a/src/hotspot/share/classfile/vmSymbols.hpp ++++ b/src/hotspot/share/classfile/vmSymbols.hpp +@@ -465,7 +465,6 @@ + template(static_offset_name, "staticOffset") \ + template(static_base_name, "staticBase") \ + template(field_offset_name, "fieldOffset") \ +- template(field_type_name, "fieldType") \ + \ + /* name symbols needed by intrinsics */ \ + \ +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch b/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch new file mode 100644 index 000000000000..66c3844e93f2 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch @@ -0,0 +1,54 @@ +From 025d0d2903963fb79f83cf0d90418783d3ef6813 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 17:18:16 +0100 +Subject: [PATCH 29/34] mark_as_scavengable only alive methods + +--- + .../share/prims/jvmtiEnhancedRedefineClasses.cpp | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index 197e1c0029f..e00fac1f693 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -223,19 +223,21 @@ class FieldCopier : public FieldClosure { + + // TODO: review... + void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { +- ScavengableNMethods::register_nmethod(nm); ++ if (nm->is_alive()) { ++ ScavengableNMethods::register_nmethod(nm); ++ } + } + + void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { + // It should work not only for G1 but also for another GCs, but this way is safer now +- if (!nm->is_zombie() && !nm->is_unloaded()) { ++ if (nm->is_alive()) { + Universe::heap()->unregister_nmethod(nm); + } + } + + void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) { + // It should work not only for G1 but also for another GCs, but this way is safer now +- if (!nm->is_zombie() && !nm->is_unloaded()) { ++ if (nm->is_alive()) { + Universe::heap()->register_nmethod(nm); + } + } +@@ -511,9 +513,9 @@ void VM_EnhancedRedefineClasses::doit() { + flush_dependent_code(thread); + // } + +- // Adjust constantpool caches for all classes that reference methods of the evolved class. +- ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); +- ClassLoaderDataGraph::classes_do(&clear_cpool_cache); ++ // Adjust constantpool caches for all classes that reference methods of the evolved class. ++ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); ++ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); + + // JSR-292 support + if (_any_class_has_resolved_methods) { +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch b/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch new file mode 100644 index 000000000000..20f9c81e6dc5 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch @@ -0,0 +1,28 @@ +From 27aabfefe7d799545049bb81ba19d4ed2ff6379c Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 17:20:11 +0100 +Subject: [PATCH 30/34] dcevm15 - lock on + ClassLoaderDataGraph::rollback_redefinition + +rollback is not in safepoint, therefore must be locked +--- + src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index e00fac1f693..db5fb1c472b 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -1382,7 +1382,9 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne + // Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. + void VM_EnhancedRedefineClasses::rollback() { + log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); ++ ClassLoaderDataGraph_lock->lock(); + ClassLoaderDataGraph::rollback_redefinition(); ++ ClassLoaderDataGraph_lock->unlock(); + + for (int i = 0; i < _new_classes->length(); i++) { + SystemDictionary::remove_from_hierarchy(_new_classes->at(i)); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch b/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch new file mode 100644 index 000000000000..1758fa26919b --- /dev/null +++ b/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch @@ -0,0 +1,28 @@ +From 9b405cb642d5935c39c8dbd522ea2fdecfc29ef3 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 19:59:50 +0100 +Subject: [PATCH 31/34] ResourceMark in G1IterateObjectClosureTask fixing + memory leaks + +G1IterateObjectClosureTask is used only in redefinition full GC run +--- + src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +index a29d2dddc2d..2af6df6c1e4 100644 +--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp ++++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +@@ -2362,6 +2362,9 @@ class G1IterateObjectClosureTask : public AbstractGangTask { + _cl(cl), _g1h(g1h), _hrclaimer(g1h->workers()->active_workers()) { } + + virtual void work(uint worker_id) { ++ Thread *thread = Thread::current(); ++ HandleMark hm(thread); // make sure any handles created are deleted ++ ResourceMark rm(thread); + IterateObjectClosureRegionClosure blk(_cl); + _g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id); + } +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch b/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch new file mode 100644 index 000000000000..e8fbfc04eeac --- /dev/null +++ b/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch @@ -0,0 +1,91 @@ +From 40fe40884d4efc50864bb3f2dd88f0a2e7122d5a Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 20:05:03 +0100 +Subject: [PATCH 32/34] dcevm15 - fix hidded classes + +--- + .../prims/jvmtiEnhancedRedefineClasses.cpp | 41 ++++++++++++++----- + 1 file changed, 30 insertions(+), 11 deletions(-) + +diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +index db5fb1c472b..590f7fdfafe 100644 +--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp ++++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp +@@ -722,7 +722,8 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { + } + + // Cannot redefine or retransform an anonymous class. +- if (InstanceKlass::cast(k)->is_unsafe_anonymous()) { ++ // TODO: check if is correct in j15 ++ if (InstanceKlass::cast(k)->is_unsafe_anonymous() || InstanceKlass::cast(k)->is_hidden()) { + return false; + } + return true; +@@ -808,21 +809,27 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + + InstanceKlass* k; + +- if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) { +- const InstanceKlass* host_class = the_class->unsafe_anonymous_host(); ++ if (the_class->is_unsafe_anonymous() || the_class->is_hidden()) { ++ InstanceKlass* dynamic_host_class = NULL; ++ InstanceKlass* unsafe_anonymous_host = NULL; + +- // Make sure it's the real host class, not another anonymous class. +- while (host_class != NULL && host_class->is_unsafe_anonymous()) { +- host_class = host_class->unsafe_anonymous_host(); ++ if (the_class->is_hidden()) { ++ log_debug(redefine, class, load)("loading hidden class %s", the_class->name()->as_C_string()); ++ dynamic_host_class = the_class->nest_host(THREAD); ++ } ++ ++ if (the_class->is_unsafe_anonymous()) { ++ log_debug(redefine, class, load)("loading usafe anonymous %s", the_class->name()->as_C_string()); ++ unsafe_anonymous_host = the_class->unsafe_anonymous_host(); + } + + ClassLoadInfo cl_info(protection_domain, +- host_class, +- NULL, // dynamic_nest_host ++ unsafe_anonymous_host, + NULL, // cp_patches ++ dynamic_host_class, // dynamic_nest_host + Handle(), // classData +- false, // is_hidden +- false, // is_strong_hidden ++ the_class->is_hidden(), // is_hidden ++ !the_class->is_non_strong_hidden(), // is_strong_hidden + true); // FIXME: check if correct. can_access_vm_annotations + + k = SystemDictionary::parse_stream(the_class_sym, +@@ -833,7 +840,17 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { + THREAD); + + k->class_loader_data()->exchange_holders(the_class->class_loader_data()); +- the_class->class_loader_data()->inc_keep_alive(); ++ ++ if (the_class->is_hidden()) { ++ // from jvm_lookup_define_class() (jvm.cpp): ++ // The hidden class loader data has been artificially been kept alive to ++ // this point. The mirror and any instances of this class have to keep ++ // it alive afterwards. ++ the_class->class_loader_data()->dec_keep_alive(); ++ } else { ++ the_class->class_loader_data()->inc_keep_alive(); ++ } ++ + } else { + k = SystemDictionary::resolve_from_stream(the_class_sym, + the_class_loader, +@@ -1475,6 +1492,8 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { + ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version())); + } + ++ // FIXME: check new nest_host for hidden ++ + // Update implementor if there is only one, in this case implementor() can reference old class + if (ik->is_interface()) { + Klass* implKlass = ik->implementor(); +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch b/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch new file mode 100644 index 000000000000..f303ca4fa0a3 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch @@ -0,0 +1,27 @@ +From 29920b076b4ad96d85adbce0a1d947e5022ba3ad Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 20:08:57 +0100 +Subject: [PATCH 33/34] dcevm15 - DON'T clear F2 in CP cache after indy + unevolving + +It's not clear why it was cleared in dcevm7-11 +--- + src/hotspot/share/oops/cpCache.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp +index 79a38dbeff0..650e6fab42d 100644 +--- a/src/hotspot/share/oops/cpCache.cpp ++++ b/src/hotspot/share/oops/cpCache.cpp +@@ -650,7 +650,7 @@ void ConstantPoolCacheEntry::clear_entry() { + + if (clearData) { + if (!is_resolved_reference()) { +- _f2 = 0; ++ // _f2 = 0; + } + // FIXME: (DCEVM) we want to clear flags, but parameter size is actually used + // after we return from the method, before entry is re-initialized. So let's +-- +2.23.0 + diff --git a/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch b/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch new file mode 100644 index 000000000000..0fb5efa03e18 --- /dev/null +++ b/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch @@ -0,0 +1,49 @@ +From 1f13b20ab5553182680045b7d7324ff92da7e7f0 Mon Sep 17 00:00:00 2001 +From: Vladimir Dvorak +Date: Sun, 29 Nov 2020 21:28:06 +0100 +Subject: [PATCH 34/34] dcevm15 - fix Universe::root_oops_do + +Removed ClassLoaderDataGraph::cld_do was cause of crashes due multiple +oop patching. ClassLoaderDataGraph::cld_do replaced in dcevm15 +previously used and removed SystemDictionary:oops_do +--- + src/hotspot/share/memory/universe.cpp | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp +index 8dad437bd51..0199962a684 100644 +--- a/src/hotspot/share/memory/universe.cpp ++++ b/src/hotspot/share/memory/universe.cpp +@@ -190,21 +190,26 @@ void Universe::root_oops_do(OopClosure *oopClosure) { + // (DCEVM) TODO: Check if this is correct? + Management::oops_do(oopClosure); + OopStorageSet::vm_global()->oops_do(oopClosure); +- CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); +- ClassLoaderDataGraph::cld_do(&cld_closure); ++ // CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); ++ // ClassLoaderDataGraph::cld_do(&cld_closure); + + // Now adjust pointers in remaining weak roots. (All of which should + // have been cleared if they pointed to non-surviving objects.) + // Global (weak) JNI handles + WeakProcessor::oops_do(oopClosure); + ++ JvmtiExport::oops_do(oopClosure); ++ + CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); + CodeCache::blobs_do(&blobClosure); ++ + AOT_ONLY(AOTLoader::oops_do(oopClosure);) ++ + // StringTable::oops_do was removed in j15 + // StringTable::oops_do(oopClosure); + +- // PSScavenge::reference_processor()->weak_oops_do(oopClosure); ++ // OopStorageSet::vm_global()->oops_do(oopClosure); ++ + } + + void Universe::oops_do(OopClosure* f) { +-- +2.23.0 + From 061ee29c2e72a74cdaa99d23d51b28085cc2a183 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 2 Dec 2020 18:14:55 +0700 Subject: [PATCH 036/976] JBR-2912 add JBR 15 builds with DCEVM --- jb/project/tools/common/scripts/common.sh | 6 ++++++ jb/project/tools/linux/scripts/mkimages_x64.sh | 10 ++++++++-- jb/project/tools/mac/scripts/mkimages.sh | 10 ++++++++-- jb/project/tools/windows/scripts/mkimages_x64.sh | 8 +++++++- jb/project/tools/windows/scripts/pack_x64.sh | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index fa1b3506a6f1..01df77fae086 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -3,9 +3,15 @@ VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${buil [ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" do_reset_changes=0 +do_reset_dcevm=0 +HEAD_REVISION=0 + function do_exit() { exit_code=$1 [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + if [ $do_reset_dcevm -eq 1 ]; then + [ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION + fi exit "$exit_code" } diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 3de7497484a1..f65e3dd07bae 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -62,6 +62,12 @@ case "$bundle_type" in "jcef") do_reset_changes=1 ;; + "dcevm") + HEAD_REVISION=$(git rev-parse HEAD) + git am jb/project/tools/patches/dcevm/*.patch || do_exit $? + do_reset_dcevm=1 + do_reset_changes=1 + ;; "nomod" | "") bundle_type="" ;; @@ -94,7 +100,7 @@ JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed @@ -108,7 +114,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 218faa1f837e..289afb02d5a7 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -67,6 +67,12 @@ case "$bundle_type" in "jcef") do_reset_changes=1 ;; + "dcevm") + HEAD_REVISION=$(git rev-parse HEAD) + git am jb/project/tools/patches/dcevm/*.patch || do_exit $? + do_reset_dcevm=1 + do_reset_changes=1 + ;; "nomod" | "") bundle_type="" ;; @@ -96,7 +102,7 @@ JSDK=$IMAGES_DIR/jdk-bundle/jdk-$MAJOR_JBSDK_VERSION.jdk/Contents/Home JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed @@ -110,7 +116,7 @@ create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exi # create sdk image bundle modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index c7ff8355468e..b4358129e3da 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -51,6 +51,12 @@ case "$bundle_type" in "jcef") do_reset_changes=1 ;; + "dcevm") + HEAD_REVISION=$(git rev-parse HEAD) + git am jb/project/tools/patches/dcevm/*.patch || do_exit $? + do_reset_dcevm=1 + do_reset_changes=1 + ;; "nomod" | "") bundle_type="" ;; @@ -85,7 +91,7 @@ JSDK=$IMAGES_DIR/jdk JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 8ea40e1aee63..6be07efc3ab3 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -61,7 +61,7 @@ JSDK=$IMAGES_DIR/jdk JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then JBRSDK_BUNDLE=jbrsdk echo Creating $JBSDK.tar.gz ... [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" From e758458c039cc74f069f89e2cb98e6784dcb67a1 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 6 Dec 2020 07:59:01 +0700 Subject: [PATCH 037/976] JBR-2922 add JCEF to jbrsdk binaries & fix a misprint in get_mods_list JBR-2922 add JCEF to jbrsdk binaries & fix a misprint in get_mods_list --- jb/project/tools/common/scripts/common.sh | 3 +-- .../tools/linux/scripts/mkimages_x64.sh | 12 ++++++--- jb/project/tools/mac/scripts/mkimages.sh | 25 ++++++++++++------- .../tools/windows/scripts/mkimages_x64.sh | 8 +++++- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 01df77fae086..e4c3080f7569 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -50,6 +50,5 @@ function update_jsdk_mods() { function get_mods_list() { __mods=$1 - - return `ls "$__mods"` | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g + echo $(ls $__mods) | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g } diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index f65e3dd07bae..dc28ce18ce69 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -36,7 +36,7 @@ function create_image_bundle { __modules_path=$3 __modules=$4 - [ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-" + [ "$bundle_type" == "fd" ] && [ "$__bundle_name" == "$JBRSDK_BUNDLE" ] && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number} echo Running jlink.... @@ -45,6 +45,12 @@ function create_image_bundle { --module-path "$__modules_path" --no-man-pages --compress=2 \ --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release + mv release "$IMAGES_DIR"/"$__arch_name"/release + fi + # jmod does not preserve file permissions (JDK-8173610) [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper @@ -113,8 +119,8 @@ modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle -modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 289afb02d5a7..79cc4b1c0fd1 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -34,16 +34,17 @@ source jb/project/tools/common/scripts/common.sh function create_image_bundle { __bundle_name=$1 - __modules_path=$2 - __modules=$3 + __arch_name=$2 + __modules_path=$3 + __modules=$4 tmp=.bundle.$$.tmp mkdir "$tmp" || do_exit $? - [ "$bundle_type" == "fd" ] && fastdebug_infix="fastdebug-" + [ "$bundle_type" == "fd" ] && [ "$__bundle_name" == "$JBRSDK_BUNDLE" ] && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-osx-x64-${fastdebug_infix}b${build_number} - JRE_CONTENTS=$tmp/$__bundle_name/Contents + JRE_CONTENTS=$tmp/$__arch_name/Contents mkdir -p "$JRE_CONTENTS" || do_exit $? echo Running jlink... @@ -51,12 +52,18 @@ function create_image_bundle { --module-path "$__modules_path" --no-man-pages --compress=2 \ --add-modules "$__modules" --output "$JRE_CONTENTS/Home" || do_exit $? + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$JRE_CONTENTS/Home/release" + if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release + mv release $JRE_CONTENTS/Home/release + fi + cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" cp "$JSDK"/../Info.plist "$JRE_CONTENTS" [ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?) echo Creating "$JBR".tar.gz ... - COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__bundle_name" || do_exit $? + COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__arch_name" || do_exit $? rm -rf "$tmp" } @@ -112,14 +119,14 @@ fi # create runtime image bundle modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? -create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle -modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi -create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? +create_image_bundle "$JBRSDK_BUNDLE" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? if [ -z "$bundle_type" ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-x64-b${build_number} diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index b4358129e3da..40654c6ce135 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -42,6 +42,12 @@ function create_image_bundle { ${JSDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ --add-modules $__modules --output $__bundle_name || do_exit $? + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__bundle_name/release + if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $__bundle_name/release > release + mv release $__bundle_name/release + fi } WITH_DEBUG_LEVEL="--with-debug-level=release" @@ -105,7 +111,7 @@ create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exi # create sdk image bundle modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? From 6643fab9f0bfe4237f374a78a713ebf4f000bd65 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 20 Apr 2021 14:29:01 +0700 Subject: [PATCH 038/976] JBR-3305 remove the option --disable-warnings-as-errors from configure --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 1 - jb/project/tools/linux/scripts/mkimages_x64.sh | 1 - jb/project/tools/linux/scripts/mkimages_x86.sh | 1 - jb/project/tools/mac/scripts/mkimages.sh | 1 - jb/project/tools/windows/scripts/mkimages_x64.sh | 1 - jb/project/tools/windows/scripts/mkimages_x86.sh | 1 - 6 files changed, 6 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index ef69a24103d5..ce4854af21a4 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -27,7 +27,6 @@ JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} [ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) sh configure \ - --disable-warnings-as-errors \ --with-debug-level=release \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index dc28ce18ce69..062fa9db434c 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -85,7 +85,6 @@ case "$bundle_type" in esac sh configure \ - --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 1f7d11f8153b..69278d653dfb 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -27,7 +27,6 @@ JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} [ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) linux32 bash configure \ - --disable-warnings-as-errors \ --with-debug-level=release \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 79cc4b1c0fd1..f7b296a58650 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -91,7 +91,6 @@ case "$bundle_type" in esac sh configure \ - --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 40654c6ce135..fb036d959d65 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -74,7 +74,6 @@ case "$bundle_type" in esac sh ./configure \ - --disable-warnings-as-errors \ $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 27ac68a46094..d4041e37634c 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -29,7 +29,6 @@ WORK_DIR=$(pwd) PATH="/usr/local/bin:/usr/bin:${PATH}" ./configure \ - --disable-warnings-as-errors \ --with-target-bits=32 \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ From 3228305657fb6faa720d7c24b9a7a05480b5de84 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 29 Apr 2021 19:29:06 +0700 Subject: [PATCH 039/976] JBR-3401 enable macos-aarhc64 builds --- jb/project/tools/mac/scripts/mkimages.sh | 69 ++++++++++++++++++------ jb/project/tools/mac/scripts/sign.sh | 23 ++++++-- jb/project/tools/mac/scripts/signapp.sh | 16 +++--- 3 files changed, 77 insertions(+), 31 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index f7b296a58650..b85d572682b0 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -25,13 +25,23 @@ JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 bundle_type=$4 -JBSDK_VERSION_WITH_DOTS=$(echo "$JBSDK_VERSION" | sed 's/_/\./g') +architecture=$5 # aarch64 or x64 +enable_aot=$6 # temporary param for building test jre with aot under aarch64 +JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" JCEF_PATH=${JCEF_PATH:=./jcef_mac} +architecture=${architecture:=x64} MAJOR_JBSDK_VERSION=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}') -BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 14)} +BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)} source jb/project/tools/common/scripts/common.sh +function copyJNF { + __contents_dir=$1 + mkdir -p ${__contents_dir}/Frameworks + cp -Rp Frameworks/JavaNativeFoundation.framework ${__contents_dir}/Frameworks +} + function create_image_bundle { __bundle_name=$1 __arch_name=$2 @@ -42,7 +52,7 @@ function create_image_bundle { mkdir "$tmp" || do_exit $? [ "$bundle_type" == "fd" ] && [ "$__bundle_name" == "$JBRSDK_BUNDLE" ] && fastdebug_infix="fastdebug-" - JBR=${__bundle_name}-${JBSDK_VERSION}-osx-x64-${fastdebug_infix}b${build_number} + JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix}b${build_number} JRE_CONTENTS=$tmp/$__arch_name/Contents mkdir -p "$JRE_CONTENTS" || do_exit $? @@ -60,6 +70,13 @@ function create_image_bundle { cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" cp "$JSDK"/../Info.plist "$JRE_CONTENTS" + + if [[ "${architecture}" == *aarch64* ]]; then + # we can't notarize this library as usual framework (with headers and tbd-file) + # but single library notarizes correctly + copyJNF $JRE_CONTENTS + fi + [ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?) echo Creating "$JBR".tar.gz ... @@ -68,7 +85,11 @@ function create_image_bundle { } WITH_DEBUG_LEVEL="--with-debug-level=release" -RELEASE_NAME=macosx-x86_64-server-release +CONF_ARCHITECTURE=x86_64 +if [[ "${architecture}" == *aarch64* ]]; then + CONF_ARCHITECTURE=aarch64 +fi +RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-release case "$bundle_type" in "jcef") @@ -86,20 +107,36 @@ case "$bundle_type" in "fd") do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" - RELEASE_NAME=macosx-x86_64-server-fastdebug + RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-fastdebug + JBSDK=macosx-${architecture}-server-release ;; esac -sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="$VENDOR_NAME" \ - --with-vendor-version-string="$VENDOR_VERSION_STRING" \ - --with-version-pre= \ - --with-version-build="$JDK_BUILD_NUMBER" \ - --with-version-opt=b"$build_number" \ - --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes || do_exit $? - +if [[ "${architecture}" == *aarch64* ]]; then + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-version-pre= \ + --with-version-build="${JDK_BUILD_NUMBER}" \ + --with-version-opt=b"${build_number}" \ + --with-boot-jdk="$BOOT_JDK" \ + --disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \ + --enable-cds=no \ + --with-extra-cflags="-F$(pwd)/Frameworks" \ + --with-extra-cxxflags="-F$(pwd)/Frameworks" \ + --with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $? +else + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + --enable-cds=yes || do_exit $? +fi make clean CONF=$RELEASE_NAME || do_exit $? make images CONF=$RELEASE_NAME || do_exit $? @@ -128,7 +165,7 @@ fi create_image_bundle "$JBRSDK_BUNDLE" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? if [ -z "$bundle_type" ]; then - JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-x64-b${build_number} + JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number} echo Creating "$JBRSDK_TEST" ... make test-image CONF=$RELEASE_NAME || do_exit $? [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index d9f9f646a57b..0b2ee825a53a 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -26,17 +26,30 @@ log "Signing libraries and executables..." # -perm +111 searches for executables for f in \ "Contents/Home/bin" \ - "Contents/Home/lib" \ - "Contents/Frameworks"; do + "Contents/Home/lib"; do if [ -d "$APP_DIRECTORY/$f" ]; then find "$APP_DIRECTORY/$f" \ -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ - -exec codesign --timestamp \ + -exec codesign --timestamp --force \ -v -s "$JB_CERT" --options=runtime \ --entitlements entitlements.xml {} \; fi done +if [ -d "$APP_DIRECTORY/Contents/Frameworks" ]; then + log "Signing frameworks..." + for f in $APP_DIRECTORY/Contents/Frameworks/*; do + find "$f" \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" \) \ + -exec codesign --timestamp --force \ + -v -s "$JB_CERT" \ + --entitlements entitlements.xml {} \; + codesign --timestamp --force \ + -v -s "$JB_CERT" --options=runtime \ + --entitlements entitlements.xml "$f" + done +fi + log "Signing libraries in jars in $PWD" # todo: add set -euo pipefail; into the inner sh -c @@ -55,7 +68,7 @@ find "$APP_DIRECTORY" -name '*.jar' \ find jarfolder \ -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \ - -exec codesign --timestamp \ + -exec codesign --timestamp --force \ -v -s "$JB_CERT" --options=runtime \ --entitlements entitlements.xml {} \; @@ -71,7 +84,7 @@ for f in \ if [ -d "$APP_DIRECTORY/$f" ]; then find "$APP_DIRECTORY/$f" \ -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ - -exec codesign --timestamp \ + -exec codesign --timestamp --force \ -v -s "$JB_CERT" --options=runtime \ --entitlements entitlements.xml {} \; fi diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index 04ea4ef93807..518e41d50b05 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x #immediately exit script with an error if a command fails set -euo pipefail @@ -32,17 +32,13 @@ mkdir "$BACKUP_JMODS" log "Unzipping $INPUT_FILE to $EXPLODED ..." tar -xzvf "$INPUT_FILE" --directory $EXPLODED -rm "$INPUT_FILE" BUILD_NAME="$(ls "$EXPLODED")" +sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist +rm -f $EXPLODED/$BUILD_NAME/Contents/CodeResources +rm "$INPUT_FILE" if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then mv $EXPLODED/$BUILD_NAME/Contents/Home/jmods $BACKUP_JMODS fi -if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then - mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS -fi -if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then - mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS -fi log "$INPUT_FILE extracted and removed" @@ -131,8 +127,8 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..." mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home fi - COPYFILE_DISABLE=1 tar -pczf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME + tar -pczvf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME log "Finished zipping" ) rm -rf "$EXPLODED" -log "Done" +log "Done" \ No newline at end of file From 32dcb4a79268e8b2ba1a6aebe770556b5b7272f4 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 23 Mar 2021 17:26:25 +0300 Subject: [PATCH 040/976] Add build.gradle --- jb/project/java-gradle/build.gradle | 135 ++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 jb/project/java-gradle/build.gradle diff --git a/jb/project/java-gradle/build.gradle b/jb/project/java-gradle/build.gradle new file mode 100644 index 000000000000..c5d18ab682ef --- /dev/null +++ b/jb/project/java-gradle/build.gradle @@ -0,0 +1,135 @@ +apply plugin: 'java' +import org.gradle.internal.os.OperatingSystem + +repositories { + mavenCentral() +} + +def test_jvm = { + if (project.hasProperty('jbsdkhome')) { + file(jbsdkhome + (OperatingSystem.current().isWindows()?"/bin/java.exe" : "/bin/java")).absolutePath + } else { + if (OperatingSystem.current().isMacOsX()) { + file('../../../build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-11.0.4.jdk/Contents/Home/bin/java').absolutePath + } else if (OperatingSystem.current().isLinux()) { + file('../../../build/linux-x86_64-normal-server-release/images/jdk/bin/java').absolutePath + } else { + file('../../../build/windows-x86_64-normal-server-release/images/jdk/bin/java.exe').absolutePath + } + } +} + +dependencies { + testCompile('junit:junit:4.12'){ + exclude group: 'org.hamcrest' + } + testCompile 'org.hamcrest:hamcrest-library:1.3' + testCompile 'net.java.dev.jna:jna:4.4.0' + testCompile 'com.twelvemonkeys.imageio:imageio-tiff:3.3.2' + testCompile 'org.apache.commons:commons-lang3:3.0' +} + +def jdk_modules = ["java.base", "java.logging", "java.prefs", + "java.se.ee", "java.sql", "java.datatransfer", + "java.management", "java.rmi", "java.security.jgss", + "java.sql.rowset", "java.desktop", "java.management.rmi", + "java.scripting", "java.security.sasl", "java.transaction", + "java.instrument", "java.naming", "java.se", + "java.smartcardio", "java.xml.crypto"] + +def jdk_class_dirs = [] + +jdk_modules.collect(jdk_class_dirs) { + new File("../../../src/" + it + "/share/classes") +} + +if (OperatingSystem.current().isMacOsX()) + jdk_modules.collect(jdk_class_dirs) { + "../../../src/" + it + "/macosx/classes" + } +else if (OperatingSystem.current().isLinux()) { + jdk_modules.collect(jdk_class_dirs) { + "../../../src/" + it + "/solaris/classes" + } + jdk_modules.collect(jdk_class_dirs) { + "../../../src/" + it + "/unix/classes" + } +} else + jdk_modules.collect(jdk_class_dirs) { + "../../../src/" + it + "/windows/classes" + } + +sourceSets.main.java.srcDirs = jdk_class_dirs + +sourceSets { + test { + java { + srcDir "../../../test/jdk/jbu" + } + } +} + +test.dependsOn.clear() + +test.dependsOn tasks.compileTestJava + +test { + systemProperty "jb.java2d.metal", "true" + systemProperty "testdata", file('../../../test/jdk/jbu/testdata').absolutePath + +// Generate golden images for DroidFontTest and MixedTextTest +// systemProperty "gentestdata", "" + +// Enable Java2D logging (https://confluence.jetbrains.com/display/JRE/Java2D+Rendering+Logging) +// systemProperty "sun.java2d.trace", "log" +// systemProperty "sun.java2d.trace", "log,pimpl" + + outputs.upToDateWhen { false } + executable = test_jvm() + +// Enable async/dtrace profiler + jvmArgs "-XX:+PreserveFramePointer" +// Enable native J2D logging (only in debug build) +// Can be turned on for J2D by adding "#define DEBUG 1" into jdk/src/share/native/sun/java2d/Trace.h + +// environment 'J2D_TRACE_LEVEL', '4' +} + +def buildDir = project.buildscript.sourceFile.parentFile.parentFile.parentFile.parentFile + +def make_cmd = "make" +if (OperatingSystem.current().isWindows()) { + def cyg_make_cmd = new File("c:/cygwin64/bin/make.exe") + if (cyg_make_cmd.exists()) make_cmd = cyg_make_cmd.absolutePath +} +def test_run = false +task make_images { + doLast { + if (!test_run) { + def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "images") + def proc = pb.redirectErrorStream(true).start() + proc.inputStream.eachLine { println it } + assert proc.waitFor() == 0 + } + } +} + +task make_clean { + doLast { + def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "clean") + def proc = pb.redirectErrorStream(true).start() + proc.inputStream.eachLine { println it } + assert proc.waitFor() == 0 + } +} + +task run_test { + doLast { + test_run = true + } +} + +tasks.cleanTest.dependsOn tasks.run_test +classes.dependsOn.clear() +classes.dependsOn tasks.make_images +tasks.cleanClasses.dependsOn tasks.make_clean From 72e9ec0195681de449c20cba4b95b004e2560a62 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sat, 24 Apr 2021 05:49:55 +0700 Subject: [PATCH 041/976] configure BOOT_JDK to use JDK 16 --- jb/project/docker/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jb/project/docker/Dockerfile b/jb/project/docker/Dockerfile index f14c47fb5321..fb02f1c9d28a 100644 --- a/jb/project/docker/Dockerfile +++ b/jb/project/docker/Dockerfile @@ -3,11 +3,11 @@ FROM centos:7 RUN yum -y install centos-release-scl RUN yum -y install devtoolset-8 RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool gcc gcc-c++ libstdc++-devel alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel git -# Install Java 15 -RUN wget https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz \ --O - | tar xz -C / -RUN mv /zulu15.27.17-ca-jdk15.0.0-linux_x64 /jdk15.0.0 +# Install Java 16 +RUN wget https://cdn.azul.com/zulu/bin/zulu16.28.11-ca-jdk16.0.0-linux_x64.tar.gz \ + -O - | tar xz -C / +RUN mv /zulu16.28.11-ca-jdk16.0.0-linux_x64 /jdk16.0.0 ENV PATH /opt/rh/devtoolset-8/root/usr/bin:$PATH RUN mkdir .git -RUN git config user.email "builduser@jetbrains.com" +RUN git config user.email "teamcity@jetbrains.com" RUN git config user.name "builduser" From 47d77144980c41ed866756a7a0afb9220bfddceb Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 11 Dec 2020 17:08:27 +0700 Subject: [PATCH 042/976] JBR-667 add shenandoahgc feature (cherry picked from commit e15dad04) --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 5 +++-- jb/project/tools/linux/scripts/mkimages_x64.sh | 1 + jb/project/tools/mac/scripts/mkimages.sh | 2 ++ jb/project/tools/windows/scripts/mkimages_x64.sh | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index ce4854af21a4..afdc34118611 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -30,8 +30,9 @@ sh configure \ --with-debug-level=release \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-jvm-features=shenandoahgc \ --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ + --with-version-build="${JDK_BUILD_NUMBER}" \ --with-version-opt=b${build_number} \ --with-boot-jdk=${BOOT_JDK} \ --enable-cds=yes || exit $? @@ -67,7 +68,7 @@ grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules echo Running jlink.... ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/,$//g) \ + --add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/',$'//g) \ --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? echo Modifying release info ... diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 062fa9db434c..d0e9d6b0aae8 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -88,6 +88,7 @@ sh configure \ $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build="$JDK_BUILD_NUMBER" \ --with-version-opt=b"$build_number" \ diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index b85d572682b0..4a08d003d7b5 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -117,6 +117,7 @@ if [[ "${architecture}" == *aarch64* ]]; then $WITH_DEBUG_LEVEL \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build="${JDK_BUILD_NUMBER}" \ --with-version-opt=b"${build_number}" \ @@ -131,6 +132,7 @@ else $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build="$JDK_BUILD_NUMBER" \ --with-version-opt=b"$build_number" \ diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index fb036d959d65..f94483afcd17 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -77,6 +77,7 @@ sh ./configure \ $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build=$JDK_BUILD_NUMBER \ --with-version-opt=b${build_number} \ @@ -109,7 +110,7 @@ modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle -modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/,/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) +modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi From 5f894d6b792b1b52fcd20e2bd2f356e52fe1a2bb Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 20 Dec 2020 14:49:47 +0700 Subject: [PATCH 043/976] JBR-2957 notarize JBR and JBRSDK as APPL (cherry picked from commit 0e7f9ce4cadd6b3ad68a8d2eda7c9c5a92cae309) --- jb/project/tools/mac/scripts/notarize.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jb/project/tools/mac/scripts/notarize.sh b/jb/project/tools/mac/scripts/notarize.sh index fa95c1b165b2..ded48e12d1de 100755 --- a/jb/project/tools/mac/scripts/notarize.sh +++ b/jb/project/tools/mac/scripts/notarize.sh @@ -58,7 +58,7 @@ file="$APP_NAME.zip" log "Zipping $file..." rm -rf "$file" -ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY/Contents" "$file" +ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file" log "Notarizing $file..." rm -rf "altool.init.out" "altool.check.out" From 8770a6d941c15ff9bb169425c85a26ab82d358b1 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 2 Mar 2021 05:27:55 +0700 Subject: [PATCH 044/976] JBR-1505 add jdk.jcmd module into JBR (cherry picked from commit c40b9c8b9e5e5f34c956effa8e09fd0264ff5969) --- jb/project/tools/patches/add_jcef_module.patch | 14 +++++++------- modules.list | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/jb/project/tools/patches/add_jcef_module.patch b/jb/project/tools/patches/add_jcef_module.patch index 6a793bc64987..d28deca1f2c3 100644 --- a/jb/project/tools/patches/add_jcef_module.patch +++ b/jb/project/tools/patches/add_jcef_module.patch @@ -1,21 +1,21 @@ diff --git modules.list modules.list -index 7c4b3e9cb6d..5ed60349ca7 100644 +index 054f21d1ee0..d9a121f0273 100644 --- modules.list +++ modules.list -@@ -53,4 +53,7 @@ jdk.security.jgss, - jdk.unsupported, +@@ -49,4 +49,7 @@ jdk.unsupported, jdk.xml.dom, jdk.zipfs, --jdk.hotspot.agent -+jdk.hotspot.agent, + jdk.hotspot.agent, +-jdk.jcmd ++jdk.jcmd, +jcef, +gluegen.rt, +jogl.all diff --git src/java.desktop/share/classes/module-info.java src/java.desktop/share/classes/module-info.java -index b663b382f52..3e9acdc0c27 100644 +index 897647ee368..781d1809493 100644 --- src/java.desktop/share/classes/module-info.java +++ src/java.desktop/share/classes/module-info.java -@@ -109,7 +109,11 @@ module java.desktop { +@@ -116,7 +116,11 @@ module java.desktop { // see make/GensrcModuleInfo.gmk exports sun.awt to jdk.accessibility, diff --git a/modules.list b/modules.list index e23d793ca612..33375b527c49 100644 --- a/modules.list +++ b/modules.list @@ -54,4 +54,5 @@ jdk.security.jgss, jdk.unsupported, jdk.xml.dom, jdk.zipfs, -jdk.hotspot.agent +jdk.hotspot.agent, +jdk.jcmd From f7f9377138b239bf5608031a396031b046c75b65 Mon Sep 17 00:00:00 2001 From: "Vitaly.Provodin" Date: Thu, 19 Dec 2019 06:30:59 +0300 Subject: [PATCH 045/976] add dockerfile for x86 (cherry picked from commit 8fb2341ea8ae3243f3bcb45b18028a694337febe) --- jb/project/docker/Dockerfile.x86 | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 jb/project/docker/Dockerfile.x86 diff --git a/jb/project/docker/Dockerfile.x86 b/jb/project/docker/Dockerfile.x86 new file mode 100644 index 000000000000..146da91e7983 --- /dev/null +++ b/jb/project/docker/Dockerfile.x86 @@ -0,0 +1,7 @@ +FROM i386/ubuntu:xenial + +RUN linux32 apt-get update && apt-get install -y --no-install-recommends apt-utils +COPY jbrsdk-11.0.5-b1 /jbrsdk-11.0.5-b1 +RUN linux32 apt-get -y install file build-essential zip unzip curl libx11-dev libxext-dev \ + libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libasound2-data \ + libpng12-0 libasound2 libfreetype6 libfontconfig1-dev libasound2-dev autoconf From e3a2c494a64018502d51890b3558d8fb98822ff8 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 20 Jul 2021 19:19:54 +0300 Subject: [PATCH 046/976] JBR-3627 include jmods in jbrsdk bundle for jbr-dev --- jb/project/tools/common/scripts/common.sh | 10 ++++++++++ jb/project/tools/linux/scripts/mkimages_x64.sh | 1 + jb/project/tools/mac/scripts/mkimages.sh | 1 + jb/project/tools/windows/scripts/mkimages_x64.sh | 1 + 4 files changed, 13 insertions(+) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index e4c3080f7569..fe642270fa70 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -52,3 +52,13 @@ function get_mods_list() { __mods=$1 echo $(ls $__mods) | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g } + +function copy_jmods() { + __mods_list=$1 + __jmods_from=$2 + __jmods_to=$3 + + mkdir -p $__jmods_to + + echo "${__mods_list}," | while read -d, mod; do cp $__jmods_from/$mod.jmod $__jmods_to/; done +} diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index d0e9d6b0aae8..14a429559cd8 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -49,6 +49,7 @@ function create_image_bundle { if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release mv release "$IMAGES_DIR"/"$__arch_name"/release + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods fi # jmod does not preserve file permissions (JDK-8173610) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 4a08d003d7b5..759ee97ab91e 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -66,6 +66,7 @@ function create_image_bundle { if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release mv release $JRE_CONTENTS/Home/release + copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods fi cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index f94483afcd17..f109387b41e3 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -47,6 +47,7 @@ function create_image_bundle { if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $__bundle_name/release > release mv release $__bundle_name/release + copy_jmods "$__modules" "$__modules_path" "$__bundle_name"/jmods fi } From 36684a575d016fce6a20e75ffdc97e2e155ea84e Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 3 Jun 2022 05:35:14 +0700 Subject: [PATCH 047/976] JBR-3639 add jbrsdk tarballs for dcevm, jcef builds --- .../tools/linux/scripts/mkimages_x64.sh | 15 ++++--- jb/project/tools/mac/scripts/mkimages.sh | 14 +++--- .../tools/windows/scripts/mkimages_x64.sh | 31 ++++++------- jb/project/tools/windows/scripts/pack_x64.sh | 43 ++++++------------- 4 files changed, 43 insertions(+), 60 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 14a429559cd8..6b725ee7705e 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -36,7 +36,7 @@ function create_image_bundle { __modules_path=$3 __modules=$4 - [ "$bundle_type" == "fd" ] && [ "$__bundle_name" == "$JBRSDK_BUNDLE" ] && fastdebug_infix="fastdebug-" + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number} echo Running jlink.... @@ -46,7 +46,7 @@ function create_image_bundle { --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release - if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release mv release "$IMAGES_DIR"/"$__arch_name"/release copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods @@ -67,19 +67,19 @@ RELEASE_NAME=linux-x86_64-server-release case "$bundle_type" in "jcef") - do_reset_changes=1 + do_reset_changes=0 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=1 - do_reset_changes=1 + do_reset_dcevm=0 + do_reset_changes=0 ;; "nomod" | "") bundle_type="" ;; "fd") - do_reset_changes=1 + do_reset_changes=0 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=linux-x86_64-server-fastdebug ;; @@ -113,6 +113,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed jbr_name_postfix="_${bundle_type}" + [ "$bundle_type" != "fd" ] && jbrsdk_name_postfix="_${bundle_type}" fi # create runtime image bundle @@ -124,7 +125,7 @@ modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi -create_image_bundle $JBRSDK_BUNDLE $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? if [ -z "$bundle_type" ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number} diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 759ee97ab91e..ab6c7e5c595b 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -51,7 +51,7 @@ function create_image_bundle { tmp=.bundle.$$.tmp mkdir "$tmp" || do_exit $? - [ "$bundle_type" == "fd" ] && [ "$__bundle_name" == "$JBRSDK_BUNDLE" ] && fastdebug_infix="fastdebug-" + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix}b${build_number} JRE_CONTENTS=$tmp/$__arch_name/Contents @@ -63,7 +63,7 @@ function create_image_bundle { --add-modules "$__modules" --output "$JRE_CONTENTS/Home" || do_exit $? grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$JRE_CONTENTS/Home/release" - if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release mv release $JRE_CONTENTS/Home/release copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods @@ -94,19 +94,19 @@ RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-release case "$bundle_type" in "jcef") - do_reset_changes=1 + do_reset_changes=0 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=1 - do_reset_changes=1 + do_reset_dcevm=0 + do_reset_changes=0 ;; "nomod" | "") bundle_type="" ;; "fd") - do_reset_changes=1 + do_reset_changes=0 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-fastdebug JBSDK=macosx-${architecture}-server-release @@ -165,7 +165,7 @@ modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/',' if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi -create_image_bundle "$JBRSDK_BUNDLE" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? if [ -z "$bundle_type" ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number} diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index f109387b41e3..6ccad55bf7ab 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -33,21 +33,22 @@ source jb/project/tools/common/scripts/common.sh function create_image_bundle { __bundle_name=$1 - __modules_path=$2 - __modules=$3 + __arch_name=$2 + __modules_path=$3 + __modules=$4 - [ -d $__bundle_name ] && rm -rf $__bundle_name + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" echo Running jlink ... ${JSDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ - --add-modules $__modules --output $__bundle_name || do_exit $? + --add-modules $__modules --output $__arch_name || do_exit $? - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__bundle_name/release - if [ "$__bundle_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' $__bundle_name/release > release - mv release $__bundle_name/release - copy_jmods "$__modules" "$__modules_path" "$__bundle_name"/jmods + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $__arch_name/release > release + mv release $__arch_name/release + copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods fi } @@ -56,19 +57,19 @@ RELEASE_NAME=windows-x86_64-server-release case "$bundle_type" in "jcef") - do_reset_changes=1 + do_reset_changes=0 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=1 - do_reset_changes=1 + do_reset_dcevm=0 + do_reset_changes=0 ;; "nomod" | "") bundle_type="" ;; "fd") - do_reset_changes=1 + do_reset_changes=0 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=windows-x86_64-server-fastdebug ;; @@ -108,13 +109,13 @@ fi # create runtime image bundle modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? -create_image_bundle "jbr${jbr_name_postfix}" $JSDK_MODS_DIR "$modules" || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi -create_image_bundle "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? do_exit 0 \ No newline at end of file diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 6be07efc3ab3..5a147d50a667 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -26,52 +26,33 @@ build_number=$3 bundle_type=$4 function pack_jbr { + __bundle_name=$1 + __arch_name=$2 - if [ -z "${bundle_type}" ]; then - JBR_BUNDLE=jbr - else - JBR_BUNDLE=jbr_${bundle_type} - [ -d ${BASE_DIR}/jbr ] && rm -rf ${BASE_DIR}/jbr - cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr - fi - JBR_BASE_NAME=${JBR_BUNDLE}-${JBSDK_VERSION} + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} - JBR=$JBR_BASE_NAME-windows-x64-b$build_number echo Creating $JBR.tar.gz ... - /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || do_exit $? + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? } -JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -JBR_BASE_NAME=jbr-$JBSDK_VERSION -RELEASE_NAME=windows-x86_64-server-release -JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number} -case "$bundle_type" in - "nomod" | "") - bundle_type="" - ;; - "fd") - RELEASE_NAME=macosx-x86_64-server-fastdebug - JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number} - ;; -esac +[ "$bundle_type" == "nomod" ] && bundle_type="" +JBRSDK_BUNDLE=jbrsdk +RELEASE_NAME=windows-x86_64-server-release IMAGES_DIR=build/$RELEASE_NAME/images -JSDK=$IMAGES_DIR/jdk -JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number BASE_DIR=. if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then - JBRSDK_BUNDLE=jbrsdk - echo Creating $JBSDK.tar.gz ... - [ -f "$JBSDK.tar.gz" ] && rm "$JBSDK.tar.gz" - /usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || do_exit $? + jbr_name_postfix="_${bundle_type}" fi -pack_jbr $bundle_type +pack_jbr jbr${jbr_name_postfix} jbr +pack_jbr jbrsdk${jbr_name_postfix} jbrsdk if [ -z "$bundle_type" ]; then - JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number + JBRSDK_TEST=$JBRSDK_BUNDLE-$JBSDK_VERSION-windows-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? fi \ No newline at end of file From 677e427d0fe138b33ea4a67b5fdda2f119331bec Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Mon, 26 Jul 2021 19:04:45 +0300 Subject: [PATCH 048/976] JBR-3645 Tool to support keeping JBR in sync with OpenJDK --- jb/jdkdiff.py | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100755 jb/jdkdiff.py diff --git a/jb/jdkdiff.py b/jb/jdkdiff.py new file mode 100755 index 000000000000..2d9f10b68607 --- /dev/null +++ b/jb/jdkdiff.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 + +import argparse +import math +import os.path +import sys +import subprocess + + +def fatal(msg): + sys.stderr.write(f"[fatal] {msg}\n") + sys.exit(1) + + +def verbose(options, *msg): + if options.verbose: + sys.stdout.write(f"[verbose] ") + sys.stdout.write(*msg) + sys.stdout.write('\n') + + +def first_line(str): + return "" if not str else str.splitlines()[0] + + +class Options: + def __init__(self): + ap = argparse.ArgumentParser(description="Show bugfixes differences between JBR and OpenJDK git repos", + epilog="Example: %(prog)s --jdk ./jdk11u/ --jbr ./JetBrainsRuntime/ --path src/hotspot --limit 200") + ap.add_argument('--jdk', dest='jdkpath', help='path to OpenJDK git repo', required=True) + ap.add_argument('--jbr', dest='jbrpath', help='path to JBR git repo', required=True) + ap.add_argument('--path', dest='path', help='limit to changes in this path (relative to git root)') + ap.add_argument('--limit', dest='limit', help='limit to this many log entries in --jdk repo', type=int, default=-1) + ap.add_argument('-o', dest="output_dir", help="save patches to this directory (created if necessary)") + ap.add_argument('-v', dest='verbose', help="verbose output", default=False, action='store_true') + args = ap.parse_args() + + if not os.path.isdir(args.jdkpath): + fatal(f"{args.jdkpath} not a directory") + + if not os.path.isdir(args.jbrpath): + fatal(f"{args.jbrpath} not a directory") + + if not git_is_available(): + fatal("can't run git commands; make sure git is in PATH") + + self.jdkpath = args.jdkpath + self.jbrpath = args.jbrpath + self.path = args.path + self.limit = args.limit + self.output_dir = args.output_dir + self.verbose = args.verbose + + +class GitRepo: + def __init__(self, rootpath): + self.rootpath = rootpath + + def run_git_cmd(self, git_args): + args = ["git", "-C", self.rootpath] + args.extend(git_args) + # print(f"Runnig git cmd '{' '.join(args)}'") + p = subprocess.run(args, capture_output=True, text=True) + if p.returncode != 0: + fatal(f"git returned non-zero code in {self.rootpath} ({first_line(p.stderr)})") + return p.stdout + + def save_git_cmd(self, fname, git_args): + args = ["git", "-C", self.rootpath] + args.extend(git_args) + # print(f"Runnig git cmd '{' '.join(args)}'") + with open(fname, "w") as stdout_file: + p = subprocess.run(args, stdout=stdout_file) + if p.returncode != 0: + fatal(f"git returned non-zero code in {self.rootpath} ({first_line(p.stderr)})") + + def current_branch(self): + branch_name = self.run_git_cmd(["branch", "--show-current"]).strip() + return branch_name + + def log(self, path=None, limit=None): + cmds = ["log", "--no-decorate"] + if limit: + cmds.extend(["-n", str(limit)]) + if path: + cmds.append(path) + full_log = self.run_git_cmd(cmds) + return full_log + + +class Commit: + def __init__(self, lines): + self.sha = lines[0].split()[1] + self.message = "" + self.bugid = None + + # Commit message starts after one blank line + read_message = False + for l in lines: + if read_message: + self.message += l + "\n" + if not read_message and l == "": + read_message = True + + if self.message and self.message != "" and ":" in self.message: + maybe_bugid = self.message.split(":")[0].strip() + if 10 >= len(maybe_bugid) >= 4: + self.bugid = maybe_bugid + + +class History: + def __init__(self, log): + log_itr = iter(log.splitlines()) + self.commits = [] + commit_lines = [] + for line in log_itr: + if line.startswith("commit ") and len(commit_lines) > 0: + commit = Commit(commit_lines) + self.commits.append(commit) + commit_lines = [] + commit_lines.append(line) + + if len(commit_lines) > 0: + commit = Commit(commit_lines) + self.commits.append(commit) + + def contains(self, str): + return any(str in commit.message for commit in self.commits) + + def size(self): + return len(self.commits) + + +def print_explanation(options, jdk, jbr): + verbose(options, f"Reading history from '{jdk.rootpath}' on branch '{jdk.current_branch()}'") + if options.path: + verbose(options, f"\t(only under '{options.path}')") + verbose(options, f"Searching for same fixes in '{jbr.rootpath}' on branch '{jbr.current_branch()}'") + + +def git_is_available(): + p = None + try: + p = subprocess.run(["git", "--help"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except: + pass + return p is not None and p.returncode == 0 + + +def main(): + check_python_min_requirements() + + options = Options() + + jdk = GitRepo(options.jdkpath) + jbr = GitRepo(options.jbrpath) + + print_explanation(options, jdk, jbr) + + commits_to_save = [] + try: + jdk_log = jdk.log(options.path, options.limit) + jdk_history = History(jdk_log) + + jbr_log = jbr.log(options.path) + jbr_history = History(jbr_log) + + verbose(options, f"Read {jdk_history.size()} commits in JDK, {jbr_history.size()} in JBR") + + for c in jdk_history.commits: + if c.bugid: + verbose(options, f"Looking for bugfix for {c.bugid}") + if not jbr_history.contains(c.bugid): + commits_to_save.append(c) + print(f"[note] Fix for {c.bugid} not found in JBR ({jbr.rootpath})") + print(f" commit {c.sha}") + print(f" {first_line(c.message).strip()}") + except KeyboardInterrupt: + fatal("Interrupted") + + if len(commits_to_save) > 0 and options.output_dir: + print() + if not os.path.exists(options.output_dir): + verbose(options, f"Creating output directory {options.output_dir}") + os.makedirs(options.output_dir) + nzeroes = len(str(len(commits_to_save))) + for i, c in enumerate(reversed(commits_to_save)): + fname = os.path.join(options.output_dir, f"{str(i).zfill(nzeroes)}-{c.bugid}.patch") + print(f"[note] {c.bugid} saved as {fname}") + fname = os.path.abspath(fname) + jdk.save_git_cmd(fname, ["format-patch", "-1", c.sha, "--stdout"]) + + script_fname = os.path.join(options.output_dir, "apply.sh") + with open(script_fname, "w") as script_file: + print(apply_script_code.format(os.path.abspath(jbr.rootpath), os.path.abspath(options.output_dir)), + file=script_file) + print(f"[note] Execute 'bash {script_fname}' to apply patches to {jbr.rootpath}") + + +def check_python_min_requirements(): + if sys.version_info < (3, 6): + fatal("Minimum version 3.6 is required to run this script") + + +apply_script_code = """ +#!/bin/bash + +GITROOT={0} +PATCHROOT={1} + +cd $PATCHROOT || exit 1 +PATCHES=$(find $PATCHROOT -name '*.patch' | sort -n) + +for P in $PATCHES; do + git -C $GITROOT am $P + if [ $? != 0 ]; then + mv "$P" "$P.failed" + echo "[ERROR] Patch $P did not apply cleanly. Try applying it manually." + echo "[NOTE] Execute this script to apply the remaining patches." + exit 1 + else + mv "$P" "$P.done" + fi +done + +echo "[NOTE] Done applying patches; check $PATCHROOT for .patch and .patch.failed to see if all have been applied." +""" + +if __name__ == '__main__': + main() From 1894f724d5cb7c27f8ea713ff2e30c7e87b3924e Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 30 Jul 2021 14:18:38 +0300 Subject: [PATCH 049/976] JBR-3655 jbr-dev build fails to find jcef modules on Windows --- jb/project/tools/windows/scripts/mkimages_x64.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 6ccad55bf7ab..d0d7b3b2bec9 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -99,6 +99,11 @@ JSDK=$IMAGES_DIR/jdk JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk +where cygpath +if [ $? -eq 0 ]; then + JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" +fi + if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? From b81f691326cefc4b56d55f471013a5cca1e9ea1b Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 1 Oct 2021 07:16:23 +0700 Subject: [PATCH 050/976] configure BOOT_JDK to use JDK 17 --- jb/project/docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jb/project/docker/Dockerfile b/jb/project/docker/Dockerfile index fb02f1c9d28a..37eb2a236b4b 100644 --- a/jb/project/docker/Dockerfile +++ b/jb/project/docker/Dockerfile @@ -4,9 +4,9 @@ RUN yum -y install centos-release-scl RUN yum -y install devtoolset-8 RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool gcc gcc-c++ libstdc++-devel alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel git # Install Java 16 -RUN wget https://cdn.azul.com/zulu/bin/zulu16.28.11-ca-jdk16.0.0-linux_x64.tar.gz \ +RUN wget https://cdn.azul.com/zulu/bin/zulu17.28.13-ca-jdk17.0.0-linux_x64.tar.gz \ -O - | tar xz -C / -RUN mv /zulu16.28.11-ca-jdk16.0.0-linux_x64 /jdk16.0.0 +RUN mv /zulu17.28.13-ca-jdk17.0.0-linux_x64 /jdk17.0.0 ENV PATH /opt/rh/devtoolset-8/root/usr/bin:$PATH RUN mkdir .git RUN git config user.email "teamcity@jetbrains.com" From 6e5e47e05a3782d873b9ca1c1c1a70aa28f9a696 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 24 Oct 2021 06:23:11 +0700 Subject: [PATCH 051/976] JBR-3904 fix the image directory name of macos builds --- jb/project/tools/mac/scripts/mkimages.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index ab6c7e5c595b..4b97176e95a4 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -31,7 +31,6 @@ JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" JCEF_PATH=${JCEF_PATH:=./jcef_mac} architecture=${architecture:=x64} -MAJOR_JBSDK_VERSION=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}') BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)} source jb/project/tools/common/scripts/common.sh @@ -144,7 +143,11 @@ make clean CONF=$RELEASE_NAME || do_exit $? make images CONF=$RELEASE_NAME || do_exit $? IMAGES_DIR=build/$RELEASE_NAME/images -JSDK=$IMAGES_DIR/jdk-bundle/jdk-$MAJOR_JBSDK_VERSION.jdk/Contents/Home + +major_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}') +minor_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $3}') +[ -z "$minor_version" -o "$minor_version" = "0" ] && version_dir=$major_version || version_dir=$JBSDK_VERSION_WITH_DOTS +JSDK=$IMAGES_DIR/jdk-bundle/jdk-$version_dir.jdk/Contents/Home JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk From dbbb3d18cc6fcf667c7ce97b6323d4635ecdc1d9 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 24 Oct 2021 08:53:21 +0700 Subject: [PATCH 052/976] JBR-3905 add incremental JBR building --- .../tools/linux/scripts/mkimages_x64.sh | 39 +++++++---- jb/project/tools/mac/scripts/mkimages.sh | 70 ++++++++++++------- .../tools/windows/scripts/mkimages_x64.sh | 53 +++++++++----- 3 files changed, 107 insertions(+), 55 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 6b725ee7705e..9f8feb7a9586 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -21,6 +21,16 @@ # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_linux_x64 +while getopts ":i?" o; do + case "${o}" in + i) + i="incremental build" + INC_BUILD=1 + ;; + esac +done +shift $((OPTIND-1)) + JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 @@ -30,6 +40,19 @@ JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64} source jb/project/tools/common/scripts/common.sh +function do_configure { + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + --enable-cds=yes || do_exit $? +} + function create_image_bundle { __bundle_name=$1 __arch_name=$2 @@ -85,18 +108,10 @@ case "$bundle_type" in ;; esac -sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="$VENDOR_NAME" \ - --with-vendor-version-string="$VENDOR_VERSION_STRING" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="$JDK_BUILD_NUMBER" \ - --with-version-opt=b"$build_number" \ - --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes || do_exit $? - -make clean CONF=$RELEASE_NAME || exit $? +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + make clean CONF=$RELEASE_NAME || do_exit $? +fi make images CONF=$RELEASE_NAME || do_exit $? IMAGES_DIR=build/$RELEASE_NAME/images diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 4b97176e95a4..911c53eb53f7 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -21,6 +21,16 @@ # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_mac +while getopts ":i?" o; do + case "${o}" in + i) + i="incremental build" + INC_BUILD=1 + ;; + esac +done +shift $((OPTIND-1)) + JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 @@ -41,6 +51,36 @@ function copyJNF { cp -Rp Frameworks/JavaNativeFoundation.framework ${__contents_dir}/Frameworks } +function do_configure { + if [[ "${architecture}" == *aarch64* ]]; then + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="${VENDOR_NAME}" \ + --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="${JDK_BUILD_NUMBER}" \ + --with-version-opt=b"${build_number}" \ + --with-boot-jdk="$BOOT_JDK" \ + --disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \ + --enable-cds=no \ + --with-extra-cflags="-F$(pwd)/Frameworks" \ + --with-extra-cxxflags="-F$(pwd)/Frameworks" \ + --with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $? + else + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + --enable-cds=yes || do_exit $? + fi +} + function create_image_bundle { __bundle_name=$1 __arch_name=$2 @@ -112,34 +152,10 @@ case "$bundle_type" in ;; esac -if [[ "${architecture}" == *aarch64* ]]; then - sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="${JDK_BUILD_NUMBER}" \ - --with-version-opt=b"${build_number}" \ - --with-boot-jdk="$BOOT_JDK" \ - --disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \ - --enable-cds=no \ - --with-extra-cflags="-F$(pwd)/Frameworks" \ - --with-extra-cxxflags="-F$(pwd)/Frameworks" \ - --with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $? -else - sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="$VENDOR_NAME" \ - --with-vendor-version-string="$VENDOR_VERSION_STRING" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="$JDK_BUILD_NUMBER" \ - --with-version-opt=b"$build_number" \ - --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes || do_exit $? +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + make clean CONF=$RELEASE_NAME || do_exit $? fi -make clean CONF=$RELEASE_NAME || do_exit $? make images CONF=$RELEASE_NAME || do_exit $? IMAGES_DIR=build/$RELEASE_NAME/images diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index d0d7b3b2bec9..af0d9eff6f0e 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -21,6 +21,16 @@ # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_win_x64 +while getopts ":i?" o; do + case "${o}" in + i) + i="incremental build" + INC_BUILD=1 + ;; + esac +done +shift $((OPTIND-1)) + JBSDK_VERSION=$1 JDK_BUILD_NUMBER=$2 build_number=$3 @@ -31,6 +41,21 @@ JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64} source jb/project/tools/common/scripts/common.sh +function do_configure { + sh ./configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b${build_number} \ + --with-toolchain-version=$TOOLCHAIN_VERSION \ + --with-boot-jdk=$BOOT_JDK \ + --disable-ccache \ + --enable-cds=yes || do_exit $? +} + function create_image_bundle { __bundle_name=$1 __arch_name=$2 @@ -75,23 +100,19 @@ case "$bundle_type" in ;; esac -sh ./configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="$VENDOR_NAME" \ - --with-vendor-version-string="$VENDOR_VERSION_STRING" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build=$JDK_BUILD_NUMBER \ - --with-version-opt=b${build_number} \ - --with-toolchain-version=$TOOLCHAIN_VERSION \ - --with-boot-jdk=$BOOT_JDK \ - --disable-ccache \ - --enable-cds=yes || do_exit $? - -if [ -z "$bundle_type" ]; then - make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + if [ -z "$bundle_type" ]; then + make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? + fi else - make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? + if [ -z "$bundle_type" ]; then + make LOG=info CONF=$RELEASE_NAME images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME images || do_exit $? + fi fi IMAGES_DIR=build/$RELEASE_NAME/images From a2ebee0ca97723c9a10742fccdde5c7b63cb8e09 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Tue, 30 Nov 2021 20:09:20 +0300 Subject: [PATCH 053/976] JBR-4059 Create Dockerfile for building on AArch64 Linux --- jb/project/docker/Dockerfile.aarch64 | 47 +++++++++++++++++++++++++++ jb/project/docker/mkdocker_aarch64.sh | 26 +++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 jb/project/docker/Dockerfile.aarch64 create mode 100755 jb/project/docker/mkdocker_aarch64.sh diff --git a/jb/project/docker/Dockerfile.aarch64 b/jb/project/docker/Dockerfile.aarch64 new file mode 100644 index 000000000000..47e49de26ff8 --- /dev/null +++ b/jb/project/docker/Dockerfile.aarch64 @@ -0,0 +1,47 @@ +# NOTE: This Dockerfile is meant to be used from the mkdocker_aarch64.sh script. + +# Pull a concrete version of Linux that does NOT recieve updates after it's +# been created. This is so that the image is as stable as possible to make +# image creation reproducible. +# NB: this also means there may be no security-related fixes there, need to +# move the version to the next manually. +FROM arm64v8/ubuntu:focal-20211006 + +# Install the necessary build tools +RUN export DEBIAN_FRONTEND=noninteractive \ + export DEBCONF_NONINTERACTIVE_SEEN=true && \ + echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \ + echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \ + apt-get update -qy && \ + apt-get install -qy \ + autoconf \ + build-essential \ + bzip2 \ + file \ + g++-10=10.3.0-1ubuntu1~20.04 \ + gcc-10=10.3.0-1ubuntu1~20.04 \ + git \ + libasound2-dev \ + libcups2-dev \ + libfontconfig1-dev \ + libx11-dev \ + libxext-dev \ + libxrandr-dev \ + libxrender-dev \ + libxt-dev \ + libxtst-dev \ + make \ + tar \ + unzip \ + zip && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 && \ + apt-get clean -qy && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Set up boot JDK for building +COPY boot_jdk.tar.gz /jdk17/ +RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk.tar.gz && rm /jdk17/boot_jdk.tar.gz +ENV BOOT_JDK=/jdk17 + +RUN git config --global user.email "teamcity@jetbrains.com" && \ + git config --global user.name "builduser" diff --git a/jb/project/docker/mkdocker_aarch64.sh b/jb/project/docker/mkdocker_aarch64.sh new file mode 100755 index 000000000000..bcaeaa076f81 --- /dev/null +++ b/jb/project/docker/mkdocker_aarch64.sh @@ -0,0 +1,26 @@ +#!/bin/bash -x + +# This script creates a Docker image suitable for building AArch64 variant +# of the JetBrains Runtime "dev" version. + +BOOT_JDK_REMOTE_FILE=zulu17.30.15-ca-jdk17.0.1-linux_aarch64.tar.gz +BOOT_JDK_SHA=4d9c9116eb0cdd2d7fb220d6d27059f4bf1b7e95cc93d5512bd8ce3791af86c7 +BOOT_JDK_LOCAL_FILE=boot_jdk.tar.gz + +if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then + # Obtain "boot JDK" from outside of the container. + wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE +else + echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download" +fi + +# Verify that what we've downloaded can be trusted. +sha256sum -c - < Date: Wed, 24 Nov 2021 07:47:45 -0800 Subject: [PATCH 054/976] JBR-4033 Linux: update build scripts to produce more deterministic output This commits achieves almost the same build output with the same build input on Linux. Exceptions are: - class files timestamps differ in jrt-fs.jar (for all output), - class files timestamps differ in all the jmod files (for jbrsdk...tar.gz). NB: jbrsdk...test...tar.gz does not need to be deterministic. This was achieved mainly by - setting several environment variables (SOURCE_DATE_EPOCH, TZ), - providing the necessary options to the configure script, - setting the timestamp of all files that make up the resulting archive to SORUCE_DATE_EPOCH and normalizing the list of said files before archiving. (cherry picked from commit ffded82734b26df0a5402e0b55c80c68588c9e85) --- jb/project/tools/common/scripts/common.sh | 14 ++++++++++++++ jb/project/tools/linux/scripts/mkimages_aarch64.sh | 13 +++++++++---- jb/project/tools/linux/scripts/mkimages_x64.sh | 14 +++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index fe642270fa70..96eaeb7eb768 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -6,6 +6,20 @@ do_reset_changes=0 do_reset_dcevm=0 HEAD_REVISION=0 +# Enable reproducible builds +TZ=UTC +export TZ +SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)" +export SOURCE_DATE_EPOCH +COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)" +BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)" +REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" +REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build + --with-source-date=$SOURCE_DATE_EPOCH + --with-hotspot-build-time=$BUILD_TIME + --with-copyright-year=$COPYRIGHT_YEAR + --with-native-debug-symbols=none" + function do_exit() { exit_code=$1 [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index afdc34118611..12d260cb3795 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -35,7 +35,9 @@ sh configure \ --with-version-build="${JDK_BUILD_NUMBER}" \ --with-version-opt=b${build_number} \ --with-boot-jdk=${BOOT_JDK} \ - --enable-cds=yes || exit $? + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + || exit $? make clean CONF=linux-aarch64-server-release || exit $? make images CONF=linux-aarch64-server-release test-image || exit $? @@ -54,9 +56,11 @@ echo Creating $JBSDK.tar.gz ... sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release -tar -pcf $JBSDK.tar \ +# NB: --sort=name requires tar1.28 +tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBSDK.tar \ --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? +touch -c -d @$SOURCE_DATE_EPOCH $JBRSDK.tar gzip $JBSDK.tar || exit $? JBR_BUNDLE=jbr @@ -75,10 +79,11 @@ echo Modifying release info ... grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release echo Creating $JBR.tar.gz ... -tar -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? +tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? +touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar gzip $JBR.tar || exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file +gzip $JBRSDK_TEST.tar || exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 9f8feb7a9586..8da8e731ba62 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -50,7 +50,9 @@ function do_configure { --with-version-build="$JDK_BUILD_NUMBER" \ --with-version-opt=b"$build_number" \ --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes || do_exit $? + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? } function create_image_bundle { @@ -79,8 +81,14 @@ function create_image_bundle { [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper echo Creating "$JBR".tar.gz ... - tar -pcf "$JBR".tar -C "$IMAGES_DIR" "$__arch_name" || do_exit $? + + (cd "$IMAGES_DIR" && + find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + tar $REPRODUCIBLE_TAR_OPTS \ + --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? + mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" + touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar gzip "$JBR".tar || do_exit $? rm -rf "${IMAGES_DIR:?}"/"$__arch_name" } @@ -151,4 +159,4 @@ if [ -z "$bundle_type" ]; then gzip "$JBRSDK_TEST".tar || do_exit $? fi -do_exit 0 \ No newline at end of file +do_exit 0 From c73b2bd5c85539adbec1b1ca5e3d97c917063e20 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Tue, 30 Nov 2021 22:34:30 +0300 Subject: [PATCH 055/976] JBR-4063 macOS: update build scripts to produce more deterministic output Make mkimages.sh produce more deterministic .tar.gz archives on MacOS. NB: build notarization is not in the scope of this change. (cherry picked from commit e1a1b6814decb9bf2c66ffb27bb8cf93a16a7058) --- jb/project/tools/common/scripts/common.sh | 22 +++++++++++++++++++--- jb/project/tools/mac/scripts/mkimages.sh | 19 +++++++++++++++---- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 96eaeb7eb768..b757afc40ee7 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -6,14 +6,30 @@ do_reset_changes=0 do_reset_dcevm=0 HEAD_REVISION=0 +OS_NAME=$(uname -s) # Enable reproducible builds TZ=UTC export TZ SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)" export SOURCE_DATE_EPOCH -COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)" -BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)" -REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" + +case "$OS_NAME" in + Linux) + COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)" + BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)" + REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" + ;; + Darwin) + COPYRIGHT_YEAR="$(date -u -r $SOURCE_DATE_EPOCH +%Y)" + BUILD_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%F)" + TOUCH_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%Y%m%d%H%M.%S)" + REPRODUCIBLE_TAR_OPTS="--uid 0 --gid 0 --numeric-owner" + ;; + *) + # TODO: Windows + ;; +esac + REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build --with-source-date=$SOURCE_DATE_EPOCH --with-hotspot-build-time=$BUILD_TIME diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 911c53eb53f7..d1bafac173bc 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -66,7 +66,9 @@ function do_configure { --enable-cds=no \ --with-extra-cflags="-F$(pwd)/Frameworks" \ --with-extra-cxxflags="-F$(pwd)/Frameworks" \ - --with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $? + --with-extra-ldflags="-F$(pwd)/Frameworks" \ + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? else sh configure \ $WITH_DEBUG_LEVEL \ @@ -77,7 +79,9 @@ function do_configure { --with-version-build="$JDK_BUILD_NUMBER" \ --with-version-opt=b"$build_number" \ --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes || do_exit $? + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? fi } @@ -120,7 +124,14 @@ function create_image_bundle { [ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?) echo Creating "$JBR".tar.gz ... - COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__arch_name" || do_exit $? + # Normalize timestamp + find "$tmp"/"$__arch_name" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME" + + (cd "$tmp" && + find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + COPYFILE_DISABLE=1 tar $REPRODUCIBLE_TAR_OPTS --no-recursion --null -T - \ + -czf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man') || do_exit $? + mv "$tmp"/"$JBR".tar.gz "$JBR".tar.gz rm -rf "$tmp" } @@ -194,4 +205,4 @@ if [ -z "$bundle_type" ]; then COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? fi -do_exit 0 \ No newline at end of file +do_exit 0 From df404eb6d32d656e843f55aecd2b5eb628512cb5 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Thu, 2 Dec 2021 08:56:21 +0300 Subject: [PATCH 056/976] JBR-4061 Specify build user for the build --- jb/project/tools/common/scripts/common.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index b757afc40ee7..593176b28e9a 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -34,7 +34,8 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build --with-source-date=$SOURCE_DATE_EPOCH --with-hotspot-build-time=$BUILD_TIME --with-copyright-year=$COPYRIGHT_YEAR - --with-native-debug-symbols=none" + --with-native-debug-symbols=none + --with-build-user=builduser" function do_exit() { exit_code=$1 From 790d189a70a7403517b05aa0228c519acf092e25 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 3 Dec 2021 10:48:58 +0700 Subject: [PATCH 057/976] JBR-4082 create JBR & JBRSDK installer packages --- jb/project/tools/mac/scripts/mkimages.sh | 4 + jb/project/tools/mac/scripts/notarize.sh | 16 ++-- jb/project/tools/mac/scripts/sign.sh | 94 ++++++++++++------------ jb/project/tools/mac/scripts/signapp.sh | 22 +++--- 4 files changed, 73 insertions(+), 63 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index d1bafac173bc..78f5dd3825fe 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -57,6 +57,8 @@ function do_configure { $WITH_DEBUG_LEVEL \ --with-vendor-name="${VENDOR_NAME}" \ --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ + --with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \ + --with-macosx-bundle-id-base="com.jetbrains.jbr" \ --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build="${JDK_BUILD_NUMBER}" \ @@ -74,6 +76,8 @@ function do_configure { $WITH_DEBUG_LEVEL \ --with-vendor-name="$VENDOR_NAME" \ --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \ + --with-macosx-bundle-id-base="com.jetbrains.jbr" \ --with-jvm-features=shenandoahgc \ --with-version-pre= \ --with-version-build="$JDK_BUILD_NUMBER" \ diff --git a/jb/project/tools/mac/scripts/notarize.sh b/jb/project/tools/mac/scripts/notarize.sh index ded48e12d1de..488205e85cf2 100755 --- a/jb/project/tools/mac/scripts/notarize.sh +++ b/jb/project/tools/mac/scripts/notarize.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x APP_DIRECTORY=$1 APPL_USER=$2 @@ -54,17 +54,15 @@ function altool-upload() { #immediately exit script with an error if a command fails set -euo pipefail -file="$APP_NAME.zip" +#file="$APP_NAME.zip" -log "Zipping $file..." -rm -rf "$file" -ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file" +#log "Zipping $file..." +#rm -rf "$file" +#ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file" -log "Notarizing $file..." +log "Notarizing $APP_NAME..." rm -rf "altool.init.out" "altool.check.out" -altool-upload "$file" - -rm -rf "$file" +altool-upload "$APP_NAME" notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')" diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index 0b2ee825a53a..59e1d104bd66 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -1,14 +1,17 @@ -#!/bin/bash +#!/bin/bash -x -APP_DIRECTORY=$1 -JB_CERT=$2 +APPLICATION_PATH=$1 +APP_NAME=$2 +BUNDLE_ID=$3 +JB_DEVELOPER_CERT=$4 +JB_INSTALLER_CERT=$5 -if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then +if [[ -z "$APPLICATION_PATH" ]] || [[ -z "$JB_DEVELOPER_CERT" ]]; then echo "Usage: $0 AppDirectory CertificateID" exit 1 fi -if [[ ! -d "$APP_DIRECTORY" ]]; then - echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory" +if [[ ! -d "$APPLICATION_PATH" ]]; then + echo "AppDirectory '$APPLICATION_PATH' does not exist or not a directory" exit 1 fi @@ -20,43 +23,30 @@ function log() { set -euo pipefail # Cleanup files left from previous sign attempt (if any) -find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \; +find "$APPLICATION_PATH" -name '*.cstemp' -exec rm '{}' \; log "Signing libraries and executables..." # -perm +111 searches for executables for f in \ - "Contents/Home/bin" \ - "Contents/Home/lib"; do - if [ -d "$APP_DIRECTORY/$f" ]; then - find "$APP_DIRECTORY/$f" \ - -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ - -exec codesign --timestamp --force \ - -v -s "$JB_CERT" --options=runtime \ + "Contents/Home/lib" "Contents/MacOS" \ + "Contents/Home/Frameworks" \ + "Contents/Frameworks"; do + if [ -d "$APPLICATION_PATH/$f" ]; then + find "$APPLICATION_PATH/$f" \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "*.node" -o -perm +111 \) \ + -exec codesign --timestamp \ + -v -s "$JB_DEVELOPER_CERT" --options=runtime --force \ --entitlements entitlements.xml {} \; fi done -if [ -d "$APP_DIRECTORY/Contents/Frameworks" ]; then - log "Signing frameworks..." - for f in $APP_DIRECTORY/Contents/Frameworks/*; do - find "$f" \ - -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" \) \ - -exec codesign --timestamp --force \ - -v -s "$JB_CERT" \ - --entitlements entitlements.xml {} \; - codesign --timestamp --force \ - -v -s "$JB_CERT" --options=runtime \ - --entitlements entitlements.xml "$f" - done -fi - log "Signing libraries in jars in $PWD" # todo: add set -euo pipefail; into the inner sh -c # `-e` prevents `grep -q && printf` loginc # with `-o pipefail` there's no input for 'while' loop -find "$APP_DIRECTORY" -name '*.jar' \ - -exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; | +find "$APPLICATION_PATH" -name '*.jar' \ + -exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '\.tbd\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; | while IFS= read -r -d $'\0' file; do log "Processing libraries in $file" @@ -67,12 +57,13 @@ find "$APP_DIRECTORY" -name '*.jar' \ cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename") find jarfolder \ - -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \ - -exec codesign --timestamp --force \ - -v -s "$JB_CERT" --options=runtime \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "jattach" \) \ + -exec codesign --timestamp \ + --force \ + -v -s "$JB_DEVELOPER_CERT" --options=runtime \ --entitlements entitlements.xml {} \; - (cd jarfolder; zip -q -r -o ../jar.jar .) + (cd jarfolder; zip -q -r -o -0 ../jar.jar .) mv jar.jar "$file" done @@ -80,28 +71,41 @@ rm -rf jarfolder jar.jar log "Signing other files..." for f in \ - "Contents/MacOS"; do - if [ -d "$APP_DIRECTORY/$f" ]; then - find "$APP_DIRECTORY/$f" \ - -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \ - -exec codesign --timestamp --force \ - -v -s "$JB_CERT" --options=runtime \ + "Contents/Home/bin"; do + if [ -d "$APPLICATION_PATH/$f" ]; then + find "$APPLICATION_PATH/$f" \ + -type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -perm +111 \) \ + -exec codesign --timestamp \ + -v -s "$JB_DEVELOPER_CERT" --options=runtime --force \ --entitlements entitlements.xml {} \; fi done #log "Signing executable..." #codesign --timestamp \ -# -v -s "$JB_CERT" --options=runtime \ +# -v -s "$JB_DEVELOPER_CERT" --options=runtime \ # --force \ -# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea" +# --entitlements entitlements.xml "$APPLICATION_PATH/Contents/MacOS/idea" log "Signing whole app..." codesign --timestamp \ - -v -s "$JB_CERT" --options=runtime \ + -v -s "$JB_DEVELOPER_CERT" --options=runtime \ --force \ - --entitlements entitlements.xml "$APP_DIRECTORY" + --entitlements entitlements.xml "$APPLICATION_PATH" + +BUILD_NAME=$(echo $APPLICATION_PATH | awk -F"/" '{ print $2 }') + +log "Creating $APP_NAME.pkg..." +rm -rf "$APP_NAME.pkg" +pkgbuild --identifier $BUNDLE_ID --sign "$JB_INSTALLER_CERT" --root $APPLICATION_PATH \ + --install-location /Library/Java/JavaVirtualMachines/${BUILD_NAME} ${APP_NAME}.pkg + +#log "Signing whole app..." +#codesign --timestamp \ +# -v -s "$JB_DEVELOPER_CERT" --options=runtime \ +# --force \ +# --entitlements entitlements.xml $APP_NAME.pkg log "Verifying java is not broken" -find "$APP_DIRECTORY" \ +find "$APPLICATION_PATH" \ -type f -name 'java' -perm +111 -exec {} -version \; diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index 518e41d50b05..6f3a17b88b7d 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -12,8 +12,9 @@ BACKUP_JMODS=$2.backup USERNAME=$3 PASSWORD=$4 CODESIGN_STRING=$5 -NOTARIZE=$6 -BUNDLE_ID=$7 +JB_INSTALLER_CERT=$6 +NOTARIZE=$7 +BUNDLE_ID=$8 cd "$(dirname "$0")" @@ -33,7 +34,7 @@ mkdir "$BACKUP_JMODS" log "Unzipping $INPUT_FILE to $EXPLODED ..." tar -xzvf "$INPUT_FILE" --directory $EXPLODED BUILD_NAME="$(ls "$EXPLODED")" -sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist +#sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist rm -f $EXPLODED/$BUILD_NAME/Contents/CodeResources rm "$INPUT_FILE" if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then @@ -42,7 +43,9 @@ fi log "$INPUT_FILE extracted and removed" -APPLICATION_PATH="$EXPLODED/$BUILD_NAME" +APP_NAME=$(echo ${INPUT_FILE} | awk -F".tar" '{ print $1 }') +APPLICATION_PATH=$(sed "s/osx-//" <<< "$EXPLODED/$APP_NAME") +mv $EXPLODED/$BUILD_NAME $APPLICATION_PATH find "$APPLICATION_PATH/Contents/Home/bin" \ -maxdepth 1 -type f -name '*.jnilib' -print0 | @@ -79,7 +82,7 @@ limit=3 set +e while [[ $attempt -le $limit ]]; do log "Signing (attempt $attempt) $APPLICATION_PATH ..." - ./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING" + ./sign.sh "$APPLICATION_PATH" "$APP_NAME" "$BUNDLE_ID" "$CODESIGN_STRING" "$JB_INSTALLER_CERT" ec=$? if [[ $ec -ne 0 ]]; then ((attempt += 1)) @@ -92,6 +95,7 @@ while [[ $attempt -le $limit ]]; do log "Signing done" codesign -v "$APPLICATION_PATH" -vvvvv log "Check sign done" + spctl -a -v $APPLICATION_PATH ((attempt += limit)) fi done @@ -102,13 +106,12 @@ if [ "$NOTARIZE" = "yes" ]; then log "Notarizing..." # shellcheck disable=SC1090 source "$HOME/.notarize_token" - APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }') # Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root # Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR FAKE_ROOT="$(pwd)/fake-root" mkdir -p "$FAKE_ROOT" echo "Notarization will use fake root: $FAKE_ROOT" - ./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT" + ./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME.pkg" "$BUNDLE_ID" "$FAKE_ROOT" rm -rf "$FAKE_ROOT" set +e @@ -124,10 +127,11 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..." #cd "$EXPLODED" #ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE" if test -d $BACKUP_JMODS/jmods; then - mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home + mv $BACKUP_JMODS/jmods $APPLICATION_PATH/Contents/Home fi + mv $APPLICATION_PATH $EXPLODED/$BUILD_NAME - tar -pczvf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME + tar -pczvf $INPUT_FILE --exclude='man' -C $EXPLODED $BUILD_NAME log "Finished zipping" ) rm -rf "$EXPLODED" From 0bc3f7a99fc63ddafd7c2144d2310b91809f0918 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 7 Dec 2021 04:24:09 +0700 Subject: [PATCH 058/976] JBR-3756 remove JNF from mac-aarch64 binaries --- jb/project/tools/mac/scripts/mkimages.sh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 78f5dd3825fe..a25fd09c36dd 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -45,12 +45,6 @@ BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)} source jb/project/tools/common/scripts/common.sh -function copyJNF { - __contents_dir=$1 - mkdir -p ${__contents_dir}/Frameworks - cp -Rp Frameworks/JavaNativeFoundation.framework ${__contents_dir}/Frameworks -} - function do_configure { if [[ "${architecture}" == *aarch64* ]]; then sh configure \ @@ -119,12 +113,6 @@ function create_image_bundle { cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" cp "$JSDK"/../Info.plist "$JRE_CONTENTS" - if [[ "${architecture}" == *aarch64* ]]; then - # we can't notarize this library as usual framework (with headers and tbd-file) - # but single library notarizes correctly - copyJNF $JRE_CONTENTS - fi - [ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?) echo Creating "$JBR".tar.gz ... From 55728be8ac2fcab36d5354d3dca2d328b4f91cea Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 7 Dec 2021 04:31:14 +0700 Subject: [PATCH 059/976] JBR-4067 fix misprint with applying obsolete exclude_jcef_module.patch --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 12d260cb3795..ecb7b602e0bd 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -24,8 +24,6 @@ source jb/project/tools/common/scripts/common.sh JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - sh configure \ --with-debug-level=release \ --with-vendor-name="${VENDOR_NAME}" \ From ab4853f8c5d1d08b7bcc796ac6d502f305650299 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 31 Dec 2021 05:46:53 +0700 Subject: [PATCH 060/976] JBR-4154 extract version info from sources & JBR-4099 make test-image on jbrsdk_jcef step --- jb/project/tools/common/scripts/common.sh | 45 +++++++++++++- .../tools/linux/scripts/mkimages_aarch64.sh | 20 +----- .../tools/linux/scripts/mkimages_x64.sh | 51 ++++++---------- jb/project/tools/mac/scripts/mkimages.sh | 61 ++++++------------- .../tools/windows/scripts/mkimages_x64.sh | 48 +++++---------- jb/project/tools/windows/scripts/pack_x64.sh | 28 +++------ 6 files changed, 106 insertions(+), 147 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 593176b28e9a..d3a00834f4e1 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -1,5 +1,48 @@ +#!/bin/bash -x + +function do_maketest() { + if [ "${bundle_type: -1}" == "t" ]; then + echo ${bundle_type%?} + return 1 + else + echo ${bundle_type} + return 0 + fi +} + +function getVersionProp() { + grep "^${1}" make/conf/version-numbers.conf | cut -d'=' -f2 +} + +while getopts ":i?" o; do + case "${o}" in + i) + i="incremental build" + INC_BUILD=1 + ;; + esac +done +shift $((OPTIND-1)) + +build_number=$1 +bundle_type=$2 +architecture=$3 # aarch64 or x64 + +bundle_type=$(do_maketest) +do_maketest=$? +tag_prefix="jdk-" +OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | tr -d ',' | sort -t "-" -k 2 -g | tail -n 1) +VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE") +VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM") +VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE") +[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}" +echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']" +JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')} +[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1 +echo "##teamcity[setParameter name='env.JDK_UPDATE_NUMBER' value='${JDK_BUILD_NUMBER}']" + VENDOR_NAME="JetBrains s.r.o." -VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}.${JDK_BUILD_NUMBER}-${build_number}" +VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION}+${JDK_BUILD_NUMBER}-${build_number}" [ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}" do_reset_changes=0 diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index ecb7b602e0bd..69fafce15926 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -1,24 +1,8 @@ #!/bin/bash -x -# The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build +# The following parameter must be specified: +# build_number - specifies the number of JetBrainsRuntime build # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) -# - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') source jb/project/tools/common/scripts/common.sh diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 8da8e731ba62..bc1b677f1a5c 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -1,45 +1,26 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) -# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to be built; possible values: -# or nomod - the release bundles without any additional modules (jcef) -# jcef - the release bundles with jcef -# fd - the fastdebug bundles which also include the jcef module +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# This script makes test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. # # Environment variables: +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument +# to configure +# By default JDK_BUILD_NUMBER is set zero # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_linux_x64 -while getopts ":i?" o; do - case "${o}" in - i) - i="incremental build" - INC_BUILD=1 - ;; - esac -done -shift $((OPTIND-1)) - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -bundle_type=$4 -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64} - source jb/project/tools/common/scripts/common.sh +JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64} + function do_configure { sh configure \ $WITH_DEBUG_LEVEL \ @@ -98,7 +79,8 @@ RELEASE_NAME=linux-x86_64-server-release case "$bundle_type" in "jcef") - do_reset_changes=0 + do_reset_changes=1 + do_maketest=1 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) @@ -110,7 +92,7 @@ case "$bundle_type" in bundle_type="" ;; "fd") - do_reset_changes=0 + do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=linux-x86_64-server-fastdebug ;; @@ -150,9 +132,10 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? -if [ -z "$bundle_type" ]; then +if [ $do_maketest -eq 1 ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number} echo Creating "$JBRSDK_TEST" ... + [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java make test-image CONF=$RELEASE_NAME || do_exit $? tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index a25fd09c36dd..01c015efc284 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -1,49 +1,27 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) -# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to be built; possible values: -# or nomod - the release bundles without any additional modules (jcef) -# jcef - the release bundles with jcef -# fd - the fastdebug bundles which also include the jcef module +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# This script makes test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. # # Environment variables: +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument +# to configure +# By default JDK_BUILD_NUMBER is set zero # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_mac -while getopts ":i?" o; do - case "${o}" in - i) - i="incremental build" - INC_BUILD=1 - ;; - esac -done -shift $((OPTIND-1)) - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -bundle_type=$4 -architecture=$5 # aarch64 or x64 -enable_aot=$6 # temporary param for building test jre with aot under aarch64 -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') -WITH_IMPORT_MODULES="--with-import-modules=${MODULAR_SDK_PATH:=./modular-sdk}" +source jb/project/tools/common/scripts/common.sh + JCEF_PATH=${JCEF_PATH:=./jcef_mac} architecture=${architecture:=x64} -BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)} - -source jb/project/tools/common/scripts/common.sh +BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 17)} function do_configure { if [[ "${architecture}" == *aarch64* ]]; then @@ -136,7 +114,8 @@ RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-release case "$bundle_type" in "jcef") - do_reset_changes=0 + do_reset_changes=1 + do_maketest=1 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) @@ -148,7 +127,7 @@ case "$bundle_type" in bundle_type="" ;; "fd") - do_reset_changes=0 + do_reset_changes=1 WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-fastdebug JBSDK=macosx-${architecture}-server-release @@ -163,10 +142,7 @@ make images CONF=$RELEASE_NAME || do_exit $? IMAGES_DIR=build/$RELEASE_NAME/images -major_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}') -minor_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $3}') -[ -z "$minor_version" -o "$minor_version" = "0" ] && version_dir=$major_version || version_dir=$JBSDK_VERSION_WITH_DOTS -JSDK=$IMAGES_DIR/jdk-bundle/jdk-$version_dir.jdk/Contents/Home +JSDK=$IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk @@ -189,9 +165,10 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? -if [ -z "$bundle_type" ]; then +if [ $do_maketest -eq 1 ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number} echo Creating "$JBRSDK_TEST" ... + [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java make test-image CONF=$RELEASE_NAME || do_exit $? [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index af0d9eff6f0e..7f32e0dcd77a 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -1,46 +1,27 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) -# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to be built; possible values: -# or nomod - the release bundles without any additional modules (jcef) -# jcef - the release bundles with jcef -# fd - the fastdebug bundles which also include the jcef module +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# This script makes test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. # # Environment variables: +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument +# to configure +# By default JDK_BUILD_NUMBER is set zero # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_win_x64 -while getopts ":i?" o; do - case "${o}" in - i) - i="incremental build" - INC_BUILD=1 - ;; - esac -done -shift $((OPTIND-1)) - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -bundle_type=$4 -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') +source jb/project/tools/common/scripts/common.sh + WORK_DIR=$(pwd) JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64} -source jb/project/tools/common/scripts/common.sh - function do_configure { sh ./configure \ $WITH_DEBUG_LEVEL \ @@ -83,6 +64,7 @@ RELEASE_NAME=windows-x86_64-server-release case "$bundle_type" in "jcef") do_reset_changes=0 + do_maketest=1 ;; "dcevm") HEAD_REVISION=$(git rev-parse HEAD) @@ -102,13 +84,13 @@ esac if [ -z "$INC_BUILD" ]; then do_configure || do_exit $? - if [ -z "$bundle_type" ]; then + if [ $do_maketest -eq 1 ]; then make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? else make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? fi else - if [ -z "$bundle_type" ]; then + if [ $do_maketest -eq 1 ]; then make LOG=info CONF=$RELEASE_NAME images test-image || do_exit $? else make LOG=info CONF=$RELEASE_NAME images || do_exit $? diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 5a147d50a667..2079b0e338cc 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -1,29 +1,19 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used) -# JDK_BUILD_NUMBER - specifies udate release of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# bundle_type - specifies bundle to be built; possible values: -# or nomod - the bundles without any additional modules (jcef) -# jcef - the bundles with jcef -# fd - the fastdebug bundles which also include the jcef module +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# This script packs test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. # source jb/project/tools/common/scripts/common.sh -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 -bundle_type=$4 +[ "$bundle_type" == "jcef" ] && do_maketest=1 function pack_jbr { __bundle_name=$1 @@ -51,7 +41,7 @@ fi pack_jbr jbr${jbr_name_postfix} jbr pack_jbr jbrsdk${jbr_name_postfix} jbrsdk -if [ -z "$bundle_type" ]; then +if [ $do_maketest -eq 1 ]; then JBRSDK_TEST=$JBRSDK_BUNDLE-$JBSDK_VERSION-windows-test-x64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? From a6bb8452d0bbc4dcb90157721fb13a742755aff9 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Mon, 10 Jan 2022 18:06:13 +0300 Subject: [PATCH 061/976] JBR-4145 Make builds independent from build directory Supplied the --disable-absolute-path-in-output option to the configure script when building JBR. --- jb/project/tools/common/scripts/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index d3a00834f4e1..85258198077a 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -77,7 +77,7 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build --with-source-date=$SOURCE_DATE_EPOCH --with-hotspot-build-time=$BUILD_TIME --with-copyright-year=$COPYRIGHT_YEAR - --with-native-debug-symbols=none + --disable-absolute-paths-in-output --with-build-user=builduser" function do_exit() { From 2e5e6a4427c7ed4b89a37668674e5524c8397702 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Thu, 17 Feb 2022 11:11:39 +0300 Subject: [PATCH 062/976] JBR-3917 Problem using windows certificate store (trustStoreType=Windows-ROOT not recognized) --- .../project/tools/common/modules.list | 0 jb/project/tools/common/scripts/common.sh | 2 +- .../tools/linux/scripts/mkimages_aarch64.sh | 2 +- .../tools/linux/scripts/mkimages_x64.sh | 4 +- .../tools/linux/scripts/mkimages_x86.sh | 4 +- jb/project/tools/mac/scripts/mkimages.sh | 4 +- .../tools/patches/add_jcef_module.patch | 10 +- .../tools/windows/scripts/mkimages_x64.sh | 7 +- .../tools/windows/scripts/mkimages_x86.sh | 3 +- test/jdk/jb/build/CheckJBRModules.java | 106 ++++++++++++++++++ test/jdk/jb/build/CheckJBRModulesWindows.java | 53 +++++++++ 11 files changed, 178 insertions(+), 17 deletions(-) rename modules.list => jb/project/tools/common/modules.list (100%) create mode 100644 test/jdk/jb/build/CheckJBRModules.java create mode 100644 test/jdk/jb/build/CheckJBRModulesWindows.java diff --git a/modules.list b/jb/project/tools/common/modules.list similarity index 100% rename from modules.list rename to jb/project/tools/common/modules.list diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 85258198077a..59c32805f509 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -82,7 +82,7 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build function do_exit() { exit_code=$1 - [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java if [ $do_reset_dcevm -eq 1 ]; then [ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION fi diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 69fafce15926..cbcd452463b9 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -50,7 +50,7 @@ JBR_BASE_NAME=jbr-$JBSDK_VERSION rm -rf $BASE_DIR/$JBR_BUNDLE JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number -grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64 +grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64 echo Running jlink.... ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index bc1b677f1a5c..293a8ccd5a24 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -122,7 +122,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t fi # create runtime image bundle -modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle @@ -135,7 +135,7 @@ create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MOD if [ $do_maketest -eq 1 ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number} echo Creating "$JBRSDK_TEST" ... - [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java make test-image CONF=$RELEASE_NAME || do_exit $? tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 69278d653dfb..e1fcfd3cf420 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -61,7 +61,7 @@ JBR_BASE_NAME=jbr-$JBSDK_VERSION rm -rf $BASE_DIR/$JBR_BUNDLE JBR=$JBR_BASE_NAME-linux-x86-b$build_number -grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 +grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 echo Running jlink.... ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ @@ -77,4 +77,4 @@ gzip $JBR.tar || exit $? JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? \ No newline at end of file +gzip $JBRSDK_TEST.tar || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 01c015efc284..e4eedc4d82ec 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -155,7 +155,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t fi # create runtime image bundle -modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle @@ -168,7 +168,7 @@ create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_ if [ $do_maketest -eq 1 ]; then JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number} echo Creating "$JBRSDK_TEST" ... - [ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java + [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java make test-image CONF=$RELEASE_NAME || do_exit $? [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? diff --git a/jb/project/tools/patches/add_jcef_module.patch b/jb/project/tools/patches/add_jcef_module.patch index d28deca1f2c3..6a4aed824f6a 100644 --- a/jb/project/tools/patches/add_jcef_module.patch +++ b/jb/project/tools/patches/add_jcef_module.patch @@ -1,8 +1,8 @@ -diff --git modules.list modules.list -index 054f21d1ee0..d9a121f0273 100644 ---- modules.list -+++ modules.list -@@ -49,4 +49,7 @@ jdk.unsupported, +diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list +index 522acb7cb43..c40e689d5de 100644 +--- jb/project/tools/common/modules.list ++++ jb/project/tools/common/modules.list +@@ -51,4 +51,7 @@ jdk.unsupported.desktop, jdk.xml.dom, jdk.zipfs, jdk.hotspot.agent, diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 7f32e0dcd77a..06604d8db076 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -115,8 +115,9 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t jbr_name_postfix="_${bundle_type}" fi -# create runtime image bundle -modules=$(xargs < modules.list | sed s/" "//g) || do_exit $? +# create runtime image bundlef +modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? +modules+=",jdk.crypto.mscapi" create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? # create sdk image bundle @@ -126,4 +127,4 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_t fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? -do_exit 0 \ No newline at end of file +do_exit 0 diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index d4041e37634c..15e05184a15a 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -53,7 +53,8 @@ mv release ${JBRSDK_BUNDLE}/release JBR_BUNDLE=jbr rm -rf ${JBR_BUNDLE} -grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 +grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 +echo ",jdk.crypto.mscapi" >> modules.list.x86 ${JSDK}/bin/jlink \ --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ --add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? diff --git a/test/jdk/jb/build/CheckJBRModules.java b/test/jdk/jb/build/CheckJBRModules.java new file mode 100644 index 000000000000..681692ffd67a --- /dev/null +++ b/test/jdk/jb/build/CheckJBRModules.java @@ -0,0 +1,106 @@ +/* + * Copyright 2022 JetBrains s.r.o. + * 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. + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @requires !vm.graal.enabled + * @summary Verifies the list of available modules + * @library /test/lib + * @run main CheckJBRModules + */ +public class CheckJBRModules { + static final String moduleNames[] = { + "java.base", + "java.compiler", + "java.datatransfer", + "java.desktop", + "java.instrument", + "java.logging", + "java.management", + "java.management.rmi", + "java.naming", + "java.net.http", + "java.prefs", + "java.rmi", + "java.scripting", + "java.se", + "java.security.jgss", + "java.security.sasl", + "java.smartcardio", + "java.sql", + "java.sql.rowset", + "java.transaction.xa", + "java.xml", + "java.xml.crypto", + "jdk.accessibility", + "jdk.attach", + "jdk.charsets", + "jdk.compiler", + "jdk.crypto.cryptoki", + "jdk.crypto.ec", + "jdk.dynalink", + "jdk.httpserver", + "jdk.internal.ed", + "jdk.internal.le", + "jdk.internal.vm.ci", + "jdk.javadoc", + "jdk.jdi", + "jdk.jdwp.agent", + "jdk.jfr", + "jdk.jsobject", + "jdk.localedata", + "jdk.management", + "jdk.management.agent", + "jdk.management.jfr", + "jdk.naming.dns", + "jdk.naming.rmi", + "jdk.net", + "jdk.sctp", + "jdk.security.auth", + "jdk.security.jgss", + "jdk.unsupported", + "jdk.unsupported.desktop", + "jdk.xml.dom", + "jdk.zipfs", + "jdk.hotspot.agent", + "jdk.jcmd" }; + + public static void main(String args[]) throws Exception { + final OutputAnalyzer oa = exec("--list-modules").shouldHaveExitValue(0); + for(String moduleName : moduleNames) { + oa.shouldContain(moduleName); + } + } + + /** + * java args... returning the OutputAnalyzer to analyzer the output + */ + private static OutputAnalyzer exec(String... args) throws Exception { + return ProcessTools.executeTestJava(args) + .outputTo(System.out) + .errorTo(System.out); + } +} diff --git a/test/jdk/jb/build/CheckJBRModulesWindows.java b/test/jdk/jb/build/CheckJBRModulesWindows.java new file mode 100644 index 000000000000..46c494f11a93 --- /dev/null +++ b/test/jdk/jb/build/CheckJBRModulesWindows.java @@ -0,0 +1,53 @@ +/* + * Copyright 2022 JetBrains s.r.o. + * 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. + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @requires !vm.graal.enabled + * @requires (os.family == "windows") + * @summary Verifies the list of available modules specific to Windows + * @library /test/lib + * @run main CheckJBRModulesWindows + */ +public class CheckJBRModulesWindows { + static final String moduleNames[] = { "jdk.crypto.mscapi" }; + + public static void main(String args[]) throws Exception { + final OutputAnalyzer oa = exec("--list-modules").shouldHaveExitValue(0); + for(String moduleName : moduleNames) { + oa.shouldContain(moduleName); + } + } + + /** + * java args... returning the OutputAnalyzer to analyzer the output + */ + private static OutputAnalyzer exec(String... args) throws Exception { + return ProcessTools.executeTestJava(args) + .outputTo(System.out) + .errorTo(System.out); + } +} From 303f17fdf3a2449910a46e5d51ba9a2ff9eb2edb Mon Sep 17 00:00:00 2001 From: Vladimir Kempik Date: Thu, 17 Feb 2022 17:31:33 +0300 Subject: [PATCH 063/976] JBR-4242:Provide native JBR builds for alpine Linux --- jb/project/docker/Dockerfile.musl_x64 | 22 ++++++++++++++++ jb/project/docker/mkdocker_musl_x64.sh | 26 +++++++++++++++++++ .../tools/linux/scripts/mkimages_x64.sh | 17 ++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 jb/project/docker/Dockerfile.musl_x64 create mode 100755 jb/project/docker/mkdocker_musl_x64.sh diff --git a/jb/project/docker/Dockerfile.musl_x64 b/jb/project/docker/Dockerfile.musl_x64 new file mode 100644 index 000000000000..b8cea877d351 --- /dev/null +++ b/jb/project/docker/Dockerfile.musl_x64 @@ -0,0 +1,22 @@ +# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_x64.sh script. + +# Pull a concrete version of Linux that does NOT recieve updates after it's +# been created. This is so that the image is as stable as possible to make +# image creation reproducible. +# NB: this also means there may be no security-related fixes there, need to +# move the version to the next manually. +FROM alpine:3.5 + +# Install the necessary build tools +RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \ + git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \ + libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \ + fontconfig fontconfig-dev linux-headers + +# Set up boot JDK for building +COPY boot_jdk_musl_amd64.tar.gz /jdk17/ +RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_amd64.tar.gz && rm /jdk17/boot_jdk_musl_amd64.tar.gz +ENV BOOT_JDK=/jdk17 + +RUN git config --global user.email "teamcity@jetbrains.com" && \ + git config --global user.name "builduser" diff --git a/jb/project/docker/mkdocker_musl_x64.sh b/jb/project/docker/mkdocker_musl_x64.sh new file mode 100755 index 000000000000..5bec8bbfbc97 --- /dev/null +++ b/jb/project/docker/mkdocker_musl_x64.sh @@ -0,0 +1,26 @@ +#!/bin/bash -x + +# This script creates a Docker image suitable for building musl-x64 variant +# of the JetBrains Runtime version 17. + +BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_x64.tar.gz +BOOT_JDK_SHA=bcc5342011bd9f3643372aadbdfa68d47463ff0d8621668a0bdf2910614d95c6 +BOOT_JDK_LOCAL_FILE=boot_jdk_musl_amd64.tar.gz + +if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then + # Obtain "boot JDK" from outside of the container. + wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE +else + echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download" +fi + +# Verify that what we've downloaded can be trusted. +sha256sum -c - < Date: Tue, 22 Feb 2022 16:09:14 +0300 Subject: [PATCH 064/976] JBR-4283: Provide native JBR builds for alpine Linux-aarch64 --- jb/project/docker/Dockerfile.musl_aarch64 | 22 ++++++++++++++++ jb/project/docker/mkdocker_musl_aarch64.sh | 26 +++++++++++++++++++ .../tools/linux/scripts/mkimages_aarch64.sh | 19 +++++++++++--- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 jb/project/docker/Dockerfile.musl_aarch64 create mode 100755 jb/project/docker/mkdocker_musl_aarch64.sh diff --git a/jb/project/docker/Dockerfile.musl_aarch64 b/jb/project/docker/Dockerfile.musl_aarch64 new file mode 100644 index 000000000000..108f63451ea9 --- /dev/null +++ b/jb/project/docker/Dockerfile.musl_aarch64 @@ -0,0 +1,22 @@ +# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_aarch64.sh script. + +# Pull a concrete version of Linux that does NOT recieve updates after it's +# been created. This is so that the image is as stable as possible to make +# image creation reproducible. +# NB: this also means there may be no security-related fixes there, need to +# move the version to the next manually. +FROM arm64v8/alpine:3.12 + +# Install the necessary build tools +RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \ + git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \ + libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \ + fontconfig fontconfig-dev linux-headers + +# Set up boot JDK for building +COPY boot_jdk_musl_aarch64.tar.gz /jdk17/ +RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_aarch64.tar.gz && rm /jdk17/boot_jdk_musl_aarch64.tar.gz +ENV BOOT_JDK=/jdk17 + +RUN git config --global user.email "teamcity@jetbrains.com" && \ + git config --global user.name "builduser" diff --git a/jb/project/docker/mkdocker_musl_aarch64.sh b/jb/project/docker/mkdocker_musl_aarch64.sh new file mode 100755 index 000000000000..b0c292d2c762 --- /dev/null +++ b/jb/project/docker/mkdocker_musl_aarch64.sh @@ -0,0 +1,26 @@ +#!/bin/bash -x + +# This script creates a Docker image suitable for building musl AArch64 variant +# of the JetBrains Runtime version 17. + +BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_aarch64.tar.gz +BOOT_JDK_SHA=6b920559abafbe9bdef386a20ecf3a2f318bc1f0d8359eb1f95aee26606bbc70 +BOOT_JDK_LOCAL_FILE=boot_jdk_musl_aarch64.tar.gz + +if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then + # Obtain "boot JDK" from outside of the container. + wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE +else + echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download" +fi + +# Verify that what we've downloaded can be trusted. +sha256sum -c - < modules.list.aarch64 echo Running jlink.... ${JSDK}/bin/jlink \ @@ -65,7 +78,7 @@ tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar gzip $JBR.tar || exit $? -JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number +JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}test-aarch64-b$build_number echo Creating $JBRSDK_TEST.tar.gz ... tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? gzip $JBRSDK_TEST.tar || exit $? From 7c80ac29b0a70cee8d36e9f3596f7de27b025074 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 14 Oct 2021 09:23:35 +0700 Subject: [PATCH 065/976] JBR-4188 add script comparing performance results add exec permissions && fix misprint in checking if headers exist move the script comparing performance results from jdk8u_test --- jb/project/tools/test/perfcmp.sh | 83 ++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 jb/project/tools/test/perfcmp.sh diff --git a/jb/project/tools/test/perfcmp.sh b/jb/project/tools/test/perfcmp.sh new file mode 100755 index 000000000000..45d7d05baeeb --- /dev/null +++ b/jb/project/tools/test/perfcmp.sh @@ -0,0 +1,83 @@ +#!/bin/bash -x + +usage () +{ +echo "Usage: perfcmp.sh [options] " +echo "Options:" +echo -e " -h, --help\tdisplay this help" +echo -e " -tc\tprint teacmity statistic" +echo -e "test_results_cur - the file with metrics values for the current measuring" +echo -e "test_results_ref - the file with metrics values for the reference measuring" +echo -e "results - results of comaprison" +echo -e "test_prefix - specifys measuring type, makes sense for enabled -tc, by default no prefixes" +echo -e "noHeaders - by default 1-st line contains headers" +echo -e "" +echo -e "test_results_* files content should be in csv format with header and tab separator:" +echo -e "The 1-st column is the test name" +echo -e "The 2-st column is the test value" +echo -e "" +echo -e "Example:" +echo -e "Test Value" +echo -e "Testname 51.54" +} + +while [ -n "$1" ] +do +case "$1" in +-h | --help) usage +exit 1 ;; +-tc) tc=1 + shift + break ;; +*) break;; +esac +done + +if [[ "$#" < "3" ]]; then + echo "Error: Invalid arguments" + usage + exit 1 +fi + +curFile=$1 +refFile=$2 +resFile=$3 +testNamePrefix=$4 +noHeaders=$5 +echo $curFile +echo $refFile +echo $resFile + +curValues=`cat "$curFile" | cut -f 2 | tr -d '\t'` +if [ -z $noHeaders ]; then + curValuesHeader=`echo "$curValues" | head -n +1`_cur + header=`cat "$refFile" | head -n +1 | awk -F'\t' -v x=$curValuesHeader '{print " "$1"\t"$2"_ref\t"x"\tratio"}'` + testContent=`paste -d '\t' $refFile <(echo "$curValues") | tail -n +2` +else + testContent=`paste -d '\t' $refFile <(echo "$curValues") | tail -n +1` +fi + +testContent=`echo "$testContent" | awk -F'\t' '{ if ($3>$2+$2*0.1) {print "* "$1"\t"$2"\t"$3"\t"(($2==0)?"-":$3/$2)} else {print " "$1"\t"$2"\t"$3"\t"(($2==0)?"-":$3/$2)} }'` +if [ -z $noHeaders ]; then + echo "$header" > $resFile +fi +echo "$testContent" >> $resFile +cat "$resFile" | tr '\t' ';' | column -t -s ';' | tee $resFile + +if [ -z $tc ]; then +exit 0 +fi + +echo "$testContent" 2>&1 | ( + while read -r s; do + testname=`echo "$s" | cut -f 1 | tr -d "[:space:]" | tr -d "*"` + duration=`echo "$s" | cut -f 3` + failed=`echo "$s" | cut -c1 | grep -c "*"` + echo \#\#teamcity[testStarted name=\'$testNamePrefix$testname\'] + echo "===>$s" + echo \#\#teamcity[buildStatisticValue key=\'$testNamePrefix$testname\' value=\'$duration\'] + [ $failed -eq 1 ] && echo \#\#teamcity[testFailed name=\'$testNamePrefix$testname\' message=\'$s\'] + echo \#\#teamcity[testFinished name=\'$testNamePrefix$testname\' duration=\'$duration\'] + failed=0 + done +) \ No newline at end of file From 961048ecbc71fbad5e20819ab3c52cf97f3c5fc0 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 22 Apr 2022 21:24:34 +0300 Subject: [PATCH 066/976] JBR-3906 JBR for Linux aarch64 with JCEF is missing, is there any support plan? --- .../tools/linux/scripts/mkimages_aarch64.sh | 199 ++++++++++++------ .../patches/add_jcef_module_aarch64.patch | 30 +++ 2 files changed, 166 insertions(+), 63 deletions(-) create mode 100644 jb/project/tools/patches/add_jcef_module_aarch64.patch diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 350f9f1d66c6..934e341c580d 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -1,11 +1,41 @@ #!/bin/bash -x -# The following parameter must be specified: +# The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # +# This script makes test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. +# +# Environment variables: +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument +# to configure +# By default JDK_BUILD_NUMBER is set zero +# JCEF_PATH - specifies the path to the directory with JCEF binaries. +# By default JCEF binaries should be located in ./jcef_linux_aarch64 source jb/project/tools/common/scripts/common.sh +JCEF_PATH=${JCEF_PATH:=./jcef_linux_aarch64} + +function do_configure { + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? +} + function is_musl { libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1) if [ -z $libc ]; then @@ -15,70 +45,113 @@ function is_musl { return 0 } -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} - -LIBC_TYPE_SUFFIX='' - -if is_musl; then LIBC_TYPE_SUFFIX='musl-' ; fi - -sh configure \ - --with-debug-level=release \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="${JDK_BUILD_NUMBER}" \ - --with-version-opt=b${build_number} \ - --with-boot-jdk=${BOOT_JDK} \ - --enable-cds=yes \ - $REPRODUCIBLE_BUILD_OPTS \ - || exit $? -make clean CONF=linux-aarch64-server-release || exit $? -make images CONF=linux-aarch64-server-release test-image || exit $? - -JBSDK=${JBRSDK_BASE_NAME}-linux-${LIBC_TYPE_SUFFIX}aarch64-b${build_number} -BASE_DIR=build/linux-aarch64-server-release/images -JSDK=${BASE_DIR}/jdk +function create_image_bundle { + __bundle_name=$1 + __arch_name=$2 + __modules_path=$3 + __modules=$4 + + libc_type_suffix='' + + if is_musl; then libc_type_suffix='musl-' ; fi + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}aarch64-${fastdebug_infix}b${build_number} + + echo Running jlink.... + [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + $JSDK/bin/jlink \ + --module-path "$__modules_path" --no-man-pages --compress=2 \ + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release + mv release "$IMAGES_DIR"/"$__arch_name"/release + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + fi + + # jmod does not preserve file permissions (JDK-8173610) + [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + + echo Creating "$JBR".tar.gz ... + + (cd "$IMAGES_DIR" && + find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + tar $REPRODUCIBLE_TAR_OPTS \ + --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? + mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar + [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" + touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar + gzip "$JBR".tar || do_exit $? + rm -rf "${IMAGES_DIR:?}"/"$__arch_name" +} + +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=linux-aarch64-server-release + +case "$bundle_type" in + "jcef") + do_reset_changes=1 + do_maketest=1 + ;; + "dcevm") + HEAD_REVISION=$(git rev-parse HEAD) + git am jb/project/tools/patches/dcevm/*.patch || do_exit $? + do_reset_dcevm=0 + do_reset_changes=0 + ;; + "nomod" | "") + bundle_type="" + ;; + "fd") + do_reset_changes=1 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=linux-aarch64-server-fastdebug + ;; +esac + +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + make clean CONF=$RELEASE_NAME || do_exit $? +fi +make images CONF=$RELEASE_NAME || do_exit $? + +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -rm -rf $BASE_DIR/$JBRSDK_BUNDLE -cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? - -echo Creating $JBSDK.tar.gz ... -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - -# NB: --sort=name requires tar1.28 -tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBSDK.tar \ - --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \ - -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? -touch -c -d @$SOURCE_DATE_EPOCH $JBRSDK.tar -gzip $JBSDK.tar || exit $? - -JBR_BUNDLE=jbr -JBR_BASE_NAME=jbr-$JBSDK_VERSION -rm -rf $BASE_DIR/$JBR_BUNDLE - -JBR=$JBR_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}aarch64-b$build_number -grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64 -echo Running jlink.... -${JSDK}/bin/jlink \ - --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/',$'//g) \ - --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? - -echo Modifying release info ... -grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release - -echo Creating $JBR.tar.gz ... -tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $? -touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar -gzip $JBR.tar || exit $? - -JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}test-aarch64-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then + git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $? + update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $? + cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed + + jbr_name_postfix="_${bundle_type}" +fi + +# create runtime image bundle +modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? + +# create sdk image bundle +modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? + +if [ $do_maketest -eq 1 ]; then + JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-aarch64-b${build_number} + echo Creating "$JBRSDK_TEST" ... + [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java + make test-image CONF=$RELEASE_NAME || do_exit $? + tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + gzip "$JBRSDK_TEST".tar || do_exit $? +fi + +do_exit 0 diff --git a/jb/project/tools/patches/add_jcef_module_aarch64.patch b/jb/project/tools/patches/add_jcef_module_aarch64.patch new file mode 100644 index 000000000000..2752dc95f3b9 --- /dev/null +++ b/jb/project/tools/patches/add_jcef_module_aarch64.patch @@ -0,0 +1,30 @@ +diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list +index 522acb7..c40e689 100644 +--- jb/project/tools/common/modules.list ++++ jb/project/tools/common/modules.list +@@ -51,4 +51,7 @@ jdk.unsupported.desktop, + jdk.xml.dom, + jdk.zipfs, + jdk.hotspot.agent, +-jdk.jcmd ++jdk.jcmd, ++jcef, ++gluegen.rt, ++jogl.all +diff --git src/java.desktop/share/classes/module-info.java src/java.desktop/share/classes/module-info.java +index 897647e..781d180 100644 +--- src/java.desktop/share/classes/module-info.java ++++ src/java.desktop/share/classes/module-info.java +@@ -116,7 +116,11 @@ module java.desktop { + // see make/GensrcModuleInfo.gmk + exports sun.awt to + jdk.accessibility, +- jdk.unsupported.desktop; ++ jdk.unsupported.desktop, ++ jcef, ++ jogl.all; ++ ++ exports java.awt.peer to jcef; + + exports java.awt.dnd.peer to jdk.unsupported.desktop; + exports sun.awt.dnd to jdk.unsupported.desktop; From d08112162d7aec088d2669329054a3396e1e3793 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 3 May 2022 08:45:33 +0700 Subject: [PATCH 067/976] JBR-4437 add sources to JBRSDK distributions --- jb/project/tools/mac/scripts/mkimages.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index e4eedc4d82ec..929e1e36aacc 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -85,6 +85,7 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release mv release $JRE_CONTENTS/Home/release + cp $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home/lib/src.zip $JRE_CONTENTS/Home/lib copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods fi From 2ff62e938bc348e092260fdb6c739229fe8bbdef Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 13 May 2022 06:15:29 +0700 Subject: [PATCH 068/976] JBR-4437 add sources to JBRSDK distributions for Windows and Linux --- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 1 + jb/project/tools/linux/scripts/mkimages_x64.sh | 1 + jb/project/tools/windows/scripts/mkimages_x64.sh | 1 + 3 files changed, 3 insertions(+) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 934e341c580d..c071dac58dc1 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -68,6 +68,7 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release mv release "$IMAGES_DIR"/"$__arch_name"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods fi diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 5d57081694dc..f606e14671de 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -68,6 +68,7 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release mv release "$IMAGES_DIR"/"$__arch_name"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods fi diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 06604d8db076..c7ed22bdeb04 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -54,6 +54,7 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $__arch_name/release > release mv release $__arch_name/release + cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods fi } From 1a9318a6f86f1438b36ed5104c55804c2a82fac3 Mon Sep 17 00:00:00 2001 From: Vladimir Kempik Date: Fri, 20 May 2022 14:30:29 +0300 Subject: [PATCH 069/976] JBR-4452: Update crash report message with JBR youtrack link instead of bugreport.java.com --- jb/project/tools/common/scripts/common.sh | 5 +++++ jb/project/tools/common/static_conf_args.txt | 1 + jb/project/tools/linux/scripts/mkimages_aarch64.sh | 1 + jb/project/tools/linux/scripts/mkimages_x64.sh | 1 + jb/project/tools/linux/scripts/mkimages_x86.sh | 1 + jb/project/tools/mac/scripts/mkimages.sh | 2 ++ jb/project/tools/windows/scripts/mkimages_x64.sh | 1 + jb/project/tools/windows/scripts/mkimages_x86.sh | 1 + 8 files changed, 13 insertions(+) create mode 100644 jb/project/tools/common/static_conf_args.txt diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 59c32805f509..e634cc0d01b4 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -49,6 +49,11 @@ do_reset_changes=0 do_reset_dcevm=0 HEAD_REVISION=0 +STATIC_CONF_ARGS="" +common_conf_props_file="jb/project/tools/common/static_conf_args.txt" +if [[ -f "$common_conf_props_file" ]]; then + STATIC_CONF_ARGS=$(<$common_conf_props_file) +fi OS_NAME=$(uname -s) # Enable reproducible builds TZ=UTC diff --git a/jb/project/tools/common/static_conf_args.txt b/jb/project/tools/common/static_conf_args.txt new file mode 100644 index 000000000000..b29477301ac8 --- /dev/null +++ b/jb/project/tools/common/static_conf_args.txt @@ -0,0 +1 @@ +--with-vendor-vm-bug-url=https://youtrack.jetbrains.com/issues/JBR \ No newline at end of file diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index c071dac58dc1..4300e5ce80a7 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -32,6 +32,7 @@ function do_configure { --with-version-opt=b"$build_number" \ --with-boot-jdk="$BOOT_JDK" \ --enable-cds=yes \ + $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ || do_exit $? } diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index f606e14671de..481aae53ae54 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -32,6 +32,7 @@ function do_configure { --with-version-opt=b"$build_number" \ --with-boot-jdk="$BOOT_JDK" \ --enable-cds=yes \ + $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ || do_exit $? } diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index e1fcfd3cf420..f74ef643c412 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -34,6 +34,7 @@ linux32 bash configure \ --with-version-build=$JDK_BUILD_NUMBER \ --with-version-opt=b${build_number} \ --with-boot-jdk=${BOOT_JDK} \ + $STATIC_CONF_ARGS \ --enable-cds=yes || exit $? make clean CONF=linux-x86-server-release || exit $? make images CONF=linux-x86-server-release test-image || exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 929e1e36aacc..16d960985192 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -41,6 +41,7 @@ function do_configure { --with-extra-cflags="-F$(pwd)/Frameworks" \ --with-extra-cxxflags="-F$(pwd)/Frameworks" \ --with-extra-ldflags="-F$(pwd)/Frameworks" \ + $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ || do_exit $? else @@ -56,6 +57,7 @@ function do_configure { --with-version-opt=b"$build_number" \ --with-boot-jdk="$BOOT_JDK" \ --enable-cds=yes \ + $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ || do_exit $? fi diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index c7ed22bdeb04..c152bf138a98 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -34,6 +34,7 @@ function do_configure { --with-toolchain-version=$TOOLCHAIN_VERSION \ --with-boot-jdk=$BOOT_JDK \ --disable-ccache \ + $STATIC_CONF_ARGS \ --enable-cds=yes || do_exit $? } diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 15e05184a15a..97c7b51be1d2 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -38,6 +38,7 @@ PATH="/usr/local/bin:/usr/bin:${PATH}" --with-toolchain-version=${TOOLCHAIN_VERSION} \ --with-boot-jdk=${BOOT_JDK} \ --disable-ccache \ + $STATIC_CONF_ARGS \ --enable-cds=yes || exit 1 make clean CONF=windows-x86-server-release || exit 1 make LOG=info images CONF=windows-x86-server-release test-image || exit 1 From 568ff618dc2eae3c09043a52a8f05c23402ba932 Mon Sep 17 00:00:00 2001 From: Nikita Provotorov Date: Mon, 23 May 2022 10:38:41 +0100 Subject: [PATCH 070/976] JBR-2074 Windows 10 AArch64 support: add build and pack scripts. --- .../tools/windows/scripts/mkimages_aarch64.sh | 134 ++++++++++++++++++ .../tools/windows/scripts/pack_aarch64.sh | 48 +++++++ 2 files changed, 182 insertions(+) create mode 100644 jb/project/tools/windows/scripts/mkimages_aarch64.sh create mode 100644 jb/project/tools/windows/scripts/pack_aarch64.sh diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh new file mode 100644 index 000000000000..40647cc80a23 --- /dev/null +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -0,0 +1,134 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module +# +# This script makes test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. +# +# Environment variables: +# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument +# to configure +# By default JDK_BUILD_NUMBER is set zero +# JCEF_PATH - specifies the path to the directory with JCEF binaries. +# By default JCEF binaries should be located in ./jcef_win_aarch64 + +source jb/project/tools/common/scripts/common.sh + +WORK_DIR=$(pwd) +JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_aarch64} + +function do_configure { + sh ./configure \ + --openjdk-target=aarch64-unknown-cygwin \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b${build_number} \ + --with-toolchain-version=$TOOLCHAIN_VERSION \ + --with-boot-jdk=$BOOT_JDK \ + --with-build-jdk=$BOOT_JDK \ + --disable-ccache \ + $STATIC_CONF_ARGS \ + --enable-cds=yes || do_exit $? +} + +function create_image_bundle { + __bundle_name=$1 + __arch_name=$2 + __modules_path=$3 + __modules=$4 + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + + echo Running jlink ... + ${BOOT_JDK}/bin/jlink \ + --module-path $__modules_path --no-man-pages --compress=2 \ + --add-modules $__modules --output $__arch_name || do_exit $? + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $__arch_name/release > release + mv release $__arch_name/release + cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib + copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods + fi +} + +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=windows-aarch64-server-release + +case "$bundle_type" in + "jcef") + do_reset_changes=0 + do_maketest=1 + ;; + "dcevm") + HEAD_REVISION=$(git rev-parse HEAD) + git am jb/project/tools/patches/dcevm/*.patch || do_exit $? + do_reset_dcevm=0 + do_reset_changes=0 + ;; + "nomod" | "") + bundle_type="" + ;; + "fd") + do_reset_changes=0 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=windows-aarch64-server-fastdebug + ;; +esac + +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + if [ $do_maketest -eq 1 ]; then + make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? + fi +else + if [ $do_maketest -eq 1 ]; then + make LOG=info CONF=$RELEASE_NAME images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME images || do_exit $? + fi +fi + +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods +JBRSDK_BUNDLE=jbrsdk + +where cygpath +if [ $? -eq 0 ]; then + JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" +fi + +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then + git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $? + update_jsdk_mods "$BOOT_JDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? + cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not unchanged + + jbr_name_postfix="_${bundle_type}" +fi + +# create runtime image bundle +modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? +modules+=",jdk.crypto.mscapi" +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? + +# create sdk image bundle +modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) || do_exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? + +do_exit 0 diff --git a/jb/project/tools/windows/scripts/pack_aarch64.sh b/jb/project/tools/windows/scripts/pack_aarch64.sh new file mode 100644 index 000000000000..2732a87a704f --- /dev/null +++ b/jb/project/tools/windows/scripts/pack_aarch64.sh @@ -0,0 +1,48 @@ +#!/bin/bash -x + +# The following parameters must be specified: +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module +# +# This script packs test-image along with JDK images when bundle_type is set to "jcef". +# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images. +# + +source jb/project/tools/common/scripts/common.sh + +[ "$bundle_type" == "jcef" ] && do_maketest=1 + +function pack_jbr { + __bundle_name=$1 + __arch_name=$2 + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} + + echo Creating $JBR.tar.gz ... + + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? +} + +[ "$bundle_type" == "nomod" ] && bundle_type="" + +JBRSDK_BUNDLE=jbrsdk +RELEASE_NAME=windows-aarch64-server-release +IMAGES_DIR=build/$RELEASE_NAME/images +BASE_DIR=. + +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then + jbr_name_postfix="_${bundle_type}" +fi + +pack_jbr jbr${jbr_name_postfix} jbr +pack_jbr jbrsdk${jbr_name_postfix} jbrsdk + +if [ $do_maketest -eq 1 ]; then + JBRSDK_TEST=$JBRSDK_BUNDLE-$JBSDK_VERSION-windows-test-aarch64-b$build_number + echo Creating $JBRSDK_TEST.tar.gz ... + /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? +fi \ No newline at end of file From 5e2fc8e8d7045a6269d7d080a2fe7d64aa97cf1c Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 27 Apr 2022 14:59:49 +0700 Subject: [PATCH 071/976] JBR-4370 create a test checking all JBR artifacts exist - add exit code --- test/jdk/jb/build/check_for_artifacts.sh | 135 +++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 test/jdk/jb/build/check_for_artifacts.sh diff --git a/test/jdk/jb/build/check_for_artifacts.sh b/test/jdk/jb/build/check_for_artifacts.sh new file mode 100755 index 000000000000..7d6d7964ef90 --- /dev/null +++ b/test/jdk/jb/build/check_for_artifacts.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# +# Copyright 2000-2022 JetBrains s.r.o. +# 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. +# + +# The test checks all required JBR artifacts were built and published + +dirname=$1 +jbsdk_version=$2 +build_number=$3 + + +read -r -d '' allArtifacts << EndOFArtifactsList +jbr-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz +jbr-${jbsdk_version}-linux-musl-aarch64-b${build_number}.tar.gz +jbr-${jbsdk_version}-linux-musl-x64-b${build_number}.tar.gz +jbr-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbr-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz +jbr-${jbsdk_version}-osx-x64-b${build_number}.tar.gz +jbr-${jbsdk_version}-windows-x64-b${build_number}.tar.gz + +jbr_fd-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz +jbr_fd-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbr_fd-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz +jbr_fd-${jbsdk_version}-osx-x64-b${build_number}.tar.gz +jbr_fd-${jbsdk_version}-windows-x64-b${build_number}.tar.gz + +jbr_jcef-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz +jbr_jcef-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbr_jcef-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz +jbr_jcef-${jbsdk_version}-osx-aarch64-b${build_number}.pkg +jbr_jcef-${jbsdk_version}-osx-x64-b${build_number}.tar.gz +jbr_jcef-${jbsdk_version}-osx-x64-b${build_number}.pkg +jbr_jcef-${jbsdk_version}-windows-x64-b${build_number}.tar.gz + +jbr-${jbsdk_version}-osx-aarch64-b${build_number}.pkg +jbr-${jbsdk_version}-osx-x64-b${build_number}.pkg +jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}.pkg +jbrsdk-${jbsdk_version}-osx-x64-b${build_number}.pkg + +jbrsdk-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-windows-x64-b${build_number}.tar.gz + +jbrsdk-${jbsdk_version}-linux-test-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-test-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-test-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-test-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-test-aarch64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-test-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-windows-test-x64-b${build_number}.tar.gz + +jbrsdk-${jbsdk_version}-linux-aarch64-fastdebug-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-x64-fastdebug-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-aarch64-fastdebug-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-osx-x64-fastdebug-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-windows-x64-fastdebug-b${build_number}.tar.gz + +jbrsdk-${jbsdk_version}-linux-aarch64-fastdebug-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-aarch64-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-linux-musl-x64-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-linux-x64-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-linux-x64-fastdebug-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-osx-aarch64-fastdebug-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-osx-x64-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-osx-x64-fastdebug-b${build_number}_diz.tar.gz + +jbrsdk_jcef-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz +jbrsdk_jcef-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbrsdk_jcef-${jbsdk_version}-osx-aarch64-b${build_number}.pkg +jbrsdk_jcef-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz +jbrsdk_jcef-${jbsdk_version}-osx-x64-b${build_number}.pkg +jbrsdk_jcef-${jbsdk_version}-osx-x64-b${build_number}.tar.gz +jbrsdk_jcef-${jbsdk_version}-windows-x64-b${build_number}.tar.gz + +jbrsdk_jcef-${jbsdk_version}-linux-x64-b${build_number}_diz.tar.gz +jbrsdk_jcef-${jbsdk_version}-osx-aarch64-b${build_number}_diz.tar.gz +jbrsdk_jcef-${jbsdk_version}-osx-x64-b${build_number}_diz.tar.gz + +EndOFArtifactsList + +testname="JBRArtifacts" +count=$(echo $allArtifacts | wc -w) +n=0 +echo \#\#teamcity[testStarted name=\'$testname\'] +echo "Non existing artifacts:" +for artifact in $allArtifacts; do + isFound=$(ls $dirname | grep -c $artifact) + if [ $isFound -eq 0 ]; then + n=$((n+1)) + echo -e "\t$artifact" + fi +done + +echo "Extra artifacts:" +for relpath in $(ls $dirname); do + filename=$(basename $relpath) + isFound=$(echo $allArtifacts | grep -c $filename) + if [ $isFound -eq 0 ]; then + n=$((n+1)) + echo -e "\t$filename" + fi +done +if [ $n -eq 0 ]; then + echo \#\#teamcity[testFinished name=\'$testname\'] +else + echo \#\#teamcity[testFailed name=\'$testname\' message=\'Some artifacts cannot be found\'] +fi + +exit $n \ No newline at end of file From 0e3c54d66f0056e5d91870b3fcda1092a19ffad8 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 14 Dec 2021 09:00:03 +0700 Subject: [PATCH 072/976] JBR-4053 integrate DCEVM patches as usual commits --- .../tools/linux/scripts/mkimages_x64.sh | 10 +- jb/project/tools/mac/scripts/mkimages.sh | 10 +- .../0001-Apply-basic-dcevm11-patch.patch | 8853 ----------------- .../patches/dcevm/0002-dcevm11-fixes.patch | 1569 --- ...xception-on-redefinition-of-class-A-.patch | 29 - .../dcevm/0004-HotswapAgent-integration.patch | 1086 -- ...upport-for-Lambda-class-redefinition.patch | 240 - ...bytecode-found-error-if-method-with-.patch | 135 - ...method-with-Universe-throw_no_such_m.patch | 57 - .../dcevm/0008-Support-for-G1-gc.patch | 1310 --- ...e-log-level-in-advanced-redefinition.patch | 50 - ...ssRedefinition-is-false-disabled-by-.patch | 26 - ...edRedefineClasses.-to-CMakeLists.txt.patch | 2977 ------ ...POT_VM_DISTRO-Dynamic-Code-Evolution.patch | 25 - .../0013-Fix-G1-nmethod-registration.patch | 71 - ...d-s-_new_version-_old_version-to-NUL.patch | 26 - .../0015-Clear-dcevm-code-separation.patch | 193 - ...sClosure-fixes-problems-with-remote-.patch | 26 - ...-Cleanup-code-related-to-removed-CMS.patch | 3934 -------- ...GC-spaces-originally-in-removed-CMS-.patch | 183 - ...-fix-java15-patch-compilation-issues.patch | 942 -- .../patches/dcevm/0020-dcevm15-G1-fixes.patch | 25 - ...021-dcevm15-Fix-flush-dependent-code.patch | 133 - ...0022-dcevm15-fix-ResolvedMethodTable.patch | 211 - ...23-dcevm15-fix-Universe-root_oops_do.patch | 88 - .../dcevm/0024-Cleanup-dcevm-comments.patch | 67 - ...ot-AllowEnhancedClassRedefinition-mo.patch | 43 - ...m15-add-ClassLoaderDataGraph_lock-on.patch | 32 - ...-has_nestmate_access_to-has-newest-h.patch | 29 - .../dcevm/0028-Remove-unused-fieldType.patch | 24 - ...rk_as_scavengable-only-alive-methods.patch | 54 - ...ClassLoaderDataGraph-rollback_redefi.patch | 28 - ...G1IterateObjectClosureTask-fixing-me.patch | 28 - .../0032-dcevm15-fix-hidded-classes.patch | 91 - ...ear-F2-in-CP-cache-after-indy-unevol.patch | 27 - ...34-dcevm15-fix-Universe-root_oops_do.patch | 49 - .../tools/windows/scripts/mkimages_aarch64.sh | 10 +- .../tools/windows/scripts/mkimages_x64.sh | 10 +- 38 files changed, 8 insertions(+), 22693 deletions(-) delete mode 100644 jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch delete mode 100644 jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch delete mode 100644 jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch delete mode 100644 jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch delete mode 100644 jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch delete mode 100644 jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch delete mode 100644 jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch delete mode 100644 jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch delete mode 100644 jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch delete mode 100644 jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch delete mode 100644 jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch delete mode 100644 jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch delete mode 100644 jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch delete mode 100644 jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch delete mode 100644 jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch delete mode 100644 jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch delete mode 100644 jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch delete mode 100644 jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch delete mode 100644 jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch delete mode 100644 jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch delete mode 100644 jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch delete mode 100644 jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch delete mode 100644 jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch delete mode 100644 jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch delete mode 100644 jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch delete mode 100644 jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch delete mode 100644 jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch delete mode 100644 jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch delete mode 100644 jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch delete mode 100644 jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch delete mode 100644 jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch delete mode 100644 jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch delete mode 100644 jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch delete mode 100644 jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 481aae53ae54..36f12ace3a35 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -97,12 +97,6 @@ case "$bundle_type" in do_reset_changes=1 do_maketest=1 ;; - "dcevm") - HEAD_REVISION=$(git rev-parse HEAD) - git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=0 - do_reset_changes=0 - ;; "nomod" | "") bundle_type="" ;; @@ -127,7 +121,7 @@ JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed @@ -142,7 +136,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 16d960985192..aeff541dff30 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -120,12 +120,6 @@ case "$bundle_type" in do_reset_changes=1 do_maketest=1 ;; - "dcevm") - HEAD_REVISION=$(git rev-parse HEAD) - git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=0 - do_reset_changes=0 - ;; "nomod" | "") bundle_type="" ;; @@ -149,7 +143,7 @@ JSDK=$IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed @@ -163,7 +157,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat "$JSDK"/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? diff --git a/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch b/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch deleted file mode 100644 index 71a984a38f01..000000000000 --- a/jb/project/tools/patches/dcevm/0001-Apply-basic-dcevm11-patch.patch +++ /dev/null @@ -1,8853 +0,0 @@ -From 1411794eeca7b619a2761d277586a855106a3c58 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Wed, 14 Nov 2018 21:09:39 +0100 -Subject: [PATCH 01/34] Apply basic dcevm11 patch - ---- - src/hotspot/share/ci/ciObjectFactory.cpp | 25 + - src/hotspot/share/ci/ciObjectFactory.hpp | 3 + - .../share/classfile/classFileParser.cpp | 18 +- - .../share/classfile/classFileParser.hpp | 7 + - src/hotspot/share/classfile/classLoader.cpp | 1 + - .../share/classfile/classLoaderDataGraph.cpp | 12 + - .../share/classfile/classLoaderDataGraph.hpp | 5 + - .../share/classfile/classLoaderExt.cpp | 1 + - src/hotspot/share/classfile/dictionary.cpp | 44 +- - src/hotspot/share/classfile/dictionary.hpp | 10 + - src/hotspot/share/classfile/javaClasses.cpp | 63 + - src/hotspot/share/classfile/javaClasses.hpp | 53 + - .../share/classfile/javaClasses.inline.hpp | 8 + - src/hotspot/share/classfile/klassFactory.cpp | 3 + - src/hotspot/share/classfile/klassFactory.hpp | 1 + - .../share/classfile/loaderConstraints.cpp | 15 +- - .../share/classfile/loaderConstraints.hpp | 3 + - .../share/classfile/systemDictionary.cpp | 47 +- - .../share/classfile/systemDictionary.hpp | 9 +- - .../classfile/systemDictionaryShared.cpp | 2 +- - src/hotspot/share/classfile/verifier.cpp | 2 +- - src/hotspot/share/classfile/verifier.hpp | 1 + - src/hotspot/share/classfile/vmSymbols.hpp | 8 + - .../share/gc/cms/compactibleFreeListSpace.cpp | 3148 +++++++++++++++++ - .../share/gc/cms/compactibleFreeListSpace.hpp | 759 ++++ - src/hotspot/share/gc/serial/genMarkSweep.cpp | 4 + - src/hotspot/share/gc/serial/markSweep.cpp | 99 + - src/hotspot/share/gc/serial/markSweep.hpp | 7 + - src/hotspot/share/gc/shared/gcConfig.cpp | 5 +- - src/hotspot/share/gc/shared/space.cpp | 200 +- - src/hotspot/share/gc/shared/space.hpp | 18 +- - src/hotspot/share/gc/shared/space.inline.hpp | 49 +- - .../share/interpreter/linkResolver.cpp | 7 +- - .../jfrEventClassTransformer.cpp | 1 + - src/hotspot/share/memory/universe.cpp | 39 + - src/hotspot/share/memory/universe.hpp | 12 + - src/hotspot/share/oops/cpCache.cpp | 32 +- - src/hotspot/share/oops/cpCache.hpp | 16 +- - src/hotspot/share/oops/instanceKlass.cpp | 55 +- - src/hotspot/share/oops/instanceKlass.hpp | 7 + - src/hotspot/share/oops/klass.cpp | 29 +- - src/hotspot/share/oops/klass.hpp | 47 + - src/hotspot/share/oops/method.cpp | 6 + - src/hotspot/share/oops/method.hpp | 20 + - src/hotspot/share/prims/jni.cpp | 1 + - src/hotspot/share/prims/jvm.cpp | 1 + - .../prims/jvmtiEnhancedRedefineClasses.cpp | 2255 ++++++++++++ - .../prims/jvmtiEnhancedRedefineClasses.hpp | 202 ++ - src/hotspot/share/prims/jvmtiEnv.cpp | 44 +- - src/hotspot/share/prims/jvmtiExport.cpp | 2 +- - src/hotspot/share/prims/jvmtiExport.hpp | 1 + - .../share/prims/jvmtiGetLoadedClasses.cpp | 19 +- - src/hotspot/share/prims/jvmtiImpl.cpp | 5 + - src/hotspot/share/runtime/arguments.cpp | 32 + - src/hotspot/share/runtime/arguments.hpp | 1 + - src/hotspot/share/runtime/globals.hpp | 5 + - .../share/runtime/interfaceSupport.inline.hpp | 4 +- - src/hotspot/share/runtime/javaCalls.cpp | 3 +- - src/hotspot/share/runtime/mutexLocker.cpp | 4 +- - src/hotspot/share/runtime/mutexLocker.hpp | 2 + - src/hotspot/share/runtime/reflection.cpp | 6 + - 61 files changed, 7423 insertions(+), 65 deletions(-) - create mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp - create mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp - create mode 100644 src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp - create mode 100644 src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp - -diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp -index f74f5e627a0..d713570fccf 100644 ---- a/src/hotspot/share/ci/ciObjectFactory.cpp -+++ b/src/hotspot/share/ci/ciObjectFactory.cpp -@@ -722,3 +722,28 @@ void ciObjectFactory::print() { - _unloaded_instances->length(), - _unloaded_klasses->length()); - } -+ -+ -+int ciObjectFactory::compare_cimetadata(ciMetadata** a, ciMetadata** b) { -+ Metadata* am = (*a)->constant_encoding(); -+ Metadata* bm = (*b)->constant_encoding(); -+ return ((am > bm) ? 1 : ((am == bm) ? 0 : -1)); -+} -+ -+// FIXME: review... Resoring the ciObject arrays after class redefinition -+void ciObjectFactory::resort_shared_ci_metadata() { -+ if (_shared_ci_metadata == NULL) return; -+ _shared_ci_metadata->sort(ciObjectFactory::compare_cimetadata); -+ -+#ifdef ASSERT -+ if (CIObjectFactoryVerify) { -+ Metadata* last = NULL; -+ for (int j = 0; j< _shared_ci_metadata->length(); j++) { -+ Metadata* o = _shared_ci_metadata->at(j)->constant_encoding(); -+ assert(last < o, "out of order"); -+ last = o; -+ } -+ } -+#endif // ASSERT -+} -+ -diff --git a/src/hotspot/share/ci/ciObjectFactory.hpp b/src/hotspot/share/ci/ciObjectFactory.hpp -index f78ae05a905..875462c3168 100644 ---- a/src/hotspot/share/ci/ciObjectFactory.hpp -+++ b/src/hotspot/share/ci/ciObjectFactory.hpp -@@ -88,6 +88,7 @@ private: - - ciInstance* get_unloaded_instance(ciInstanceKlass* klass); - -+ static int compare_cimetadata(ciMetadata** a, ciMetadata** b); - public: - static bool is_initialized() { return _initialized; } - -@@ -144,6 +145,8 @@ public: - - void print_contents(); - void print(); -+ -+ static void resort_shared_ci_metadata(); - }; - - #endif // SHARE_CI_CIOBJECTFACTORY_HPP -diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp -index 5e81e786dc5..0192e9e006f 100644 ---- a/src/hotspot/share/classfile/classFileParser.cpp -+++ b/src/hotspot/share/classfile/classFileParser.cpp -@@ -964,6 +964,8 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, - CHECK); - } - -+ interf = (Klass *) maybe_newest(interf); -+ - if (!interf->is_interface()) { - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), - err_msg("class %s can not implement %s, because it is not an interface (%s)", -@@ -4012,7 +4014,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, - // However, make sure it is not an array type. - bool is_array = false; - if (cp->tag_at(super_class_index).is_klass()) { -- super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index)); -+ super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index))); - if (need_verify) - is_array = super_klass->is_array_klass(); - } else if (need_verify) { -@@ -4615,7 +4617,10 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { - if (!_has_empty_finalizer) { - if (_has_finalizer || - (super != NULL && super->has_finalizer())) { -- ik->set_has_finalizer(); -+ // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active -+ if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) { -+ ik->set_has_finalizer(); -+ } - } - } - -@@ -6062,6 +6067,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, - ClassLoaderData* loader_data, - const ClassLoadInfo* cl_info, - Publicity pub_level, -+ const bool pick_newest, - TRAPS) : - _stream(stream), - _class_name(NULL), -@@ -6125,7 +6131,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, - _has_finalizer(false), - _has_empty_finalizer(false), - _has_vanilla_constructor(false), -- _max_bootstrap_specifier_index(-1) { -+ _max_bootstrap_specifier_index(-1), -+ _pick_newest(pick_newest) { - - _class_name = name != NULL ? name : vmSymbols::unknown_class_name(); - _class_name->increment_refcount(); -@@ -6604,14 +6611,15 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st - CHECK); - } - Handle loader(THREAD, _loader_data->class_loader()); -- _super_klass = (const InstanceKlass*) -+ const Klass* super_klass = - SystemDictionary::resolve_super_or_fail(_class_name, - super_class_name, - loader, - _protection_domain, - true, - CHECK); -- } -+ _super_klass = (const InstanceKlass*) maybe_newest(super_klass); -+ } - - if (_super_klass != NULL) { - if (_super_klass->has_nonstatic_concrete_methods()) { -diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp -index bf5fccf340c..6660616ccad 100644 ---- a/src/hotspot/share/classfile/classFileParser.hpp -+++ b/src/hotspot/share/classfile/classFileParser.hpp -@@ -150,6 +150,9 @@ class ClassFileParser { - const intArray* _method_ordering; - GrowableArray* _all_mirandas; - -+ // Enhanced class redefinition -+ const bool _pick_newest; -+ - enum { fixed_buffer_size = 128 }; - u_char _linenumbertable_buffer[fixed_buffer_size]; - -@@ -541,6 +544,8 @@ class ClassFileParser { - TRAPS); - - void update_class_name(Symbol* new_name); -+ // Enhanced class redefinition -+ inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; } - - public: - ClassFileParser(ClassFileStream* stream, -@@ -548,6 +553,7 @@ class ClassFileParser { - ClassLoaderData* loader_data, - const ClassLoadInfo* cl_info, - Publicity pub_level, -+ const bool pick_newest, - TRAPS); - - ~ClassFileParser(); -@@ -576,6 +582,7 @@ class ClassFileParser { - ClassLoaderData* loader_data() const { return _loader_data; } - const Symbol* class_name() const { return _class_name; } - const InstanceKlass* super_klass() const { return _super_klass; } -+ Array* local_interfaces() const { return _local_interfaces; } - - ReferenceType reference_type() const { return _rt; } - AccessFlags access_flags() const { return _access_flags; } -diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp -index a53ccea0933..93ef3ea254d 100644 ---- a/src/hotspot/share/classfile/classLoader.cpp -+++ b/src/hotspot/share/classfile/classLoader.cpp -@@ -1275,6 +1275,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR - name, - loader_data, - cl_info, -+ false, // pick_newest - THREAD); - if (HAS_PENDING_EXCEPTION) { - if (DumpSharedSpaces) { -diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp -index 9b104d9ba4d..db0fbcc45dc 100644 ---- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp -+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp -@@ -439,6 +439,18 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), - } - } - -+void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) { -+ FOR_ALL_DICTIONARY(cld) { -+ cld->dictionary()->classes_do(klass_closure); -+ } -+} -+ -+void ClassLoaderDataGraph::rollback_redefinition() { -+ FOR_ALL_DICTIONARY(cld) { -+ cld->dictionary()->rollback_redefinition(); -+ } -+} -+ - void ClassLoaderDataGraph::verify_dictionary() { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->verify(); -diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp -index 4251afab3dc..f380aa3fa34 100644 ---- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp -+++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp -@@ -102,6 +102,11 @@ class ClassLoaderDataGraph : public AllStatic { - // Added for initialize_itable_for_klass to handle exceptions. - static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS); - -+ static void dictionary_classes_do(KlassClosure* klass_closure); -+ -+ // Enhanced class redefinition -+ static void rollback_redefinition(); -+ - // VM_CounterDecay iteration support - static InstanceKlass* try_get_next_class(); - static void adjust_saved_class(ClassLoaderData* cld); -diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp -index 701c155da19..9bf4f38cf21 100644 ---- a/src/hotspot/share/classfile/classLoaderExt.cpp -+++ b/src/hotspot/share/classfile/classLoaderExt.cpp -@@ -290,6 +290,7 @@ InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) - name, - loader_data, - cl_info, -+ false, - THREAD); - - if (HAS_PENDING_EXCEPTION) { -diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp -index 8b10f5abdb1..45c979a1738 100644 ---- a/src/hotspot/share/classfile/dictionary.cpp -+++ b/src/hotspot/share/classfile/dictionary.cpp -@@ -216,6 +216,19 @@ void Dictionary::classes_do(void f(InstanceKlass*)) { - } - } - -+void Dictionary::classes_do(KlassClosure* closure) { -+ for (int index = 0; index < table_size(); index++) { -+ for (DictionaryEntry* probe = bucket(index); -+ probe != NULL; -+ probe = probe->next()) { -+ InstanceKlass* k = probe->instance_klass(); -+ if (loader_data() == k->class_loader_data()) { -+ closure->do_klass(k); -+ } -+ } -+ } -+} -+ - // Added for initialize_itable_for_klass to handle exceptions - // Just the classes from defining class loaders - void Dictionary::classes_do(void f(InstanceKlass*, TRAPS), TRAPS) { -@@ -297,6 +310,33 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, - return NULL; - } - -+bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) { -+ // There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class. -+ bool found = false; -+ for (int index = 0; index < table_size(); index++) { -+ for (DictionaryEntry* entry = bucket(index); entry != NULL; entry = entry->next()) { -+ if (entry->instance_klass() == old_klass) { -+ entry->set_literal(k); -+ found = true; -+ } -+ } -+ } -+ return found; -+} -+ -+void Dictionary::rollback_redefinition() { -+ for (int index = 0; index < table_size(); index++) { -+ for (DictionaryEntry* entry = bucket(index); -+ entry != NULL; -+ entry = entry->next()) { -+ if (entry->instance_klass()->is_redefining()) { -+ entry->set_literal((InstanceKlass*) entry->instance_klass()->old_version()); -+ } -+ } -+ } -+} -+ -+ - - InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name, - Handle protection_domain) { -@@ -305,7 +345,7 @@ InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name, - int index = hash_to_index(hash); - DictionaryEntry* entry = get_entry(index, hash, name); - if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { -- return entry->instance_klass(); -+ return old_if_redefined(entry->instance_klass()); - } else { - return NULL; - } -@@ -317,7 +357,7 @@ InstanceKlass* Dictionary::find_class(int index, unsigned int hash, - assert (index == index_for(name), "incorrect index?"); - - DictionaryEntry* entry = get_entry(index, hash, name); -- return (entry != NULL) ? entry->instance_klass() : NULL; -+ return old_if_redefined((entry != NULL) ? entry->instance_klass() : NULL); - } - - -diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp -index 99b9799753f..b4f5cd5c4df 100644 ---- a/src/hotspot/share/classfile/dictionary.hpp -+++ b/src/hotspot/share/classfile/dictionary.hpp -@@ -65,6 +65,7 @@ public: - InstanceKlass* find_class(int index, unsigned int hash, Symbol* name); - - void classes_do(void f(InstanceKlass*)); -+ void classes_do(KlassClosure* closure); - void classes_do(void f(InstanceKlass*, TRAPS), TRAPS); - void all_entries_do(KlassClosure* closure); - void classes_do(MetaspaceClosure* it); -@@ -104,6 +105,15 @@ public: - } - - void free_entry(DictionaryEntry* entry); -+ -+ // Enhanced class redefinition -+ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); -+ -+ void rollback_redefinition(); -+ -+ static InstanceKlass* old_if_redefined(InstanceKlass* k) { -+ return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; -+ } - }; - - // An entry in the class loader data dictionaries, this describes a class as -diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp -index ca1f1f0d71d..9b086a241f7 100644 ---- a/src/hotspot/share/classfile/javaClasses.cpp -+++ b/src/hotspot/share/classfile/javaClasses.cpp -@@ -2540,6 +2540,8 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHand - skip_throwableInit_check = true; - } - } -+ // (DCEVM): Line numbers from newest version must be used for EMCP-swapped methods -+ method = method->newest_version(); - if (method->is_hidden()) { - if (skip_hidden) { - if (total_count == 0) { -@@ -3747,6 +3749,62 @@ void java_lang_invoke_DirectMethodHandle::serialize_offsets(SerializeClosure* f) - } - #endif - -+// Support for java_lang_invoke_DirectMethodHandle$StaticAccessor -+ -+int java_lang_invoke_DirectMethodHandle_StaticAccessor::_static_offset_offset; -+ -+long java_lang_invoke_DirectMethodHandle_StaticAccessor::static_offset(oop dmh) { -+ assert(_static_offset_offset != 0, ""); -+ return dmh->long_field(_static_offset_offset); -+} -+ -+void java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(oop dmh, long static_offset) { -+ assert(_static_offset_offset != 0, ""); -+ dmh->long_field_put(_static_offset_offset, static_offset); -+} -+ -+#define DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(macro) \ -+ macro(_static_offset_offset, k, vmSymbols::static_offset_name(), long_signature, false) -+ -+void java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets() { -+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_StaticAccessor_klass(); -+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET); -+} -+ -+#if INCLUDE_CDS -+void java_lang_invoke_DirectMethodHandle_StaticAccessor::serialize_offsets(SerializeClosure* f) { -+ DIRECTMETHODHANDLE_STATIC_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET); -+} -+#endif -+ -+// Support for java_lang_invoke_DirectMethodHandle$Accessor -+ -+int java_lang_invoke_DirectMethodHandle_Accessor::_field_offset_offset; -+ -+int java_lang_invoke_DirectMethodHandle_Accessor::field_offset(oop dmh) { -+ assert(_field_offset_offset != 0, ""); -+ return dmh->int_field(_field_offset_offset); -+} -+ -+void java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(oop dmh, int field_offset) { -+ assert(_field_offset_offset != 0, ""); -+ dmh->int_field_put(_field_offset_offset, field_offset); -+} -+ -+#define DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(macro) \ -+ macro(_field_offset_offset, k, vmSymbols::field_offset_name(), int_signature, false) -+ -+void java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets() { -+ InstanceKlass* k = SystemDictionary::DirectMethodHandle_Accessor_klass(); -+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_COMPUTE_OFFSET); -+} -+ -+#if INCLUDE_CDS -+void java_lang_invoke_DirectMethodHandle_Accessor::serialize_offsets(SerializeClosure* f) { -+ DIRECTMETHODHANDLE_ACCESSOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET); -+} -+#endif -+ - // Support for java_lang_invoke_MethodHandle - - int java_lang_invoke_MethodHandle::_type_offset; -@@ -3938,6 +3996,11 @@ void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop - resolved_method->obj_field_put(_vmholder_offset, holder); - } - -+void java_lang_invoke_ResolvedMethodName::set_vmholder_offset(oop resolved_method, Method* m) { -+ assert(is_instance(resolved_method), "wrong type"); -+ resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror()); -+} -+ - oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) { - const Method* method = m(); - -diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp -index e33391c63e0..a68c5139151 100644 ---- a/src/hotspot/share/classfile/javaClasses.hpp -+++ b/src/hotspot/share/classfile/javaClasses.hpp -@@ -56,6 +56,8 @@ class RecordComponent; - f(java_lang_invoke_MethodType) \ - f(java_lang_invoke_CallSite) \ - f(java_lang_invoke_ConstantCallSite) \ -+ f(java_lang_invoke_DirectMethodHandle_StaticAccessor) \ -+ f(java_lang_invoke_DirectMethodHandle_Accessor) \ - f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \ - f(java_security_AccessControlContext) \ - f(java_lang_reflect_AccessibleObject) \ -@@ -256,6 +258,7 @@ class java_lang_Class : AllStatic { - static void set_component_mirror(oop java_class, oop comp_mirror); - static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, - Handle classData, TRAPS); -+ static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); - static void set_mirror_module_field(Klass* K, Handle mirror, Handle module, TRAPS); - public: - static void allocate_fixup_lists(); -@@ -1002,6 +1005,55 @@ class java_lang_invoke_DirectMethodHandle: AllStatic { - static int member_offset() { CHECK_INIT(_member_offset); } - }; - -+// Interface to java.lang.invoke.DirectMethodHandle$StaticAccessor objects -+ -+class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic { -+ friend class JavaClasses; -+ -+ private: -+ static int _static_offset_offset; // offset to static field -+ -+ static void compute_offsets(); -+ -+ public: -+ // Accessors -+ static long static_offset(oop dmh); -+ static void set_static_offset(oop dmh, long value); -+ -+ // Testers -+ static bool is_subclass(Klass* klass) { -+ return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_StaticAccessor_klass()); -+ } -+ static bool is_instance(oop obj); -+ -+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; -+}; -+ -+// Interface to java.lang.invoke.DirectMethodHandle$Accessor objects -+ -+class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic { -+ friend class JavaClasses; -+ -+ private: -+ static int _field_offset_offset; // offset to field -+ -+ static void compute_offsets(); -+ -+ public: -+ // Accessors -+ static int field_offset(oop dmh); -+ static void set_field_offset(oop dmh, int value); -+ -+ // Testers -+ static bool is_subclass(Klass* klass) { -+ return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_Accessor_klass()); -+ } -+ static bool is_instance(oop obj); -+ -+ static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; -+}; -+ -+ - // Interface to java.lang.invoke.LambdaForm objects - // (These are a private interface for managing adapter code generation.) - -@@ -1053,6 +1105,7 @@ class java_lang_invoke_ResolvedMethodName : AllStatic { - - static Method* vmtarget(oop resolved_method); - static void set_vmtarget(oop resolved_method, Method* method); -+ static void set_vmholder_offset(oop resolved_method, Method* method); - - static void set_vmholder(oop resolved_method, oop holder); - -diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp -index a654516a377..2c6ec3c5c23 100644 ---- a/src/hotspot/share/classfile/javaClasses.inline.hpp -+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp -@@ -239,6 +239,14 @@ inline bool java_lang_invoke_DirectMethodHandle::is_instance(oop obj) { - return obj != NULL && is_subclass(obj->klass()); - } - -+inline bool java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(oop obj) { -+ return obj != NULL && is_subclass(obj->klass()); -+} -+ -+inline bool java_lang_invoke_DirectMethodHandle_Accessor::is_instance(oop obj) { -+ return obj != NULL && is_subclass(obj->klass()); -+} -+ - inline bool java_lang_Module::is_instance(oop obj) { - return obj != NULL && obj->klass() == SystemDictionary::Module_klass(); - } -diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp -index 8efe2b0ca0c..65e74e7c851 100644 ---- a/src/hotspot/share/classfile/klassFactory.cpp -+++ b/src/hotspot/share/classfile/klassFactory.cpp -@@ -85,6 +85,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook( - loader_data, - &cl_info, - ClassFileParser::BROADCAST, // publicity level -+ false, - CHECK_NULL); - const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); - InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook -@@ -168,6 +169,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, - Symbol* name, - ClassLoaderData* loader_data, - const ClassLoadInfo& cl_info, -+ const bool pick_newest, - TRAPS) { - assert(stream != NULL, "invariant"); - assert(loader_data != NULL, "invariant"); -@@ -201,6 +203,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, - loader_data, - &cl_info, - ClassFileParser::BROADCAST, // publicity level -+ pick_newest, - CHECK_NULL); - - const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); -diff --git a/src/hotspot/share/classfile/klassFactory.hpp b/src/hotspot/share/classfile/klassFactory.hpp -index 97d49a52294..790b1435dce 100644 ---- a/src/hotspot/share/classfile/klassFactory.hpp -+++ b/src/hotspot/share/classfile/klassFactory.hpp -@@ -73,6 +73,7 @@ class KlassFactory : AllStatic { - Symbol* name, - ClassLoaderData* loader_data, - const ClassLoadInfo& cl_info, -+ const bool pick_newest, - TRAPS); - public: - static InstanceKlass* check_shared_class_file_load_hook( -diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp -index e258f1fd1aa..fd1bd46b8bd 100644 ---- a/src/hotspot/share/classfile/loaderConstraints.cpp -+++ b/src/hotspot/share/classfile/loaderConstraints.cpp -@@ -91,6 +91,19 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( - return pp; - } - -+void LoaderConstraintTable::update_after_redefinition() { -+ for (int index = 0; index < table_size(); index++) { -+ LoaderConstraintEntry** p = bucket_addr(index); -+ while(*p) { -+ LoaderConstraintEntry* probe = *p; -+ if (probe->klass() != NULL) { -+ // We swap the class with the newest version with an assumption that the hash will be the same -+ probe->set_klass((InstanceKlass*) probe->klass()->newest_version()); -+ } -+ p = probe->next_addr(); -+ } -+ } -+} - - void LoaderConstraintTable::purge_loader_constraints() { - assert_locked_or_safepoint(SystemDictionary_lock); -@@ -446,7 +459,7 @@ void LoaderConstraintTable::verify(PlaceholderTable* placeholders) { - if (k != NULL) { - // We found the class in the dictionary, so we should - // make sure that the Klass* matches what we already have. -- guarantee(k == probe->klass(), "klass should be in dictionary"); -+ guarantee(k == probe->klass()->newest_version(), "klass should be in dictionary"); - } else { - // If we don't find the class in the dictionary, it - // has to be in the placeholders table. -diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp -index 0a6e4da2a5b..d0fa9df73e2 100644 ---- a/src/hotspot/share/classfile/loaderConstraints.hpp -+++ b/src/hotspot/share/classfile/loaderConstraints.hpp -@@ -55,6 +55,9 @@ public: - return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); - } - -+ // (DCEVM) update all klasses with newest version -+ void update_after_redefinition(); -+ - // Check class loader constraints - bool add_entry(Symbol* name, InstanceKlass* klass1, Handle loader1, - InstanceKlass* klass2, Handle loader2); -diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp -index 3a460f95b59..e6b25e90f18 100644 ---- a/src/hotspot/share/classfile/systemDictionary.cpp -+++ b/src/hotspot/share/classfile/systemDictionary.cpp -@@ -265,6 +265,7 @@ Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader - // can return a null klass - klass = handle_resolution_exception(class_name, throw_error, klass, THREAD); - } -+ assert(klass == NULL || klass->new_version() == NULL || klass->newest_version()->is_redefining(), "must be"); - return klass; - } - -@@ -966,6 +967,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, - ClassLoaderData* loader_data = k->class_loader_data(); - MutexLocker mu(THREAD, SystemDictionary_lock); - InstanceKlass* kk = find_class(name, loader_data); -+ // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) - assert(kk == k, "should be present in dictionary"); - } - #endif -@@ -1091,6 +1093,7 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, - class_name, - loader_data, - cl_info, -+ false, // pick_newest - CHECK_NULL); - - if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) { -@@ -1145,10 +1148,13 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, -+ InstanceKlass* old_klass, - TRAPS) { - - HandleMark hm(THREAD); - -+ bool is_redefining = (old_klass != NULL); -+ - // Classloaders that support parallelism, e.g. bootstrap classloader, - // do not acquire lock here - bool DoObjectLock = true; -@@ -1172,6 +1178,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - InstanceKlass* k = NULL; - - #if INCLUDE_CDS -+ // FIXME: what to do during redefinition? - if (!DumpSharedSpaces) { - k = SystemDictionaryShared::lookup_from_stream(class_name, - class_loader, -@@ -1186,7 +1193,12 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - return NULL; - } - ClassLoadInfo cl_info(protection_domain); -- k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL); -+ k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, is_redefining, CHECK_NULL); -+ } -+ -+ if (is_redefining && k != NULL) { -+ k->set_redefining(true); -+ k->set_old_version(old_klass); - } - - assert(k != NULL, "no klass created"); -@@ -1196,7 +1208,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - // Add class just loaded - // If a class loader supports parallel classloading handle parallel define requests - // find_or_define_instance_class may return a different InstanceKlass -- if (is_parallelCapable(class_loader)) { -+ if (is_parallelCapable(class_loader) && !is_redefining) { - InstanceKlass* defined_k = find_or_define_instance_class(h_name, class_loader, k, THREAD); - if (!HAS_PENDING_EXCEPTION && defined_k != k) { - // If a parallel capable class loader already defined this class, register 'k' for cleanup. -@@ -1205,7 +1217,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - k = defined_k; - } - } else { -- define_instance_class(k, THREAD); -+ define_instance_class(k, old_klass, THREAD); - } - - // If defining the class throws an exception register 'k' for cleanup. -@@ -1220,7 +1232,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - MutexLocker mu(THREAD, SystemDictionary_lock); - - Klass* check = find_class(h_name, k->class_loader_data()); -- assert(check == k, "should be present in the dictionary"); -+ assert((check == k && !k->is_redefining()) || (k->is_redefining() && check == k->old_version()), "should be present in the dictionary"); - } ); - - return k; -@@ -1701,11 +1713,12 @@ static void post_class_define_event(InstanceKlass* k, const ClassLoaderData* def - } - } - --void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { -+void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* old_klass, TRAPS) { - - HandleMark hm(THREAD); - ClassLoaderData* loader_data = k->class_loader_data(); - Handle class_loader_h(THREAD, loader_data->class_loader()); -+ bool is_redefining = (old_klass != NULL); - - // for bootstrap and other parallel classloaders don't acquire lock, - // use placeholder token -@@ -1730,7 +1743,11 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { - Symbol* name_h = k->name(); - Dictionary* dictionary = loader_data->dictionary(); - unsigned int d_hash = dictionary->compute_hash(name_h); -- check_constraints(d_hash, k, class_loader_h, true, CHECK); -+ if (is_redefining) { -+ bool ok = dictionary->update_klass(d_hash, name_h, loader_data, k, old_klass); -+ assert (ok, "must have found old class and updated!"); -+ } -+ check_constraints(d_hash, k, class_loader_h, !is_redefining, CHECK); - - // Register class just loaded with class loader (placed in ArrayList) - // Note we do this before updating the dictionary, as this can -@@ -1764,7 +1781,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) { - k->eager_initialize(THREAD); - - // notify jvmti -- if (JvmtiExport::should_post_class_load()) { -+ if (!is_redefining && JvmtiExport::should_post_class_load()) { - assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_load((JavaThread *) THREAD, k); - -@@ -1842,7 +1859,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam - } - } - -- define_instance_class(k, THREAD); -+ define_instance_class(k, NULL, THREAD); - - Handle linkage_exception = Handle(); // null handle - -@@ -1972,6 +1989,18 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { - } - } - -+// Enhanced class redefinition -+void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { -+ assert(k != NULL, "just checking"); -+ -+ // remove receiver from sibling list -+ k->remove_from_sibling_list(); -+} -+ -+void SystemDictionary::update_constraints_after_redefinition() { -+ constraints()->update_after_redefinition(); -+} -+ - // ---------------------------------------------------------------------------- - // GC support - -@@ -2251,7 +2280,7 @@ void SystemDictionary::check_constraints(unsigned int d_hash, - // also hold array classes. - - assert(check->is_instance_klass(), "noninstance in systemdictionary"); -- if ((defining == true) || (k != check)) { -+ if ((defining == true) || ((k != check) && k->old_version() != check)) { - throwException = true; - ss.print("loader %s", loader_data->loader_name_and_id()); - ss.print(" attempted duplicate %s definition for %s. (%s)", -diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp -index 7fd274b8d77..4547449dbec 100644 ---- a/src/hotspot/share/classfile/systemDictionary.hpp -+++ b/src/hotspot/share/classfile/systemDictionary.hpp -@@ -209,6 +209,8 @@ class EventClassLoad; - \ - /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ - do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \ -+ do_klass(DirectMethodHandle_StaticAccessor_klass, java_lang_invoke_DirectMethodHandle_StaticAccessor ) \ -+ do_klass(DirectMethodHandle_Accessor_klass, java_lang_invoke_DirectMethodHandle_Accessor ) \ - do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle ) \ - do_klass(VarHandle_klass, java_lang_invoke_VarHandle ) \ - do_klass(MemberName_klass, java_lang_invoke_MemberName ) \ -@@ -334,6 +336,7 @@ public: - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, -+ InstanceKlass* old_klass, - TRAPS); - - // Lookup an already loaded class. If not found NULL is returned. -@@ -451,6 +454,10 @@ public: - static bool is_well_known_klass(Symbol* class_name); - #endif - -+ // Enhanced class redefinition -+ static void remove_from_hierarchy(InstanceKlass* k); -+ static void update_constraints_after_redefinition(); -+ - protected: - // Returns the class loader data to be used when looking up/updating the - // system dictionary. -@@ -622,7 +629,7 @@ protected: - // after waiting, but before reentering SystemDictionary_lock - // to preserve lock order semantics. - static void double_lock_wait(Handle lockObject, TRAPS); -- static void define_instance_class(InstanceKlass* k, TRAPS); -+ static void define_instance_class(InstanceKlass* k, InstanceKlass* old_klass, TRAPS); - static InstanceKlass* find_or_define_instance_class(Symbol* class_name, - Handle class_loader, - InstanceKlass* k, TRAPS); -diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp -index 96c53e059a9..91dd2f2701a 100644 ---- a/src/hotspot/share/classfile/systemDictionaryShared.cpp -+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp -@@ -1079,7 +1079,7 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class( - - k = load_shared_class_for_builtin_loader(name, class_loader, THREAD); - if (k != NULL) { -- define_instance_class(k, CHECK_NULL); -+ define_instance_class(k, NULL, CHECK_NULL); - } - } - } -diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp -index 9711662698b..4f9c750d549 100644 ---- a/src/hotspot/share/classfile/verifier.cpp -+++ b/src/hotspot/share/classfile/verifier.cpp -@@ -259,7 +259,7 @@ bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_ve - Symbol* name = klass->name(); - Klass* refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); - -- bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); -+ bool is_reflect = refl_magic_klass != NULL && (klass->is_subtype_of(refl_magic_klass) || klass->is_subtype_of(refl_magic_klass->newest_version())); - - return (should_verify_for(klass->class_loader(), should_verify_class) && - // return if the class is a bootstrapping class -diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp -index e629b4f5623..eedb57e5c9d 100644 ---- a/src/hotspot/share/classfile/verifier.hpp -+++ b/src/hotspot/share/classfile/verifier.hpp -@@ -374,6 +374,7 @@ class ClassVerifier : public StackObj { - - VerificationType object_type() const; - -+ InstanceKlass* _klass_to_verify; - InstanceKlass* _klass; // the class being verified - methodHandle _method; // current method being verified - VerificationType _this_type; // the verification type of the current class -diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp -index 28cb9bae2e2..99c5ac98995 100644 ---- a/src/hotspot/share/classfile/vmSymbols.hpp -+++ b/src/hotspot/share/classfile/vmSymbols.hpp -@@ -292,6 +292,8 @@ - template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ - template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \ - template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ -+ template(java_lang_invoke_DirectMethodHandle_StaticAccessor, "java/lang/invoke/DirectMethodHandle$StaticAccessor") \ -+ template(java_lang_invoke_DirectMethodHandle_Accessor, "java/lang/invoke/DirectMethodHandle$Accessor") \ - template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \ - template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \ - template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ -@@ -459,6 +461,12 @@ - template(big_endian_name, "BIG_ENDIAN") \ - template(use_unaligned_access_name, "UNALIGNED_ACCESS") \ - template(data_cache_line_flush_size_name, "DATA_CACHE_LINE_FLUSH_SIZE") \ -+ template(static_offset_name, "staticOffset") \ -+ template(static_base_name, "staticBase") \ -+ template(field_offset_name, "fieldOffset") \ -+ template(field_type_name, "fieldType") \ -+ \ -+ /* name symbols needed by intrinsics */ \ - \ - /* name symbols needed by intrinsics */ \ - VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ -diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp -new file mode 100644 -index 00000000000..a93f764f1b9 ---- /dev/null -+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp -@@ -0,0 +1,3148 @@ -+/* -+ * Copyright (c) 2001, 2018, 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/cms/cmsHeap.hpp" -+#include "gc/cms/cmsLockVerifier.hpp" -+#include "gc/cms/compactibleFreeListSpace.hpp" -+#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" -+#include "gc/cms/concurrentMarkSweepThread.hpp" -+#include "gc/shared/blockOffsetTable.inline.hpp" -+#include "gc/shared/collectedHeap.inline.hpp" -+#include "gc/shared/genOopClosures.inline.hpp" -+#include "gc/shared/space.inline.hpp" -+#include "gc/shared/spaceDecorator.hpp" -+#include "logging/log.hpp" -+#include "logging/logStream.hpp" -+#include "memory/allocation.inline.hpp" -+#include "memory/binaryTreeDictionary.inline.hpp" -+#include "memory/iterator.inline.hpp" -+#include "memory/resourceArea.hpp" -+#include "memory/universe.hpp" -+#include "oops/access.inline.hpp" -+#include "oops/compressedOops.inline.hpp" -+#include "oops/oop.inline.hpp" -+#include "runtime/globals.hpp" -+#include "runtime/handles.inline.hpp" -+#include "runtime/init.hpp" -+#include "runtime/java.hpp" -+#include "runtime/orderAccess.hpp" -+#include "runtime/vmThread.hpp" -+#include "utilities/align.hpp" -+#include "utilities/copy.hpp" -+ -+// Specialize for AdaptiveFreeList which tries to avoid -+// splitting a chunk of a size that is under populated in favor of -+// an over populated size. The general get_better_list() just returns -+// the current list. -+template <> -+TreeList >* -+TreeList >::get_better_list( -+ BinaryTreeDictionary >* dictionary) { -+ // A candidate chunk has been found. If it is already under -+ // populated, get a chunk associated with the hint for this -+ // chunk. -+ -+ TreeList >* curTL = this; -+ if (curTL->surplus() <= 0) { -+ /* Use the hint to find a size with a surplus, and reset the hint. */ -+ TreeList >* hintTL = this; -+ while (hintTL->hint() != 0) { -+ assert(hintTL->hint() > hintTL->size(), -+ "hint points in the wrong direction"); -+ hintTL = dictionary->find_list(hintTL->hint()); -+ assert(curTL != hintTL, "Infinite loop"); -+ if (hintTL == NULL || -+ hintTL == curTL /* Should not happen but protect against it */ ) { -+ // No useful hint. Set the hint to NULL and go on. -+ curTL->set_hint(0); -+ break; -+ } -+ assert(hintTL->size() > curTL->size(), "hint is inconsistent"); -+ if (hintTL->surplus() > 0) { -+ // The hint led to a list that has a surplus. Use it. -+ // Set the hint for the candidate to an overpopulated -+ // size. -+ curTL->set_hint(hintTL->size()); -+ // Change the candidate. -+ curTL = hintTL; -+ break; -+ } -+ } -+ } -+ return curTL; -+} -+ -+void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) { -+ TreeList >* nd = find_list(size); -+ if (nd) { -+ if (split) { -+ if (birth) { -+ nd->increment_split_births(); -+ nd->increment_surplus(); -+ } else { -+ nd->increment_split_deaths(); -+ nd->decrement_surplus(); -+ } -+ } else { -+ if (birth) { -+ nd->increment_coal_births(); -+ nd->increment_surplus(); -+ } else { -+ nd->increment_coal_deaths(); -+ nd->decrement_surplus(); -+ } -+ } -+ } -+ // A list for this size may not be found (nd == 0) if -+ // This is a death where the appropriate list is now -+ // empty and has been removed from the list. -+ // This is a birth associated with a LinAB. The chunk -+ // for the LinAB is not in the dictionary. -+} -+ -+bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { -+ if (FLSAlwaysCoalesceLarge) return true; -+ -+ TreeList >* list_of_size = find_list(size); -+ // None of requested size implies overpopulated. -+ return list_of_size == NULL || list_of_size->coal_desired() <= 0 || -+ list_of_size->count() > list_of_size->coal_desired(); -+} -+ -+// For each list in the tree, calculate the desired, desired -+// coalesce, count before sweep, and surplus before sweep. -+class BeginSweepClosure : public AscendTreeCensusClosure > { -+ double _percentage; -+ float _inter_sweep_current; -+ float _inter_sweep_estimate; -+ float _intra_sweep_estimate; -+ -+ public: -+ BeginSweepClosure(double p, float inter_sweep_current, -+ float inter_sweep_estimate, -+ float intra_sweep_estimate) : -+ _percentage(p), -+ _inter_sweep_current(inter_sweep_current), -+ _inter_sweep_estimate(inter_sweep_estimate), -+ _intra_sweep_estimate(intra_sweep_estimate) { } -+ -+ void do_list(AdaptiveFreeList* fl) { -+ double coalSurplusPercent = _percentage; -+ fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); -+ fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent)); -+ fl->set_before_sweep(fl->count()); -+ fl->set_bfr_surp(fl->surplus()); -+ } -+}; -+ -+void AFLBinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent, -+ float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { -+ BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, -+ inter_sweep_estimate, -+ intra_sweep_estimate); -+ bsc.do_tree(root()); -+} -+ -+// Calculate surpluses for the lists in the tree. -+class setTreeSurplusClosure : public AscendTreeCensusClosure > { -+ double percentage; -+ public: -+ setTreeSurplusClosure(double v) { percentage = v; } -+ -+ void do_list(AdaptiveFreeList* fl) { -+ double splitSurplusPercent = percentage; -+ fl->set_surplus(fl->count() - -+ (ssize_t)((double)fl->desired() * splitSurplusPercent)); -+ } -+}; -+ -+void AFLBinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) { -+ setTreeSurplusClosure sts(splitSurplusPercent); -+ sts.do_tree(root()); -+} -+ -+// Set hints for the lists in the tree. -+class setTreeHintsClosure : public DescendTreeCensusClosure > { -+ size_t hint; -+ public: -+ setTreeHintsClosure(size_t v) { hint = v; } -+ -+ void do_list(AdaptiveFreeList* fl) { -+ fl->set_hint(hint); -+ assert(fl->hint() == 0 || fl->hint() > fl->size(), -+ "Current hint is inconsistent"); -+ if (fl->surplus() > 0) { -+ hint = fl->size(); -+ } -+ } -+}; -+ -+void AFLBinaryTreeDictionary::set_tree_hints(void) { -+ setTreeHintsClosure sth(0); -+ sth.do_tree(root()); -+} -+ -+// Save count before previous sweep and splits and coalesces. -+class clearTreeCensusClosure : public AscendTreeCensusClosure > { -+ void do_list(AdaptiveFreeList* fl) { -+ fl->set_prev_sweep(fl->count()); -+ fl->set_coal_births(0); -+ fl->set_coal_deaths(0); -+ fl->set_split_births(0); -+ fl->set_split_deaths(0); -+ } -+}; -+ -+void AFLBinaryTreeDictionary::clear_tree_census(void) { -+ clearTreeCensusClosure ctc; -+ ctc.do_tree(root()); -+} -+ -+// Do reporting and post sweep clean up. -+void AFLBinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) { -+ // Does walking the tree 3 times hurt? -+ set_tree_surplus(splitSurplusPercent); -+ set_tree_hints(); -+ LogTarget(Trace, gc, freelist, stats) log; -+ if (log.is_enabled()) { -+ LogStream out(log); -+ report_statistics(&out); -+ } -+ clear_tree_census(); -+} -+ -+// Print census information - counts, births, deaths, etc. -+// for each list in the tree. Also print some summary -+// information. -+class PrintTreeCensusClosure : public AscendTreeCensusClosure > { -+ int _print_line; -+ size_t _total_free; -+ AdaptiveFreeList _total; -+ -+ public: -+ PrintTreeCensusClosure() { -+ _print_line = 0; -+ _total_free = 0; -+ } -+ AdaptiveFreeList* total() { return &_total; } -+ size_t total_free() { return _total_free; } -+ -+ void do_list(AdaptiveFreeList* fl) { -+ LogStreamHandle(Debug, gc, freelist, census) out; -+ -+ if (++_print_line >= 40) { -+ AdaptiveFreeList::print_labels_on(&out, "size"); -+ _print_line = 0; -+ } -+ fl->print_on(&out); -+ _total_free += fl->count() * fl->size() ; -+ total()->set_count( total()->count() + fl->count() ); -+ total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() ); -+ total()->set_surplus( total()->split_deaths() + fl->surplus() ); -+ total()->set_desired( total()->desired() + fl->desired() ); -+ total()->set_prev_sweep( total()->prev_sweep() + fl->prev_sweep() ); -+ total()->set_before_sweep(total()->before_sweep() + fl->before_sweep()); -+ total()->set_coal_births( total()->coal_births() + fl->coal_births() ); -+ total()->set_coal_deaths( total()->coal_deaths() + fl->coal_deaths() ); -+ total()->set_split_births(total()->split_births() + fl->split_births()); -+ total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); -+ } -+}; -+ -+void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const { -+ -+ st->print_cr("BinaryTree"); -+ AdaptiveFreeList::print_labels_on(st, "size"); -+ PrintTreeCensusClosure ptc; -+ ptc.do_tree(root()); -+ -+ AdaptiveFreeList* total = ptc.total(); -+ AdaptiveFreeList::print_labels_on(st, " "); -+ total->print_on(st, "TOTAL\t"); -+ st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f deficit: %8.5f", -+ ptc.total_free(), -+ (double)(total->split_births() + total->coal_births() -+ - total->split_deaths() - total->coal_deaths()) -+ /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0), -+ (double)(total->desired() - total->count()) -+ /(total->desired() != 0 ? (double)total->desired() : 1.0)); -+} -+ -+///////////////////////////////////////////////////////////////////////// -+//// CompactibleFreeListSpace -+///////////////////////////////////////////////////////////////////////// -+ -+// highest ranked free list lock rank -+int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3; -+ -+// Defaults are 0 so things will break badly if incorrectly initialized. -+size_t CompactibleFreeListSpace::IndexSetStart = 0; -+size_t CompactibleFreeListSpace::IndexSetStride = 0; -+size_t CompactibleFreeListSpace::_min_chunk_size_in_bytes = 0; -+ -+size_t MinChunkSize = 0; -+ -+void CompactibleFreeListSpace::set_cms_values() { -+ // Set CMS global values -+ assert(MinChunkSize == 0, "already set"); -+ -+ // MinChunkSize should be a multiple of MinObjAlignment and be large enough -+ // for chunks to contain a FreeChunk. -+ _min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes); -+ MinChunkSize = _min_chunk_size_in_bytes / BytesPerWord; -+ -+ assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); -+ IndexSetStart = MinChunkSize; -+ IndexSetStride = MinObjAlignment; -+} -+ -+// Constructor -+CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) : -+ _bt(bs, mr), -+ // free list locks are in the range of values taken by _lockRank -+ // This range currently is [_leaf+2, _leaf+3] -+ // Note: this requires that CFLspace c'tors -+ // are called serially in the order in which the locks are -+ // are acquired in the program text. This is true today. -+ _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true, -+ Monitor::_safepoint_check_sometimes), -+ _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1 -+ "CompactibleFreeListSpace._dict_par_lock", true, -+ Monitor::_safepoint_check_never), -+ _rescan_task_size(CardTable::card_size_in_words * BitsPerWord * -+ CMSRescanMultiple), -+ _marking_task_size(CardTable::card_size_in_words * BitsPerWord * -+ CMSConcMarkMultiple), -+ _collector(NULL), -+ _preconsumptionDirtyCardClosure(NULL) -+{ -+ assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, -+ "FreeChunk is larger than expected"); -+ _bt.set_space(this); -+ initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); -+ -+ _dictionary = new AFLBinaryTreeDictionary(mr); -+ -+ assert(_dictionary != NULL, "CMS dictionary initialization"); -+ // The indexed free lists are initially all empty and are lazily -+ // filled in on demand. Initialize the array elements to NULL. -+ initializeIndexedFreeListArray(); -+ -+ _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, -+ SmallForLinearAlloc); -+ -+ // CMSIndexedFreeListReplenish should be at least 1 -+ CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish); -+ _promoInfo.setSpace(this); -+ if (UseCMSBestFit) { -+ _fitStrategy = FreeBlockBestFitFirst; -+ } else { -+ _fitStrategy = FreeBlockStrategyNone; -+ } -+ check_free_list_consistency(); -+ -+ // Initialize locks for parallel case. -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 -+ "a freelist par lock", true, Mutex::_safepoint_check_sometimes); -+ DEBUG_ONLY( -+ _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); -+ ) -+ } -+ _dictionary->set_par_lock(&_parDictionaryAllocLock); -+ -+ _used_stable = 0; -+} -+ -+HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size, -+ CompactPoint* cp, HeapWord* compact_top) { -+ ShouldNotReachHere(); -+ return NULL; -+} -+ -+// Like CompactibleSpace forward() but always calls cross_threshold() to -+// update the block offset table. Removed initialize_threshold call because -+// CFLS does not use a block offset array for contiguous spaces. -+HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size, -+ CompactPoint* cp, HeapWord* compact_top) { -+ // q is alive -+ // First check if we should switch compaction space -+ assert(this == cp->space, "'this' should be current compaction space."); -+ size_t compaction_max_size = pointer_delta(end(), compact_top); -+ assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), -+ "virtual adjustObjectSize_v() method is not correct"); -+ size_t adjusted_size = adjustObjectSize(size); -+ assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, -+ "no small fragments allowed"); -+ assert(minimum_free_block_size() == MinChunkSize, -+ "for de-virtualized reference below"); -+ // Can't leave a nonzero size, residual fragment smaller than MinChunkSize -+ if (adjusted_size + MinChunkSize > compaction_max_size && -+ adjusted_size != compaction_max_size) { -+ do { -+ // switch to next compaction space -+ cp->space->set_compaction_top(compact_top); -+ cp->space = cp->space->next_compaction_space(); -+ if (cp->space == NULL) { -+ cp->gen = CMSHeap::heap()->young_gen(); -+ assert(cp->gen != NULL, "compaction must succeed"); -+ cp->space = cp->gen->first_compaction_space(); -+ assert(cp->space != NULL, "generation must have a first compaction space"); -+ } -+ compact_top = cp->space->bottom(); -+ cp->space->set_compaction_top(compact_top); -+ // The correct adjusted_size may not be the same as that for this method -+ // (i.e., cp->space may no longer be "this" so adjust the size again. -+ // Use the virtual method which is not used above to save the virtual -+ // dispatch. -+ adjusted_size = cp->space->adjust_object_size_v(size); -+ compaction_max_size = pointer_delta(cp->space->end(), compact_top); -+ assert(cp->space->minimum_free_block_size() == 0, "just checking"); -+ } while (adjusted_size > compaction_max_size); -+ } -+ -+ // store the forwarding pointer into the mark word -+ if ((HeapWord*)q != compact_top) { -+ q->forward_to(oop(compact_top)); -+ assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); -+ } else { -+ // if the object isn't moving we can just set the mark to the default -+ // mark and handle it specially later on. -+ q->init_mark_raw(); -+ assert(q->forwardee() == NULL, "should be forwarded to NULL"); -+ } -+ -+ compact_top += adjusted_size; -+ -+ // we need to update the offset table so that the beginnings of objects can be -+ // found during scavenge. Note that we are updating the offset table based on -+ // where the object will be once the compaction phase finishes. -+ -+ // Always call cross_threshold(). A contiguous space can only call it when -+ // the compaction_top exceeds the current threshold but not for an -+ // non-contiguous space. -+ cp->threshold = -+ cp->space->cross_threshold(compact_top - adjusted_size, compact_top); -+ return compact_top; -+} -+ -+// A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt -+// and use of single_block instead of alloc_block. The name here is not really -+// appropriate - maybe a more general name could be invented for both the -+// contiguous and noncontiguous spaces. -+ -+HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) { -+ _bt.single_block(start, the_end); -+ return end(); -+} -+ -+// Initialize them to NULL. -+void CompactibleFreeListSpace::initializeIndexedFreeListArray() { -+ for (size_t i = 0; i < IndexSetSize; i++) { -+ // Note that on platforms where objects are double word aligned, -+ // the odd array elements are not used. It is convenient, however, -+ // to map directly from the object size to the array element. -+ _indexedFreeList[i].reset(IndexSetSize); -+ _indexedFreeList[i].set_size(i); -+ assert(_indexedFreeList[i].count() == 0, "reset check failed"); -+ assert(_indexedFreeList[i].head() == NULL, "reset check failed"); -+ assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); -+ assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); -+ } -+} -+ -+size_t CompactibleFreeListSpace::obj_size(const HeapWord* addr) const { -+ return adjustObjectSize(oop(addr)->size()); -+} -+ -+void CompactibleFreeListSpace::resetIndexedFreeListArray() { -+ for (size_t i = 1; i < IndexSetSize; i++) { -+ assert(_indexedFreeList[i].size() == (size_t) i, -+ "Indexed free list sizes are incorrect"); -+ _indexedFreeList[i].reset(IndexSetSize); -+ assert(_indexedFreeList[i].count() == 0, "reset check failed"); -+ assert(_indexedFreeList[i].head() == NULL, "reset check failed"); -+ assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); -+ assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); -+ } -+} -+ -+void CompactibleFreeListSpace::reset(MemRegion mr) { -+ resetIndexedFreeListArray(); -+ dictionary()->reset(); -+ if (BlockOffsetArrayUseUnallocatedBlock) { -+ assert(end() == mr.end(), "We are compacting to the bottom of CMS gen"); -+ // Everything's allocated until proven otherwise. -+ _bt.set_unallocated_block(end()); -+ } -+ if (!mr.is_empty()) { -+ assert(mr.word_size() >= MinChunkSize, "Chunk size is too small"); -+ _bt.single_block(mr.start(), mr.word_size()); -+ FreeChunk* fc = (FreeChunk*) mr.start(); -+ fc->set_size(mr.word_size()); -+ if (mr.word_size() >= IndexSetSize ) { -+ returnChunkToDictionary(fc); -+ } else { -+ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -+ _indexedFreeList[mr.word_size()].return_chunk_at_head(fc); -+ } -+ coalBirth(mr.word_size()); -+ } -+ _promoInfo.reset(); -+ _smallLinearAllocBlock._ptr = NULL; -+ _smallLinearAllocBlock._word_size = 0; -+} -+ -+void CompactibleFreeListSpace::reset_after_compaction() { -+ // Reset the space to the new reality - one free chunk. -+ MemRegion mr(compaction_top(), end()); -+ reset(mr); -+ // Now refill the linear allocation block(s) if possible. -+ refillLinearAllocBlocksIfNeeded(); -+} -+ -+// Walks the entire dictionary, returning a coterminal -+// chunk, if it exists. Use with caution since it involves -+// a potentially complete walk of a potentially large tree. -+FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() { -+ -+ assert_lock_strong(&_freelistLock); -+ -+ return dictionary()->find_chunk_ends_at(end()); -+} -+ -+ -+#ifndef PRODUCT -+void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() { -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ _indexedFreeList[i].allocation_stats()->set_returned_bytes(0); -+ } -+} -+ -+size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() { -+ size_t sum = 0; -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ sum += _indexedFreeList[i].allocation_stats()->returned_bytes(); -+ } -+ return sum; -+} -+ -+size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const { -+ size_t count = 0; -+ for (size_t i = IndexSetStart; i < IndexSetSize; i++) { -+ debug_only( -+ ssize_t total_list_count = 0; -+ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -+ fc = fc->next()) { -+ total_list_count++; -+ } -+ assert(total_list_count == _indexedFreeList[i].count(), -+ "Count in list is incorrect"); -+ ) -+ count += _indexedFreeList[i].count(); -+ } -+ return count; -+} -+ -+size_t CompactibleFreeListSpace::totalCount() { -+ size_t num = totalCountInIndexedFreeLists(); -+ num += dictionary()->total_count(); -+ if (_smallLinearAllocBlock._word_size != 0) { -+ num++; -+ } -+ return num; -+} -+#endif -+ -+bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const { -+ FreeChunk* fc = (FreeChunk*) p; -+ return fc->is_free(); -+} -+ -+size_t CompactibleFreeListSpace::used() const { -+ return capacity() - free(); -+} -+ -+size_t CompactibleFreeListSpace::used_stable() const { -+ return _used_stable; -+} -+ -+void CompactibleFreeListSpace::recalculate_used_stable() { -+ _used_stable = used(); -+} -+ -+size_t CompactibleFreeListSpace::free() const { -+ // "MT-safe, but not MT-precise"(TM), if you will: i.e. -+ // if you do this while the structures are in flux you -+ // may get an approximate answer only; for instance -+ // because there is concurrent allocation either -+ // directly by mutators or for promotion during a GC. -+ // It's "MT-safe", however, in the sense that you are guaranteed -+ // not to crash and burn, for instance, because of walking -+ // pointers that could disappear as you were walking them. -+ // The approximation is because the various components -+ // that are read below are not read atomically (and -+ // further the computation of totalSizeInIndexedFreeLists() -+ // is itself a non-atomic computation. The normal use of -+ // this is during a resize operation at the end of GC -+ // and at that time you are guaranteed to get the -+ // correct actual value. However, for instance, this is -+ // also read completely asynchronously by the "perf-sampler" -+ // that supports jvmstat, and you are apt to see the values -+ // flicker in such cases. -+ assert(_dictionary != NULL, "No _dictionary?"); -+ return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) + -+ totalSizeInIndexedFreeLists() + -+ _smallLinearAllocBlock._word_size) * HeapWordSize; -+} -+ -+size_t CompactibleFreeListSpace::max_alloc_in_words() const { -+ assert(_dictionary != NULL, "No _dictionary?"); -+ assert_locked(); -+ size_t res = _dictionary->max_chunk_size(); -+ res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, -+ (size_t) SmallForLinearAlloc - 1)); -+ // XXX the following could potentially be pretty slow; -+ // should one, pessimistically for the rare cases when res -+ // calculated above is less than IndexSetSize, -+ // just return res calculated above? My reasoning was that -+ // those cases will be so rare that the extra time spent doesn't -+ // really matter.... -+ // Note: do not change the loop test i >= res + IndexSetStride -+ // to i > res below, because i is unsigned and res may be zero. -+ for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride; -+ i -= IndexSetStride) { -+ if (_indexedFreeList[i].head() != NULL) { -+ assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); -+ return i; -+ } -+ } -+ return res; -+} -+ -+void LinearAllocBlock::print_on(outputStream* st) const { -+ st->print_cr(" LinearAllocBlock: ptr = " PTR_FORMAT ", word_size = " SIZE_FORMAT -+ ", refillsize = " SIZE_FORMAT ", allocation_size_limit = " SIZE_FORMAT, -+ p2i(_ptr), _word_size, _refillSize, _allocation_size_limit); -+} -+ -+void CompactibleFreeListSpace::print_on(outputStream* st) const { -+ st->print_cr("COMPACTIBLE FREELIST SPACE"); -+ st->print_cr(" Space:"); -+ Space::print_on(st); -+ -+ st->print_cr("promoInfo:"); -+ _promoInfo.print_on(st); -+ -+ st->print_cr("_smallLinearAllocBlock"); -+ _smallLinearAllocBlock.print_on(st); -+ -+ // dump_memory_block(_smallLinearAllocBlock->_ptr, 128); -+ -+ st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy)); -+} -+ -+void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) -+const { -+ reportIndexedFreeListStatistics(st); -+ st->print_cr("Layout of Indexed Freelists"); -+ st->print_cr("---------------------------"); -+ AdaptiveFreeList::print_labels_on(st, "size"); -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ _indexedFreeList[i].print_on(st); -+ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; fc = fc->next()) { -+ st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", -+ p2i(fc), p2i((HeapWord*)fc + i), -+ fc->cantCoalesce() ? "\t CC" : ""); -+ } -+ } -+} -+ -+void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st) -+const { -+ _promoInfo.print_on(st); -+} -+ -+void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st) -+const { -+ _dictionary->report_statistics(st); -+ st->print_cr("Layout of Freelists in Tree"); -+ st->print_cr("---------------------------"); -+ _dictionary->print_free_lists(st); -+} -+ -+class BlkPrintingClosure: public BlkClosure { -+ const CMSCollector* _collector; -+ const CompactibleFreeListSpace* _sp; -+ const CMSBitMap* _live_bit_map; -+ const bool _post_remark; -+ outputStream* _st; -+public: -+ BlkPrintingClosure(const CMSCollector* collector, -+ const CompactibleFreeListSpace* sp, -+ const CMSBitMap* live_bit_map, -+ outputStream* st): -+ _collector(collector), -+ _sp(sp), -+ _live_bit_map(live_bit_map), -+ _post_remark(collector->abstract_state() > CMSCollector::FinalMarking), -+ _st(st) { } -+ size_t do_blk(HeapWord* addr); -+}; -+ -+size_t BlkPrintingClosure::do_blk(HeapWord* addr) { -+ size_t sz = _sp->block_size_no_stall(addr, _collector); -+ assert(sz != 0, "Should always be able to compute a size"); -+ if (_sp->block_is_obj(addr)) { -+ const bool dead = _post_remark && !_live_bit_map->isMarked(addr); -+ _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s", -+ p2i(addr), -+ dead ? "dead" : "live", -+ sz, -+ (!dead && CMSPrintObjectsInDump) ? ":" : "."); -+ if (CMSPrintObjectsInDump && !dead) { -+ oop(addr)->print_on(_st); -+ _st->print_cr("--------------------------------------"); -+ } -+ } else { // free block -+ _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s", -+ p2i(addr), sz, CMSPrintChunksInDump ? ":" : "."); -+ if (CMSPrintChunksInDump) { -+ ((FreeChunk*)addr)->print_on(_st); -+ _st->print_cr("--------------------------------------"); -+ } -+ } -+ return sz; -+} -+ -+void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st) { -+ st->print_cr("========================="); -+ st->print_cr("Block layout in CMS Heap:"); -+ st->print_cr("========================="); -+ BlkPrintingClosure bpcl(c, this, c->markBitMap(), st); -+ blk_iterate(&bpcl); -+ -+ st->print_cr("======================================="); -+ st->print_cr("Order & Layout of Promotion Info Blocks"); -+ st->print_cr("======================================="); -+ print_promo_info_blocks(st); -+ -+ st->print_cr("==========================="); -+ st->print_cr("Order of Indexed Free Lists"); -+ st->print_cr("========================="); -+ print_indexed_free_lists(st); -+ -+ st->print_cr("================================="); -+ st->print_cr("Order of Free Lists in Dictionary"); -+ st->print_cr("================================="); -+ print_dictionary_free_lists(st); -+} -+ -+ -+void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const { -+ assert_lock_strong(&_freelistLock); -+ Log(gc, freelist, stats) log; -+ if (!log.is_debug()) { -+ return; -+ } -+ log.debug("%s", title); -+ -+ LogStream out(log.debug()); -+ _dictionary->report_statistics(&out); -+ -+ if (log.is_trace()) { -+ LogStream trace_out(log.trace()); -+ reportIndexedFreeListStatistics(&trace_out); -+ size_t total_size = totalSizeInIndexedFreeLists() + -+ _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); -+ log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); -+ } -+} -+ -+void CompactibleFreeListSpace::reportIndexedFreeListStatistics(outputStream* st) const { -+ assert_lock_strong(&_freelistLock); -+ st->print_cr("Statistics for IndexedFreeLists:"); -+ st->print_cr("--------------------------------"); -+ size_t total_size = totalSizeInIndexedFreeLists(); -+ size_t free_blocks = numFreeBlocksInIndexedFreeLists(); -+ st->print_cr("Total Free Space: " SIZE_FORMAT, total_size); -+ st->print_cr("Max Chunk Size: " SIZE_FORMAT, maxChunkSizeInIndexedFreeLists()); -+ st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks); -+ if (free_blocks != 0) { -+ st->print_cr("Av. Block Size: " SIZE_FORMAT, total_size/free_blocks); -+ } -+} -+ -+size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { -+ size_t res = 0; -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ debug_only( -+ ssize_t recount = 0; -+ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -+ fc = fc->next()) { -+ recount += 1; -+ } -+ assert(recount == _indexedFreeList[i].count(), -+ "Incorrect count in list"); -+ ) -+ res += _indexedFreeList[i].count(); -+ } -+ return res; -+} -+ -+size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const { -+ for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { -+ if (_indexedFreeList[i].head() != NULL) { -+ assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); -+ return (size_t)i; -+ } -+ } -+ return 0; -+} -+ -+void CompactibleFreeListSpace::set_end(HeapWord* value) { -+ HeapWord* prevEnd = end(); -+ assert(prevEnd != value, "unnecessary set_end call"); -+ assert(prevEnd == NULL || !BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), -+ "New end is below unallocated block"); -+ _end = value; -+ if (prevEnd != NULL) { -+ // Resize the underlying block offset table. -+ _bt.resize(pointer_delta(value, bottom())); -+ if (value <= prevEnd) { -+ assert(!BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), -+ "New end is below unallocated block"); -+ } else { -+ // Now, take this new chunk and add it to the free blocks. -+ // Note that the BOT has not yet been updated for this block. -+ size_t newFcSize = pointer_delta(value, prevEnd); -+ // Add the block to the free lists, if possible coalescing it -+ // with the last free block, and update the BOT and census data. -+ addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); -+ } -+ } -+} -+ -+class FreeListSpaceDCTOC : public FilteringDCTOC { -+ CompactibleFreeListSpace* _cfls; -+ CMSCollector* _collector; -+ bool _parallel; -+protected: -+ // Override. -+#define walk_mem_region_with_cl_DECL(ClosureType) \ -+ virtual void walk_mem_region_with_cl(MemRegion mr, \ -+ HeapWord* bottom, HeapWord* top, \ -+ ClosureType* cl); \ -+ void walk_mem_region_with_cl_par(MemRegion mr, \ -+ HeapWord* bottom, HeapWord* top, \ -+ ClosureType* cl); \ -+ void walk_mem_region_with_cl_nopar(MemRegion mr, \ -+ HeapWord* bottom, HeapWord* top, \ -+ ClosureType* cl) -+ walk_mem_region_with_cl_DECL(OopIterateClosure); -+ walk_mem_region_with_cl_DECL(FilteringClosure); -+ -+public: -+ FreeListSpaceDCTOC(CompactibleFreeListSpace* sp, -+ CMSCollector* collector, -+ OopIterateClosure* cl, -+ CardTable::PrecisionStyle precision, -+ HeapWord* boundary, -+ bool parallel) : -+ FilteringDCTOC(sp, cl, precision, boundary), -+ _cfls(sp), _collector(collector), _parallel(parallel) {} -+}; -+ -+// We de-virtualize the block-related calls below, since we know that our -+// space is a CompactibleFreeListSpace. -+ -+#define FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \ -+void FreeListSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \ -+ HeapWord* bottom, \ -+ HeapWord* top, \ -+ ClosureType* cl) { \ -+ if (_parallel) { \ -+ walk_mem_region_with_cl_par(mr, bottom, top, cl); \ -+ } else { \ -+ walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \ -+ } \ -+} \ -+void FreeListSpaceDCTOC::walk_mem_region_with_cl_par(MemRegion mr, \ -+ HeapWord* bottom, \ -+ HeapWord* top, \ -+ ClosureType* cl) { \ -+ /* Skip parts that are before "mr", in case "block_start" sent us \ -+ back too far. */ \ -+ HeapWord* mr_start = mr.start(); \ -+ size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ -+ HeapWord* next = bottom + bot_size; \ -+ while (next < mr_start) { \ -+ bottom = next; \ -+ bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ -+ next = bottom + bot_size; \ -+ } \ -+ \ -+ while (bottom < top) { \ -+ if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) && \ -+ !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ -+ oop(bottom)) && \ -+ !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ -+ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ -+ bottom += _cfls->adjustObjectSize(word_sz); \ -+ } else { \ -+ bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \ -+ } \ -+ } \ -+} \ -+void FreeListSpaceDCTOC::walk_mem_region_with_cl_nopar(MemRegion mr, \ -+ HeapWord* bottom, \ -+ HeapWord* top, \ -+ ClosureType* cl) { \ -+ /* Skip parts that are before "mr", in case "block_start" sent us \ -+ back too far. */ \ -+ HeapWord* mr_start = mr.start(); \ -+ size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -+ HeapWord* next = bottom + bot_size; \ -+ while (next < mr_start) { \ -+ bottom = next; \ -+ bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -+ next = bottom + bot_size; \ -+ } \ -+ \ -+ while (bottom < top) { \ -+ if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) && \ -+ !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ -+ oop(bottom)) && \ -+ !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ -+ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ -+ bottom += _cfls->adjustObjectSize(word_sz); \ -+ } else { \ -+ bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -+ } \ -+ } \ -+} -+ -+// (There are only two of these, rather than N, because the split is due -+// only to the introduction of the FilteringClosure, a local part of the -+// impl of this abstraction.) -+FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure) -+FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) -+ -+DirtyCardToOopClosure* -+CompactibleFreeListSpace::new_dcto_cl(OopIterateClosure* cl, -+ CardTable::PrecisionStyle precision, -+ HeapWord* boundary, -+ bool parallel) { -+ return new FreeListSpaceDCTOC(this, _collector, cl, precision, boundary, parallel); -+} -+ -+ -+// Note on locking for the space iteration functions: -+// since the collector's iteration activities are concurrent with -+// allocation activities by mutators, absent a suitable mutual exclusion -+// mechanism the iterators may go awry. For instance a block being iterated -+// may suddenly be allocated or divided up and part of it allocated and -+// so on. -+ -+// Apply the given closure to each block in the space. -+void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) { -+ assert_lock_strong(freelistLock()); -+ HeapWord *cur, *limit; -+ for (cur = bottom(), limit = end(); cur < limit; -+ cur += cl->do_blk_careful(cur)); -+} -+ -+// Apply the given closure to each block in the space. -+void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) { -+ assert_lock_strong(freelistLock()); -+ HeapWord *cur, *limit; -+ for (cur = bottom(), limit = end(); cur < limit; -+ cur += cl->do_blk(cur)); -+} -+ -+// Apply the given closure to each oop in the space. -+void CompactibleFreeListSpace::oop_iterate(OopIterateClosure* cl) { -+ assert_lock_strong(freelistLock()); -+ HeapWord *cur, *limit; -+ size_t curSize; -+ for (cur = bottom(), limit = end(); cur < limit; -+ cur += curSize) { -+ curSize = block_size(cur); -+ if (block_is_obj(cur)) { -+ oop(cur)->oop_iterate(cl); -+ } -+ } -+} -+ -+// NOTE: In the following methods, in order to safely be able to -+// apply the closure to an object, we need to be sure that the -+// object has been initialized. We are guaranteed that an object -+// is initialized if we are holding the Heap_lock with the -+// world stopped. -+void CompactibleFreeListSpace::verify_objects_initialized() const { -+ if (is_init_completed()) { -+ assert_locked_or_safepoint(Heap_lock); -+ if (Universe::is_fully_initialized()) { -+ guarantee(SafepointSynchronize::is_at_safepoint(), -+ "Required for objects to be initialized"); -+ } -+ } // else make a concession at vm start-up -+} -+ -+// Apply the given closure to each object in the space -+void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { -+ assert_lock_strong(freelistLock()); -+ NOT_PRODUCT(verify_objects_initialized()); -+ HeapWord *cur, *limit; -+ size_t curSize; -+ for (cur = bottom(), limit = end(); cur < limit; -+ cur += curSize) { -+ curSize = block_size(cur); -+ if (block_is_obj(cur)) { -+ blk->do_object(oop(cur)); -+ } -+ } -+} -+ -+// Apply the given closure to each live object in the space -+// The usage of CompactibleFreeListSpace -+// by the ConcurrentMarkSweepGeneration for concurrent GC's allows -+// objects in the space with references to objects that are no longer -+// valid. For example, an object may reference another object -+// that has already been sweep up (collected). This method uses -+// obj_is_alive() to determine whether it is safe to apply the closure to -+// an object. See obj_is_alive() for details on how liveness of an -+// object is decided. -+ -+void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { -+ assert_lock_strong(freelistLock()); -+ NOT_PRODUCT(verify_objects_initialized()); -+ HeapWord *cur, *limit; -+ size_t curSize; -+ for (cur = bottom(), limit = end(); cur < limit; -+ cur += curSize) { -+ curSize = block_size(cur); -+ if (block_is_obj(cur) && obj_is_alive(cur)) { -+ blk->do_object(oop(cur)); -+ } -+ } -+} -+ -+void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, -+ UpwardsObjectClosure* cl) { -+ assert_locked(freelistLock()); -+ NOT_PRODUCT(verify_objects_initialized()); -+ assert(!mr.is_empty(), "Should be non-empty"); -+ // We use MemRegion(bottom(), end()) rather than used_region() below -+ // because the two are not necessarily equal for some kinds of -+ // spaces, in particular, certain kinds of free list spaces. -+ // We could use the more complicated but more precise: -+ // MemRegion(used_region().start(), align_up(used_region().end(), CardSize)) -+ // but the slight imprecision seems acceptable in the assertion check. -+ assert(MemRegion(bottom(), end()).contains(mr), -+ "Should be within used space"); -+ HeapWord* prev = cl->previous(); // max address from last time -+ if (prev >= mr.end()) { // nothing to do -+ return; -+ } -+ // This assert will not work when we go from cms space to perm -+ // space, and use same closure. Easy fix deferred for later. XXX YSR -+ // assert(prev == NULL || contains(prev), "Should be within space"); -+ -+ bool last_was_obj_array = false; -+ HeapWord *blk_start_addr, *region_start_addr; -+ if (prev > mr.start()) { -+ region_start_addr = prev; -+ blk_start_addr = prev; -+ // The previous invocation may have pushed "prev" beyond the -+ // last allocated block yet there may be still be blocks -+ // in this region due to a particular coalescing policy. -+ // Relax the assertion so that the case where the unallocated -+ // block is maintained and "prev" is beyond the unallocated -+ // block does not cause the assertion to fire. -+ assert((BlockOffsetArrayUseUnallocatedBlock && -+ (!is_in(prev))) || -+ (blk_start_addr == block_start(region_start_addr)), "invariant"); -+ } else { -+ region_start_addr = mr.start(); -+ blk_start_addr = block_start(region_start_addr); -+ } -+ HeapWord* region_end_addr = mr.end(); -+ MemRegion derived_mr(region_start_addr, region_end_addr); -+ while (blk_start_addr < region_end_addr) { -+ const size_t size = block_size(blk_start_addr); -+ if (block_is_obj(blk_start_addr)) { -+ last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr); -+ } else { -+ last_was_obj_array = false; -+ } -+ blk_start_addr += size; -+ } -+ if (!last_was_obj_array) { -+ assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()), -+ "Should be within (closed) used space"); -+ assert(blk_start_addr > prev, "Invariant"); -+ cl->set_previous(blk_start_addr); // min address for next time -+ } -+} -+ -+// Callers of this iterator beware: The closure application should -+// be robust in the face of uninitialized objects and should (always) -+// return a correct size so that the next addr + size below gives us a -+// valid block boundary. [See for instance, -+// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful() -+// in ConcurrentMarkSweepGeneration.cpp.] -+HeapWord* -+CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr, -+ ObjectClosureCareful* cl) { -+ assert_lock_strong(freelistLock()); -+ // Can't use used_region() below because it may not necessarily -+ // be the same as [bottom(),end()); although we could -+ // use [used_region().start(),align_up(used_region().end(),CardSize)), -+ // that appears too cumbersome, so we just do the simpler check -+ // in the assertion below. -+ assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr), -+ "mr should be non-empty and within used space"); -+ HeapWord *addr, *end; -+ size_t size; -+ for (addr = block_start_careful(mr.start()), end = mr.end(); -+ addr < end; addr += size) { -+ FreeChunk* fc = (FreeChunk*)addr; -+ if (fc->is_free()) { -+ // Since we hold the free list lock, which protects direct -+ // allocation in this generation by mutators, a free object -+ // will remain free throughout this iteration code. -+ size = fc->size(); -+ } else { -+ // Note that the object need not necessarily be initialized, -+ // because (for instance) the free list lock does NOT protect -+ // object initialization. The closure application below must -+ // therefore be correct in the face of uninitialized objects. -+ size = cl->do_object_careful_m(oop(addr), mr); -+ if (size == 0) { -+ // An unparsable object found. Signal early termination. -+ return addr; -+ } -+ } -+ } -+ return NULL; -+} -+ -+ -+HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const { -+ NOT_PRODUCT(verify_objects_initialized()); -+ return _bt.block_start(p); -+} -+ -+HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const { -+ return _bt.block_start_careful(p); -+} -+ -+size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { -+ NOT_PRODUCT(verify_objects_initialized()); -+ // This must be volatile, or else there is a danger that the compiler -+ // will compile the code below into a sometimes-infinite loop, by keeping -+ // the value read the first time in a register. -+ while (true) { -+ // We must do this until we get a consistent view of the object. -+ if (FreeChunk::indicatesFreeChunk(p)) { -+ volatile FreeChunk* fc = (volatile FreeChunk*)p; -+ size_t res = fc->size(); -+ -+ // Bugfix for systems with weak memory model (PPC64/IA64). The -+ // block's free bit was set and we have read the size of the -+ // block. Acquire and check the free bit again. If the block is -+ // still free, the read size is correct. -+ OrderAccess::acquire(); -+ -+ // If the object is still a free chunk, return the size, else it -+ // has been allocated so try again. -+ if (FreeChunk::indicatesFreeChunk(p)) { -+ assert(res != 0, "Block size should not be 0"); -+ return res; -+ } -+ } else { -+ // Ensure klass read before size. -+ Klass* k = oop(p)->klass_or_null_acquire(); -+ if (k != NULL) { -+ assert(k->is_klass(), "Should really be klass oop."); -+ oop o = (oop)p; -+ assert(oopDesc::is_oop(o, true /* ignore mark word */), "Should be an oop."); -+ -+ size_t res = o->size_given_klass(k); -+ res = adjustObjectSize(res); -+ assert(res != 0, "Block size should not be 0"); -+ return res; -+ } -+ } -+ } -+} -+ -+// TODO: Now that is_parsable is gone, we should combine these two functions. -+// A variant of the above that uses the Printezis bits for -+// unparsable but allocated objects. This avoids any possible -+// stalls waiting for mutators to initialize objects, and is -+// thus potentially faster than the variant above. However, -+// this variant may return a zero size for a block that is -+// under mutation and for which a consistent size cannot be -+// inferred without stalling; see CMSCollector::block_size_if_printezis_bits(). -+size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p, -+ const CMSCollector* c) -+const { -+ assert(MemRegion(bottom(), end()).contains(p), "p not in space"); -+ // This must be volatile, or else there is a danger that the compiler -+ // will compile the code below into a sometimes-infinite loop, by keeping -+ // the value read the first time in a register. -+ DEBUG_ONLY(uint loops = 0;) -+ while (true) { -+ // We must do this until we get a consistent view of the object. -+ if (FreeChunk::indicatesFreeChunk(p)) { -+ volatile FreeChunk* fc = (volatile FreeChunk*)p; -+ size_t res = fc->size(); -+ -+ // Bugfix for systems with weak memory model (PPC64/IA64). The -+ // free bit of the block was set and we have read the size of -+ // the block. Acquire and check the free bit again. If the -+ // block is still free, the read size is correct. -+ OrderAccess::acquire(); -+ -+ if (FreeChunk::indicatesFreeChunk(p)) { -+ assert(res != 0, "Block size should not be 0"); -+ assert(loops == 0, "Should be 0"); -+ return res; -+ } -+ } else { -+ // Ensure klass read before size. -+ Klass* k = oop(p)->klass_or_null_acquire(); -+ if (k != NULL) { -+ assert(k->is_klass(), "Should really be klass oop."); -+ oop o = (oop)p; -+ assert(oopDesc::is_oop(o), "Should be an oop"); -+ -+ size_t res = o->size_given_klass(k); -+ res = adjustObjectSize(res); -+ assert(res != 0, "Block size should not be 0"); -+ return res; -+ } else { -+ // May return 0 if P-bits not present. -+ return c->block_size_if_printezis_bits(p); -+ } -+ } -+ assert(loops == 0, "Can loop at most once"); -+ DEBUG_ONLY(loops++;) -+ } -+} -+ -+size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const { -+ NOT_PRODUCT(verify_objects_initialized()); -+ assert(MemRegion(bottom(), end()).contains(p), "p not in space"); -+ FreeChunk* fc = (FreeChunk*)p; -+ if (fc->is_free()) { -+ return fc->size(); -+ } else { -+ // Ignore mark word because this may be a recently promoted -+ // object whose mark word is used to chain together grey -+ // objects (the last one would have a null value). -+ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -+ return adjustObjectSize(oop(p)->size()); -+ } -+} -+ -+// This implementation assumes that the property of "being an object" is -+// stable. But being a free chunk may not be (because of parallel -+// promotion.) -+bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const { -+ FreeChunk* fc = (FreeChunk*)p; -+ assert(is_in_reserved(p), "Should be in space"); -+ if (FreeChunk::indicatesFreeChunk(p)) return false; -+ Klass* k = oop(p)->klass_or_null_acquire(); -+ if (k != NULL) { -+ // Ignore mark word because it may have been used to -+ // chain together promoted objects (the last one -+ // would have a null value). -+ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -+ return true; -+ } else { -+ return false; // Was not an object at the start of collection. -+ } -+} -+ -+// Check if the object is alive. This fact is checked either by consulting -+// the main marking bitmap in the sweeping phase or, if it's a permanent -+// generation and we're not in the sweeping phase, by checking the -+// perm_gen_verify_bit_map where we store the "deadness" information if -+// we did not sweep the perm gen in the most recent previous GC cycle. -+bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const { -+ assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(), -+ "Else races are possible"); -+ assert(block_is_obj(p), "The address should point to an object"); -+ -+ // If we're sweeping, we use object liveness information from the main bit map -+ // for both perm gen and old gen. -+ // We don't need to lock the bitmap (live_map or dead_map below), because -+ // EITHER we are in the middle of the sweeping phase, and the -+ // main marking bit map (live_map below) is locked, -+ // OR we're in other phases and perm_gen_verify_bit_map (dead_map below) -+ // is stable, because it's mutated only in the sweeping phase. -+ // NOTE: This method is also used by jmap where, if class unloading is -+ // off, the results can return "false" for legitimate perm objects, -+ // when we are not in the midst of a sweeping phase, which can result -+ // in jmap not reporting certain perm gen objects. This will be moot -+ // if/when the perm gen goes away in the future. -+ if (_collector->abstract_state() == CMSCollector::Sweeping) { -+ CMSBitMap* live_map = _collector->markBitMap(); -+ return live_map->par_isMarked((HeapWord*) p); -+ } -+ return true; -+} -+ -+bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const { -+ FreeChunk* fc = (FreeChunk*)p; -+ assert(is_in_reserved(p), "Should be in space"); -+ assert(_bt.block_start(p) == p, "Should be a block boundary"); -+ if (!fc->is_free()) { -+ // Ignore mark word because it may have been used to -+ // chain together promoted objects (the last one -+ // would have a null value). -+ assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -+ return true; -+ } -+ return false; -+} -+ -+// "MT-safe but not guaranteed MT-precise" (TM); you may get an -+// approximate answer if you don't hold the freelistlock when you call this. -+size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const { -+ size_t size = 0; -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ debug_only( -+ // We may be calling here without the lock in which case we -+ // won't do this modest sanity check. -+ if (freelistLock()->owned_by_self()) { -+ size_t total_list_size = 0; -+ for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -+ fc = fc->next()) { -+ total_list_size += i; -+ } -+ assert(total_list_size == i * _indexedFreeList[i].count(), -+ "Count in list is incorrect"); -+ } -+ ) -+ size += i * _indexedFreeList[i].count(); -+ } -+ return size; -+} -+ -+HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) { -+ MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); -+ return allocate(size); -+} -+ -+HeapWord* -+CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) { -+ return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size); -+} -+ -+HeapWord* CompactibleFreeListSpace::allocate(size_t size) { -+ assert_lock_strong(freelistLock()); -+ HeapWord* res = NULL; -+ assert(size == adjustObjectSize(size), -+ "use adjustObjectSize() before calling into allocate()"); -+ -+ res = allocate_adaptive_freelists(size); -+ -+ if (res != NULL) { -+ // check that res does lie in this space! -+ assert(is_in_reserved(res), "Not in this space!"); -+ assert(is_aligned((void*)res), "alignment check"); -+ -+ FreeChunk* fc = (FreeChunk*)res; -+ fc->markNotFree(); -+ assert(!fc->is_free(), "shouldn't be marked free"); -+ assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized"); -+ // Verify that the block offset table shows this to -+ // be a single block, but not one which is unallocated. -+ _bt.verify_single_block(res, size); -+ _bt.verify_not_unallocated(res, size); -+ // mangle a just allocated object with a distinct pattern. -+ debug_only(fc->mangleAllocated(size)); -+ } -+ -+ // During GC we do not need to recalculate the stable used value for -+ // every allocation in old gen. It is done once at the end of GC instead -+ // for performance reasons. -+ if (!CMSHeap::heap()->is_gc_active()) { -+ recalculate_used_stable(); -+ } -+ -+ return res; -+} -+ -+HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) { -+ assert_lock_strong(freelistLock()); -+ HeapWord* res = NULL; -+ assert(size == adjustObjectSize(size), -+ "use adjustObjectSize() before calling into allocate()"); -+ -+ // Strategy -+ // if small -+ // exact size from small object indexed list if small -+ // small or large linear allocation block (linAB) as appropriate -+ // take from lists of greater sized chunks -+ // else -+ // dictionary -+ // small or large linear allocation block if it has the space -+ // Try allocating exact size from indexTable first -+ if (size < IndexSetSize) { -+ res = (HeapWord*) getChunkFromIndexedFreeList(size); -+ if(res != NULL) { -+ assert(res != (HeapWord*)_indexedFreeList[size].head(), -+ "Not removed from free list"); -+ // no block offset table adjustment is necessary on blocks in -+ // the indexed lists. -+ -+ // Try allocating from the small LinAB -+ } else if (size < _smallLinearAllocBlock._allocation_size_limit && -+ (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) { -+ // if successful, the above also adjusts block offset table -+ // Note that this call will refill the LinAB to -+ // satisfy the request. This is different that -+ // evm. -+ // Don't record chunk off a LinAB? smallSplitBirth(size); -+ } else { -+ // Raid the exact free lists larger than size, even if they are not -+ // overpopulated. -+ res = (HeapWord*) getChunkFromGreater(size); -+ } -+ } else { -+ // Big objects get allocated directly from the dictionary. -+ res = (HeapWord*) getChunkFromDictionaryExact(size); -+ if (res == NULL) { -+ // Try hard not to fail since an allocation failure will likely -+ // trigger a synchronous GC. Try to get the space from the -+ // allocation blocks. -+ res = getChunkFromSmallLinearAllocBlockRemainder(size); -+ } -+ } -+ -+ return res; -+} -+ -+// A worst-case estimate of the space required (in HeapWords) to expand the heap -+// when promoting obj. -+size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const { -+ // Depending on the object size, expansion may require refilling either a -+ // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize -+ // is added because the dictionary may over-allocate to avoid fragmentation. -+ size_t space = obj_size; -+ space += _promoInfo.refillSize() + 2 * MinChunkSize; -+ return space; -+} -+ -+FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) { -+ FreeChunk* ret; -+ -+ assert(numWords >= MinChunkSize, "Size is less than minimum"); -+ assert(linearAllocationWouldFail() || bestFitFirst(), -+ "Should not be here"); -+ -+ size_t i; -+ size_t currSize = numWords + MinChunkSize; -+ assert(is_object_aligned(currSize), "currSize should be aligned"); -+ for (i = currSize; i < IndexSetSize; i += IndexSetStride) { -+ AdaptiveFreeList* fl = &_indexedFreeList[i]; -+ if (fl->head()) { -+ ret = getFromListGreater(fl, numWords); -+ assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); -+ return ret; -+ } -+ } -+ -+ currSize = MAX2((size_t)SmallForDictionary, -+ (size_t)(numWords + MinChunkSize)); -+ -+ /* Try to get a chunk that satisfies request, while avoiding -+ fragmentation that can't be handled. */ -+ { -+ ret = dictionary()->get_chunk(currSize); -+ if (ret != NULL) { -+ assert(ret->size() - numWords >= MinChunkSize, -+ "Chunk is too small"); -+ _bt.allocated((HeapWord*)ret, ret->size()); -+ /* Carve returned chunk. */ -+ (void) splitChunkAndReturnRemainder(ret, numWords); -+ /* Label this as no longer a free chunk. */ -+ assert(ret->is_free(), "This chunk should be free"); -+ ret->link_prev(NULL); -+ } -+ assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); -+ return ret; -+ } -+ ShouldNotReachHere(); -+} -+ -+bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { -+ assert(fc->size() < IndexSetSize, "Size of chunk is too large"); -+ return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc); -+} -+ -+bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { -+ assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || -+ (_smallLinearAllocBlock._word_size == fc->size()), -+ "Linear allocation block shows incorrect size"); -+ return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && -+ (_smallLinearAllocBlock._word_size == fc->size())); -+} -+ -+// Check if the purported free chunk is present either as a linear -+// allocation block, the size-indexed table of (smaller) free blocks, -+// or the larger free blocks kept in the binary tree dictionary. -+bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const { -+ if (verify_chunk_is_linear_alloc_block(fc)) { -+ return true; -+ } else if (fc->size() < IndexSetSize) { -+ return verifyChunkInIndexedFreeLists(fc); -+ } else { -+ return dictionary()->verify_chunk_in_free_list(fc); -+ } -+} -+ -+#ifndef PRODUCT -+void CompactibleFreeListSpace::assert_locked() const { -+ CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock()); -+} -+ -+void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const { -+ CMSLockVerifier::assert_locked(lock); -+} -+#endif -+ -+FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { -+ // In the parallel case, the main thread holds the free list lock -+ // on behalf the parallel threads. -+ FreeChunk* fc; -+ { -+ // If GC is parallel, this might be called by several threads. -+ // This should be rare enough that the locking overhead won't affect -+ // the sequential code. -+ MutexLockerEx x(parDictionaryAllocLock(), -+ Mutex::_no_safepoint_check_flag); -+ fc = getChunkFromDictionary(size); -+ } -+ if (fc != NULL) { -+ fc->dontCoalesce(); -+ assert(fc->is_free(), "Should be free, but not coalescable"); -+ // Verify that the block offset table shows this to -+ // be a single block, but not one which is unallocated. -+ _bt.verify_single_block((HeapWord*)fc, fc->size()); -+ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -+ } -+ return fc; -+} -+ -+oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) { -+ assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); -+ assert_locked(); -+ -+ // if we are tracking promotions, then first ensure space for -+ // promotion (including spooling space for saving header if necessary). -+ // then allocate and copy, then track promoted info if needed. -+ // When tracking (see PromotionInfo::track()), the mark word may -+ // be displaced and in this case restoration of the mark word -+ // occurs in the (oop_since_save_marks_)iterate phase. -+ if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) { -+ return NULL; -+ } -+ // Call the allocate(size_t, bool) form directly to avoid the -+ // additional call through the allocate(size_t) form. Having -+ // the compile inline the call is problematic because allocate(size_t) -+ // is a virtual method. -+ HeapWord* res = allocate(adjustObjectSize(obj_size)); -+ if (res != NULL) { -+ Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size); -+ // if we should be tracking promotions, do so. -+ if (_promoInfo.tracking()) { -+ _promoInfo.track((PromotedObject*)res); -+ } -+ } -+ return oop(res); -+} -+ -+HeapWord* -+CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) { -+ assert_locked(); -+ assert(size >= MinChunkSize, "minimum chunk size"); -+ assert(size < _smallLinearAllocBlock._allocation_size_limit, -+ "maximum from smallLinearAllocBlock"); -+ return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size); -+} -+ -+HeapWord* -+CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk, -+ size_t size) { -+ assert_locked(); -+ assert(size >= MinChunkSize, "too small"); -+ HeapWord* res = NULL; -+ // Try to do linear allocation from blk, making sure that -+ if (blk->_word_size == 0) { -+ // We have probably been unable to fill this either in the prologue or -+ // when it was exhausted at the last linear allocation. Bail out until -+ // next time. -+ assert(blk->_ptr == NULL, "consistency check"); -+ return NULL; -+ } -+ assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check"); -+ res = getChunkFromLinearAllocBlockRemainder(blk, size); -+ if (res != NULL) return res; -+ -+ // about to exhaust this linear allocation block -+ if (blk->_word_size == size) { // exactly satisfied -+ res = blk->_ptr; -+ _bt.allocated(res, blk->_word_size); -+ } else if (size + MinChunkSize <= blk->_refillSize) { -+ size_t sz = blk->_word_size; -+ // Update _unallocated_block if the size is such that chunk would be -+ // returned to the indexed free list. All other chunks in the indexed -+ // free lists are allocated from the dictionary so that _unallocated_block -+ // has already been adjusted for them. Do it here so that the cost -+ // for all chunks added back to the indexed free lists. -+ if (sz < SmallForDictionary) { -+ _bt.allocated(blk->_ptr, sz); -+ } -+ // Return the chunk that isn't big enough, and then refill below. -+ addChunkToFreeLists(blk->_ptr, sz); -+ split_birth(sz); -+ // Don't keep statistics on adding back chunk from a LinAB. -+ } else { -+ // A refilled block would not satisfy the request. -+ return NULL; -+ } -+ -+ blk->_ptr = NULL; blk->_word_size = 0; -+ refillLinearAllocBlock(blk); -+ assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, -+ "block was replenished"); -+ if (res != NULL) { -+ split_birth(size); -+ repairLinearAllocBlock(blk); -+ } else if (blk->_ptr != NULL) { -+ res = blk->_ptr; -+ size_t blk_size = blk->_word_size; -+ blk->_word_size -= size; -+ blk->_ptr += size; -+ split_birth(size); -+ repairLinearAllocBlock(blk); -+ // Update BOT last so that other (parallel) GC threads see a consistent -+ // view of the BOT and free blocks. -+ // Above must occur before BOT is updated below. -+ OrderAccess::storestore(); -+ _bt.split_block(res, blk_size, size); // adjust block offset table -+ } -+ return res; -+} -+ -+HeapWord* CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder( -+ LinearAllocBlock* blk, -+ size_t size) { -+ assert_locked(); -+ assert(size >= MinChunkSize, "too small"); -+ -+ HeapWord* res = NULL; -+ // This is the common case. Keep it simple. -+ if (blk->_word_size >= size + MinChunkSize) { -+ assert(blk->_ptr != NULL, "consistency check"); -+ res = blk->_ptr; -+ // Note that the BOT is up-to-date for the linAB before allocation. It -+ // indicates the start of the linAB. The split_block() updates the -+ // BOT for the linAB after the allocation (indicates the start of the -+ // next chunk to be allocated). -+ size_t blk_size = blk->_word_size; -+ blk->_word_size -= size; -+ blk->_ptr += size; -+ split_birth(size); -+ repairLinearAllocBlock(blk); -+ // Update BOT last so that other (parallel) GC threads see a consistent -+ // view of the BOT and free blocks. -+ // Above must occur before BOT is updated below. -+ OrderAccess::storestore(); -+ _bt.split_block(res, blk_size, size); // adjust block offset table -+ _bt.allocated(res, size); -+ } -+ return res; -+} -+ -+FreeChunk* -+CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) { -+ assert_locked(); -+ assert(size < SmallForDictionary, "just checking"); -+ FreeChunk* res; -+ res = _indexedFreeList[size].get_chunk_at_head(); -+ if (res == NULL) { -+ res = getChunkFromIndexedFreeListHelper(size); -+ } -+ _bt.verify_not_unallocated((HeapWord*) res, size); -+ assert(res == NULL || res->size() == size, "Incorrect block size"); -+ return res; -+} -+ -+FreeChunk* -+CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, -+ bool replenish) { -+ assert_locked(); -+ FreeChunk* fc = NULL; -+ if (size < SmallForDictionary) { -+ assert(_indexedFreeList[size].head() == NULL || -+ _indexedFreeList[size].surplus() <= 0, -+ "List for this size should be empty or under populated"); -+ // Try best fit in exact lists before replenishing the list -+ if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) { -+ // Replenish list. -+ // -+ // Things tried that failed. -+ // Tried allocating out of the two LinAB's first before -+ // replenishing lists. -+ // Tried small linAB of size 256 (size in indexed list) -+ // and replenishing indexed lists from the small linAB. -+ // -+ FreeChunk* newFc = NULL; -+ const size_t replenish_size = CMSIndexedFreeListReplenish * size; -+ if (replenish_size < SmallForDictionary) { -+ // Do not replenish from an underpopulated size. -+ if (_indexedFreeList[replenish_size].surplus() > 0 && -+ _indexedFreeList[replenish_size].head() != NULL) { -+ newFc = _indexedFreeList[replenish_size].get_chunk_at_head(); -+ } else if (bestFitFirst()) { -+ newFc = bestFitSmall(replenish_size); -+ } -+ } -+ if (newFc == NULL && replenish_size > size) { -+ assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant"); -+ newFc = getChunkFromIndexedFreeListHelper(replenish_size, false); -+ } -+ // Note: The stats update re split-death of block obtained above -+ // will be recorded below precisely when we know we are going to -+ // be actually splitting it into more than one pieces below. -+ if (newFc != NULL) { -+ if (replenish || CMSReplenishIntermediate) { -+ // Replenish this list and return one block to caller. -+ size_t i; -+ FreeChunk *curFc, *nextFc; -+ size_t num_blk = newFc->size() / size; -+ assert(num_blk >= 1, "Smaller than requested?"); -+ assert(newFc->size() % size == 0, "Should be integral multiple of request"); -+ if (num_blk > 1) { -+ // we are sure we will be splitting the block just obtained -+ // into multiple pieces; record the split-death of the original -+ splitDeath(replenish_size); -+ } -+ // carve up and link blocks 0, ..., num_blk - 2 -+ // The last chunk is not added to the lists but is returned as the -+ // free chunk. -+ for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), -+ i = 0; -+ i < (num_blk - 1); -+ curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), -+ i++) { -+ curFc->set_size(size); -+ // Don't record this as a return in order to try and -+ // determine the "returns" from a GC. -+ _bt.verify_not_unallocated((HeapWord*) fc, size); -+ _indexedFreeList[size].return_chunk_at_tail(curFc, false); -+ _bt.mark_block((HeapWord*)curFc, size); -+ split_birth(size); -+ // Don't record the initial population of the indexed list -+ // as a split birth. -+ } -+ -+ // check that the arithmetic was OK above -+ assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, -+ "inconsistency in carving newFc"); -+ curFc->set_size(size); -+ _bt.mark_block((HeapWord*)curFc, size); -+ split_birth(size); -+ fc = curFc; -+ } else { -+ // Return entire block to caller -+ fc = newFc; -+ } -+ } -+ } -+ } else { -+ // Get a free chunk from the free chunk dictionary to be returned to -+ // replenish the indexed free list. -+ fc = getChunkFromDictionaryExact(size); -+ } -+ // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk"); -+ return fc; -+} -+ -+FreeChunk* -+CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { -+ assert_locked(); -+ FreeChunk* fc = _dictionary->get_chunk(size); -+ if (fc == NULL) { -+ return NULL; -+ } -+ _bt.allocated((HeapWord*)fc, fc->size()); -+ if (fc->size() >= size + MinChunkSize) { -+ fc = splitChunkAndReturnRemainder(fc, size); -+ } -+ assert(fc->size() >= size, "chunk too small"); -+ assert(fc->size() < size + MinChunkSize, "chunk too big"); -+ _bt.verify_single_block((HeapWord*)fc, fc->size()); -+ return fc; -+} -+ -+FreeChunk* -+CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { -+ assert_locked(); -+ FreeChunk* fc = _dictionary->get_chunk(size); -+ if (fc == NULL) { -+ return fc; -+ } -+ _bt.allocated((HeapWord*)fc, fc->size()); -+ if (fc->size() == size) { -+ _bt.verify_single_block((HeapWord*)fc, size); -+ return fc; -+ } -+ assert(fc->size() > size, "get_chunk() guarantee"); -+ if (fc->size() < size + MinChunkSize) { -+ // Return the chunk to the dictionary and go get a bigger one. -+ returnChunkToDictionary(fc); -+ fc = _dictionary->get_chunk(size + MinChunkSize); -+ if (fc == NULL) { -+ return NULL; -+ } -+ _bt.allocated((HeapWord*)fc, fc->size()); -+ } -+ assert(fc->size() >= size + MinChunkSize, "tautology"); -+ fc = splitChunkAndReturnRemainder(fc, size); -+ assert(fc->size() == size, "chunk is wrong size"); -+ _bt.verify_single_block((HeapWord*)fc, size); -+ return fc; -+} -+ -+void -+CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { -+ assert_locked(); -+ -+ size_t size = chunk->size(); -+ _bt.verify_single_block((HeapWord*)chunk, size); -+ // adjust _unallocated_block downward, as necessary -+ _bt.freed((HeapWord*)chunk, size); -+ _dictionary->return_chunk(chunk); -+#ifndef PRODUCT -+ if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { -+ TreeChunk >* tc = TreeChunk >::as_TreeChunk(chunk); -+ TreeList >* tl = tc->list(); -+ tl->verify_stats(); -+ } -+#endif // PRODUCT -+} -+ -+void -+CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { -+ assert_locked(); -+ size_t size = fc->size(); -+ _bt.verify_single_block((HeapWord*) fc, size); -+ _bt.verify_not_unallocated((HeapWord*) fc, size); -+ _indexedFreeList[size].return_chunk_at_tail(fc); -+#ifndef PRODUCT -+ if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { -+ _indexedFreeList[size].verify_stats(); -+ } -+#endif // PRODUCT -+} -+ -+// Add chunk to end of last block -- if it's the largest -+// block -- and update BOT and census data. We would -+// of course have preferred to coalesce it with the -+// last block, but it's currently less expensive to find the -+// largest block than it is to find the last. -+void -+CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats( -+ HeapWord* chunk, size_t size) { -+ // check that the chunk does lie in this space! -+ assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); -+ // One of the parallel gc task threads may be here -+ // whilst others are allocating. -+ Mutex* lock = &_parDictionaryAllocLock; -+ FreeChunk* ec; -+ { -+ MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); -+ ec = dictionary()->find_largest_dict(); // get largest block -+ if (ec != NULL && ec->end() == (uintptr_t*) chunk) { -+ // It's a coterminal block - we can coalesce. -+ size_t old_size = ec->size(); -+ coalDeath(old_size); -+ removeChunkFromDictionary(ec); -+ size += old_size; -+ } else { -+ ec = (FreeChunk*)chunk; -+ } -+ } -+ ec->set_size(size); -+ debug_only(ec->mangleFreed(size)); -+ if (size < SmallForDictionary) { -+ lock = _indexedFreeListParLocks[size]; -+ } -+ MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); -+ addChunkAndRepairOffsetTable((HeapWord*)ec, size, true); -+ // record the birth under the lock since the recording involves -+ // manipulation of the list on which the chunk lives and -+ // if the chunk is allocated and is the last on the list, -+ // the list can go away. -+ coalBirth(size); -+} -+ -+void -+CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk, -+ size_t size) { -+ // check that the chunk does lie in this space! -+ assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); -+ assert_locked(); -+ _bt.verify_single_block(chunk, size); -+ -+ FreeChunk* fc = (FreeChunk*) chunk; -+ fc->set_size(size); -+ debug_only(fc->mangleFreed(size)); -+ if (size < SmallForDictionary) { -+ returnChunkToFreeList(fc); -+ } else { -+ returnChunkToDictionary(fc); -+ } -+} -+ -+void -+CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk, -+ size_t size, bool coalesced) { -+ assert_locked(); -+ assert(chunk != NULL, "null chunk"); -+ if (coalesced) { -+ // repair BOT -+ _bt.single_block(chunk, size); -+ } -+ addChunkToFreeLists(chunk, size); -+} -+ -+// We _must_ find the purported chunk on our free lists; -+// we assert if we don't. -+void -+CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) { -+ size_t size = fc->size(); -+ assert_locked(); -+ debug_only(verifyFreeLists()); -+ if (size < SmallForDictionary) { -+ removeChunkFromIndexedFreeList(fc); -+ } else { -+ removeChunkFromDictionary(fc); -+ } -+ _bt.verify_single_block((HeapWord*)fc, size); -+ debug_only(verifyFreeLists()); -+} -+ -+void -+CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) { -+ size_t size = fc->size(); -+ assert_locked(); -+ assert(fc != NULL, "null chunk"); -+ _bt.verify_single_block((HeapWord*)fc, size); -+ _dictionary->remove_chunk(fc); -+ // adjust _unallocated_block upward, as necessary -+ _bt.allocated((HeapWord*)fc, size); -+} -+ -+void -+CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) { -+ assert_locked(); -+ size_t size = fc->size(); -+ _bt.verify_single_block((HeapWord*)fc, size); -+ NOT_PRODUCT( -+ if (FLSVerifyIndexTable) { -+ verifyIndexedFreeList(size); -+ } -+ ) -+ _indexedFreeList[size].remove_chunk(fc); -+ NOT_PRODUCT( -+ if (FLSVerifyIndexTable) { -+ verifyIndexedFreeList(size); -+ } -+ ) -+} -+ -+FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) { -+ /* A hint is the next larger size that has a surplus. -+ Start search at a size large enough to guarantee that -+ the excess is >= MIN_CHUNK. */ -+ size_t start = align_object_size(numWords + MinChunkSize); -+ if (start < IndexSetSize) { -+ AdaptiveFreeList* it = _indexedFreeList; -+ size_t hint = _indexedFreeList[start].hint(); -+ while (hint < IndexSetSize) { -+ assert(is_object_aligned(hint), "hint should be aligned"); -+ AdaptiveFreeList *fl = &_indexedFreeList[hint]; -+ if (fl->surplus() > 0 && fl->head() != NULL) { -+ // Found a list with surplus, reset original hint -+ // and split out a free chunk which is returned. -+ _indexedFreeList[start].set_hint(hint); -+ FreeChunk* res = getFromListGreater(fl, numWords); -+ assert(res == NULL || res->is_free(), -+ "Should be returning a free chunk"); -+ return res; -+ } -+ hint = fl->hint(); /* keep looking */ -+ } -+ /* None found. */ -+ it[start].set_hint(IndexSetSize); -+ } -+ return NULL; -+} -+ -+/* Requires fl->size >= numWords + MinChunkSize */ -+FreeChunk* CompactibleFreeListSpace::getFromListGreater(AdaptiveFreeList* fl, -+ size_t numWords) { -+ FreeChunk *curr = fl->head(); -+ size_t oldNumWords = curr->size(); -+ assert(numWords >= MinChunkSize, "Word size is too small"); -+ assert(curr != NULL, "List is empty"); -+ assert(oldNumWords >= numWords + MinChunkSize, -+ "Size of chunks in the list is too small"); -+ -+ fl->remove_chunk(curr); -+ // recorded indirectly by splitChunkAndReturnRemainder - -+ // smallSplit(oldNumWords, numWords); -+ FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); -+ // Does anything have to be done for the remainder in terms of -+ // fixing the card table? -+ assert(new_chunk == NULL || new_chunk->is_free(), -+ "Should be returning a free chunk"); -+ return new_chunk; -+} -+ -+FreeChunk* -+CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk, -+ size_t new_size) { -+ assert_locked(); -+ size_t size = chunk->size(); -+ assert(size > new_size, "Split from a smaller block?"); -+ assert(is_aligned(chunk), "alignment problem"); -+ assert(size == adjustObjectSize(size), "alignment problem"); -+ size_t rem_sz = size - new_size; -+ assert(rem_sz == adjustObjectSize(rem_sz), "alignment problem"); -+ assert(rem_sz >= MinChunkSize, "Free chunk smaller than minimum"); -+ FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); -+ assert(is_aligned(ffc), "alignment problem"); -+ ffc->set_size(rem_sz); -+ ffc->link_next(NULL); -+ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -+ // Above must occur before BOT is updated below. -+ // adjust block offset table -+ OrderAccess::storestore(); -+ assert(chunk->is_free() && ffc->is_free(), "Error"); -+ _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); -+ if (rem_sz < SmallForDictionary) { -+ // The freeList lock is held, but multiple GC task threads might be executing in parallel. -+ bool is_par = Thread::current()->is_GC_task_thread(); -+ if (is_par) _indexedFreeListParLocks[rem_sz]->lock(); -+ returnChunkToFreeList(ffc); -+ split(size, rem_sz); -+ if (is_par) _indexedFreeListParLocks[rem_sz]->unlock(); -+ } else { -+ returnChunkToDictionary(ffc); -+ split(size, rem_sz); -+ } -+ chunk->set_size(new_size); -+ return chunk; -+} -+ -+void -+CompactibleFreeListSpace::sweep_completed() { -+ // Now that space is probably plentiful, refill linear -+ // allocation blocks as needed. -+ refillLinearAllocBlocksIfNeeded(); -+} -+ -+void -+CompactibleFreeListSpace::gc_prologue() { -+ assert_locked(); -+ reportFreeListStatistics("Before GC:"); -+ refillLinearAllocBlocksIfNeeded(); -+} -+ -+void -+CompactibleFreeListSpace::gc_epilogue() { -+ assert_locked(); -+ assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); -+ _promoInfo.stopTrackingPromotions(); -+ repairLinearAllocationBlocks(); -+ reportFreeListStatistics("After GC:"); -+} -+ -+// Iteration support, mostly delegated from a CMS generation -+ -+void CompactibleFreeListSpace::save_marks() { -+ assert(Thread::current()->is_VM_thread(), -+ "Global variable should only be set when single-threaded"); -+ // Mark the "end" of the used space at the time of this call; -+ // note, however, that promoted objects from this point -+ // on are tracked in the _promoInfo below. -+ set_saved_mark_word(unallocated_block()); -+#ifdef ASSERT -+ // Check the sanity of save_marks() etc. -+ MemRegion ur = used_region(); -+ MemRegion urasm = used_region_at_save_marks(); -+ assert(ur.contains(urasm), -+ " Error at save_marks(): [" PTR_FORMAT "," PTR_FORMAT ")" -+ " should contain [" PTR_FORMAT "," PTR_FORMAT ")", -+ p2i(ur.start()), p2i(ur.end()), p2i(urasm.start()), p2i(urasm.end())); -+#endif -+ // inform allocator that promotions should be tracked. -+ assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); -+ _promoInfo.startTrackingPromotions(); -+} -+ -+bool CompactibleFreeListSpace::no_allocs_since_save_marks() { -+ assert(_promoInfo.tracking(), "No preceding save_marks?"); -+ return _promoInfo.noPromotions(); -+} -+ -+bool CompactibleFreeListSpace::linearAllocationWouldFail() const { -+ return _smallLinearAllocBlock._word_size == 0; -+} -+ -+void CompactibleFreeListSpace::repairLinearAllocationBlocks() { -+ // Fix up linear allocation blocks to look like free blocks -+ repairLinearAllocBlock(&_smallLinearAllocBlock); -+} -+ -+void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) { -+ assert_locked(); -+ if (blk->_ptr != NULL) { -+ assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize, -+ "Minimum block size requirement"); -+ FreeChunk* fc = (FreeChunk*)(blk->_ptr); -+ fc->set_size(blk->_word_size); -+ fc->link_prev(NULL); // mark as free -+ fc->dontCoalesce(); -+ assert(fc->is_free(), "just marked it free"); -+ assert(fc->cantCoalesce(), "just marked it uncoalescable"); -+ } -+} -+ -+void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() { -+ assert_locked(); -+ if (_smallLinearAllocBlock._ptr == NULL) { -+ assert(_smallLinearAllocBlock._word_size == 0, -+ "Size of linAB should be zero if the ptr is NULL"); -+ // Reset the linAB refill and allocation size limit. -+ _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc); -+ } -+ refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock); -+} -+ -+void -+CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) { -+ assert_locked(); -+ assert((blk->_ptr == NULL && blk->_word_size == 0) || -+ (blk->_ptr != NULL && blk->_word_size >= MinChunkSize), -+ "blk invariant"); -+ if (blk->_ptr == NULL) { -+ refillLinearAllocBlock(blk); -+ } -+} -+ -+void -+CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) { -+ assert_locked(); -+ assert(blk->_word_size == 0 && blk->_ptr == NULL, -+ "linear allocation block should be empty"); -+ FreeChunk* fc; -+ if (blk->_refillSize < SmallForDictionary && -+ (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) { -+ // A linAB's strategy might be to use small sizes to reduce -+ // fragmentation but still get the benefits of allocation from a -+ // linAB. -+ } else { -+ fc = getChunkFromDictionary(blk->_refillSize); -+ } -+ if (fc != NULL) { -+ blk->_ptr = (HeapWord*)fc; -+ blk->_word_size = fc->size(); -+ fc->dontCoalesce(); // to prevent sweeper from sweeping us up -+ } -+} -+ -+// Support for compaction -+void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { -+ scan_and_forward(this, cp, false); -+ // of the free lists doesn't work after. -+ // Prepare_for_compaction() uses the space between live objects -+ // so that later phase can skip dead space quickly. So verification -+ // of the free lists doesn't work after. -+} -+ -+void CompactibleFreeListSpace::adjust_pointers() { -+ // In other versions of adjust_pointers(), a bail out -+ // based on the amount of live data in the generation -+ // (i.e., if 0, bail out) may be used. -+ // Cannot test used() == 0 here because the free lists have already -+ // been mangled by the compaction. -+ -+ scan_and_adjust_pointers(this); -+ // See note about verification in prepare_for_compaction(). -+} -+ -+void CompactibleFreeListSpace::compact() { -+ scan_and_compact(this, false); -+} -+ -+// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2] -+// where fbs is free block sizes -+double CompactibleFreeListSpace::flsFrag() const { -+ size_t itabFree = totalSizeInIndexedFreeLists(); -+ double frag = 0.0; -+ size_t i; -+ -+ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ double sz = i; -+ frag += _indexedFreeList[i].count() * (sz * sz); -+ } -+ -+ double totFree = itabFree + -+ _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); -+ if (totFree > 0) { -+ frag = ((frag + _dictionary->sum_of_squared_block_sizes()) / -+ (totFree * totFree)); -+ frag = (double)1.0 - frag; -+ } else { -+ assert(frag == 0.0, "Follows from totFree == 0"); -+ } -+ return frag; -+} -+ -+void CompactibleFreeListSpace::beginSweepFLCensus( -+ float inter_sweep_current, -+ float inter_sweep_estimate, -+ float intra_sweep_estimate) { -+ assert_locked(); -+ size_t i; -+ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ AdaptiveFreeList* fl = &_indexedFreeList[i]; -+ log_trace(gc, freelist)("size[" SIZE_FORMAT "] : ", i); -+ fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); -+ fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); -+ fl->set_before_sweep(fl->count()); -+ fl->set_bfr_surp(fl->surplus()); -+ } -+ _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent, -+ inter_sweep_current, -+ inter_sweep_estimate, -+ intra_sweep_estimate); -+} -+ -+void CompactibleFreeListSpace::setFLSurplus() { -+ assert_locked(); -+ size_t i; -+ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ AdaptiveFreeList *fl = &_indexedFreeList[i]; -+ fl->set_surplus(fl->count() - -+ (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); -+ } -+} -+ -+void CompactibleFreeListSpace::setFLHints() { -+ assert_locked(); -+ size_t i; -+ size_t h = IndexSetSize; -+ for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { -+ AdaptiveFreeList *fl = &_indexedFreeList[i]; -+ fl->set_hint(h); -+ if (fl->surplus() > 0) { -+ h = i; -+ } -+ } -+} -+ -+void CompactibleFreeListSpace::clearFLCensus() { -+ assert_locked(); -+ size_t i; -+ for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ AdaptiveFreeList *fl = &_indexedFreeList[i]; -+ fl->set_prev_sweep(fl->count()); -+ fl->set_coal_births(0); -+ fl->set_coal_deaths(0); -+ fl->set_split_births(0); -+ fl->set_split_deaths(0); -+ } -+} -+ -+void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { -+ log_debug(gc, freelist)("CMS: Large block " PTR_FORMAT, p2i(dictionary()->find_largest_dict())); -+ setFLSurplus(); -+ setFLHints(); -+ printFLCensus(sweep_count); -+ clearFLCensus(); -+ assert_locked(); -+ _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); -+} -+ -+bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { -+ if (size < SmallForDictionary) { -+ AdaptiveFreeList *fl = &_indexedFreeList[size]; -+ return (fl->coal_desired() < 0) || -+ ((int)fl->count() > fl->coal_desired()); -+ } else { -+ return dictionary()->coal_dict_over_populated(size); -+ } -+} -+ -+void CompactibleFreeListSpace::smallCoalBirth(size_t size) { -+ assert(size < SmallForDictionary, "Size too large for indexed list"); -+ AdaptiveFreeList *fl = &_indexedFreeList[size]; -+ fl->increment_coal_births(); -+ fl->increment_surplus(); -+} -+ -+void CompactibleFreeListSpace::smallCoalDeath(size_t size) { -+ assert(size < SmallForDictionary, "Size too large for indexed list"); -+ AdaptiveFreeList *fl = &_indexedFreeList[size]; -+ fl->increment_coal_deaths(); -+ fl->decrement_surplus(); -+} -+ -+void CompactibleFreeListSpace::coalBirth(size_t size) { -+ if (size < SmallForDictionary) { -+ smallCoalBirth(size); -+ } else { -+ dictionary()->dict_census_update(size, -+ false /* split */, -+ true /* birth */); -+ } -+} -+ -+void CompactibleFreeListSpace::coalDeath(size_t size) { -+ if(size < SmallForDictionary) { -+ smallCoalDeath(size); -+ } else { -+ dictionary()->dict_census_update(size, -+ false /* split */, -+ false /* birth */); -+ } -+} -+ -+void CompactibleFreeListSpace::smallSplitBirth(size_t size) { -+ assert(size < SmallForDictionary, "Size too large for indexed list"); -+ AdaptiveFreeList *fl = &_indexedFreeList[size]; -+ fl->increment_split_births(); -+ fl->increment_surplus(); -+} -+ -+void CompactibleFreeListSpace::smallSplitDeath(size_t size) { -+ assert(size < SmallForDictionary, "Size too large for indexed list"); -+ AdaptiveFreeList *fl = &_indexedFreeList[size]; -+ fl->increment_split_deaths(); -+ fl->decrement_surplus(); -+} -+ -+void CompactibleFreeListSpace::split_birth(size_t size) { -+ if (size < SmallForDictionary) { -+ smallSplitBirth(size); -+ } else { -+ dictionary()->dict_census_update(size, -+ true /* split */, -+ true /* birth */); -+ } -+} -+ -+void CompactibleFreeListSpace::splitDeath(size_t size) { -+ if (size < SmallForDictionary) { -+ smallSplitDeath(size); -+ } else { -+ dictionary()->dict_census_update(size, -+ true /* split */, -+ false /* birth */); -+ } -+} -+ -+void CompactibleFreeListSpace::split(size_t from, size_t to1) { -+ size_t to2 = from - to1; -+ splitDeath(from); -+ split_birth(to1); -+ split_birth(to2); -+} -+ -+void CompactibleFreeListSpace::print() const { -+ print_on(tty); -+} -+ -+void CompactibleFreeListSpace::prepare_for_verify() { -+ assert_locked(); -+ repairLinearAllocationBlocks(); -+ // Verify that the SpoolBlocks look like free blocks of -+ // appropriate sizes... To be done ... -+} -+ -+class VerifyAllBlksClosure: public BlkClosure { -+ private: -+ const CompactibleFreeListSpace* _sp; -+ const MemRegion _span; -+ HeapWord* _last_addr; -+ size_t _last_size; -+ bool _last_was_obj; -+ bool _last_was_live; -+ -+ public: -+ VerifyAllBlksClosure(const CompactibleFreeListSpace* sp, -+ MemRegion span) : _sp(sp), _span(span), -+ _last_addr(NULL), _last_size(0), -+ _last_was_obj(false), _last_was_live(false) { } -+ -+ virtual size_t do_blk(HeapWord* addr) { -+ size_t res; -+ bool was_obj = false; -+ bool was_live = false; -+ if (_sp->block_is_obj(addr)) { -+ was_obj = true; -+ oop p = oop(addr); -+ guarantee(oopDesc::is_oop(p), "Should be an oop"); -+ res = _sp->adjustObjectSize(p->size()); -+ if (_sp->obj_is_alive(addr)) { -+ was_live = true; -+ p->verify(); -+ } -+ } else { -+ FreeChunk* fc = (FreeChunk*)addr; -+ res = fc->size(); -+ if (FLSVerifyLists && !fc->cantCoalesce()) { -+ guarantee(_sp->verify_chunk_in_free_list(fc), -+ "Chunk should be on a free list"); -+ } -+ } -+ if (res == 0) { -+ Log(gc, verify) log; -+ log.error("Livelock: no rank reduction!"); -+ log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n" -+ " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n", -+ p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false", -+ p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false"); -+ LogStream ls(log.error()); -+ _sp->print_on(&ls); -+ guarantee(false, "Verification failed."); -+ } -+ _last_addr = addr; -+ _last_size = res; -+ _last_was_obj = was_obj; -+ _last_was_live = was_live; -+ return res; -+ } -+}; -+ -+class VerifyAllOopsClosure: public BasicOopIterateClosure { -+ private: -+ const CMSCollector* _collector; -+ const CompactibleFreeListSpace* _sp; -+ const MemRegion _span; -+ const bool _past_remark; -+ const CMSBitMap* _bit_map; -+ -+ protected: -+ void do_oop(void* p, oop obj) { -+ if (_span.contains(obj)) { // the interior oop points into CMS heap -+ if (!_span.contains(p)) { // reference from outside CMS heap -+ // Should be a valid object; the first disjunct below allows -+ // us to sidestep an assertion in block_is_obj() that insists -+ // that p be in _sp. Note that several generations (and spaces) -+ // are spanned by _span (CMS heap) above. -+ guarantee(!_sp->is_in_reserved(obj) || -+ _sp->block_is_obj((HeapWord*)obj), -+ "Should be an object"); -+ guarantee(oopDesc::is_oop(obj), "Should be an oop"); -+ obj->verify(); -+ if (_past_remark) { -+ // Remark has been completed, the object should be marked -+ _bit_map->isMarked((HeapWord*)obj); -+ } -+ } else { // reference within CMS heap -+ if (_past_remark) { -+ // Remark has been completed -- so the referent should have -+ // been marked, if referring object is. -+ if (_bit_map->isMarked(_collector->block_start(p))) { -+ guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?"); -+ } -+ } -+ } -+ } else if (_sp->is_in_reserved(p)) { -+ // the reference is from FLS, and points out of FLS -+ guarantee(oopDesc::is_oop(obj), "Should be an oop"); -+ obj->verify(); -+ } -+ } -+ -+ template void do_oop_work(T* p) { -+ T heap_oop = RawAccess<>::oop_load(p); -+ if (!CompressedOops::is_null(heap_oop)) { -+ oop obj = CompressedOops::decode_not_null(heap_oop); -+ do_oop(p, obj); -+ } -+ } -+ -+ public: -+ VerifyAllOopsClosure(const CMSCollector* collector, -+ const CompactibleFreeListSpace* sp, MemRegion span, -+ bool past_remark, CMSBitMap* bit_map) : -+ _collector(collector), _sp(sp), _span(span), -+ _past_remark(past_remark), _bit_map(bit_map) { } -+ -+ virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); } -+ virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); } -+}; -+ -+void CompactibleFreeListSpace::verify() const { -+ assert_lock_strong(&_freelistLock); -+ verify_objects_initialized(); -+ MemRegion span = _collector->_span; -+ bool past_remark = (_collector->abstract_state() == -+ CMSCollector::Sweeping); -+ -+ ResourceMark rm; -+ HandleMark hm; -+ -+ // Check integrity of CFL data structures -+ _promoInfo.verify(); -+ _dictionary->verify(); -+ if (FLSVerifyIndexTable) { -+ verifyIndexedFreeLists(); -+ } -+ // Check integrity of all objects and free blocks in space -+ { -+ VerifyAllBlksClosure cl(this, span); -+ ((CompactibleFreeListSpace*)this)->blk_iterate(&cl); // cast off const -+ } -+ // Check that all references in the heap to FLS -+ // are to valid objects in FLS or that references in -+ // FLS are to valid objects elsewhere in the heap -+ if (FLSVerifyAllHeapReferences) -+ { -+ VerifyAllOopsClosure cl(_collector, this, span, past_remark, -+ _collector->markBitMap()); -+ -+ // Iterate over all oops in the heap. -+ CMSHeap::heap()->oop_iterate(&cl); -+ } -+ -+ if (VerifyObjectStartArray) { -+ // Verify the block offset table -+ _bt.verify(); -+ } -+} -+ -+#ifndef PRODUCT -+void CompactibleFreeListSpace::verifyFreeLists() const { -+ if (FLSVerifyLists) { -+ _dictionary->verify(); -+ verifyIndexedFreeLists(); -+ } else { -+ if (FLSVerifyDictionary) { -+ _dictionary->verify(); -+ } -+ if (FLSVerifyIndexTable) { -+ verifyIndexedFreeLists(); -+ } -+ } -+} -+#endif -+ -+void CompactibleFreeListSpace::verifyIndexedFreeLists() const { -+ size_t i = 0; -+ for (; i < IndexSetStart; i++) { -+ guarantee(_indexedFreeList[i].head() == NULL, "should be NULL"); -+ } -+ for (; i < IndexSetSize; i++) { -+ verifyIndexedFreeList(i); -+ } -+} -+ -+void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { -+ FreeChunk* fc = _indexedFreeList[size].head(); -+ FreeChunk* tail = _indexedFreeList[size].tail(); -+ size_t num = _indexedFreeList[size].count(); -+ size_t n = 0; -+ guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, -+ "Slot should have been empty"); -+ for (; fc != NULL; fc = fc->next(), n++) { -+ guarantee(fc->size() == size, "Size inconsistency"); -+ guarantee(fc->is_free(), "!free?"); -+ guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); -+ guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); -+ } -+ guarantee(n == num, "Incorrect count"); -+} -+ -+#ifndef PRODUCT -+void CompactibleFreeListSpace::check_free_list_consistency() const { -+ assert((TreeChunk >::min_size() <= IndexSetSize), -+ "Some sizes can't be allocated without recourse to" -+ " linear allocation buffers"); -+ assert((TreeChunk >::min_size()*HeapWordSize == sizeof(TreeChunk >)), -+ "else MIN_TREE_CHUNK_SIZE is wrong"); -+ assert(IndexSetStart != 0, "IndexSetStart not initialized"); -+ assert(IndexSetStride != 0, "IndexSetStride not initialized"); -+} -+#endif -+ -+void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { -+ assert_lock_strong(&_freelistLock); -+ LogTarget(Debug, gc, freelist, census) log; -+ if (!log.is_enabled()) { -+ return; -+ } -+ AdaptiveFreeList total; -+ log.print("end sweep# " SIZE_FORMAT, sweep_count); -+ ResourceMark rm; -+ LogStream ls(log); -+ outputStream* out = &ls; -+ AdaptiveFreeList::print_labels_on(out, "size"); -+ size_t total_free = 0; -+ for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -+ const AdaptiveFreeList *fl = &_indexedFreeList[i]; -+ total_free += fl->count() * fl->size(); -+ if (i % (40*IndexSetStride) == 0) { -+ AdaptiveFreeList::print_labels_on(out, "size"); -+ } -+ fl->print_on(out); -+ total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); -+ total.set_surplus( total.surplus() + fl->surplus() ); -+ total.set_desired( total.desired() + fl->desired() ); -+ total.set_prev_sweep( total.prev_sweep() + fl->prev_sweep() ); -+ total.set_before_sweep(total.before_sweep() + fl->before_sweep()); -+ total.set_count( total.count() + fl->count() ); -+ total.set_coal_births( total.coal_births() + fl->coal_births() ); -+ total.set_coal_deaths( total.coal_deaths() + fl->coal_deaths() ); -+ total.set_split_births(total.split_births() + fl->split_births()); -+ total.set_split_deaths(total.split_deaths() + fl->split_deaths()); -+ } -+ total.print_on(out, "TOTAL"); -+ log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free); -+ log.print("growth: %8.5f deficit: %8.5f", -+ (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ -+ (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), -+ (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); -+ _dictionary->print_dict_census(out); -+} -+ -+/////////////////////////////////////////////////////////////////////////// -+// CompactibleFreeListSpaceLAB -+/////////////////////////////////////////////////////////////////////////// -+ -+#define VECTOR_257(x) \ -+ /* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \ -+ { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -+ x } -+ -+// Initialize with default setting for CMS, _not_ -+// generic OldPLABSize, whose static default is different; if overridden at the -+// command-line, this will get reinitialized via a call to -+// modify_initialization() below. -+AdaptiveWeightedAverage CompactibleFreeListSpaceLAB::_blocks_to_claim[] = -+ VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CompactibleFreeListSpaceLAB::_default_dynamic_old_plab_size)); -+size_t CompactibleFreeListSpaceLAB::_global_num_blocks[] = VECTOR_257(0); -+uint CompactibleFreeListSpaceLAB::_global_num_workers[] = VECTOR_257(0); -+ -+CompactibleFreeListSpaceLAB::CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls) : -+ _cfls(cfls) -+{ -+ assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above"); -+ for (size_t i = CompactibleFreeListSpace::IndexSetStart; -+ i < CompactibleFreeListSpace::IndexSetSize; -+ i += CompactibleFreeListSpace::IndexSetStride) { -+ _indexedFreeList[i].set_size(i); -+ _num_blocks[i] = 0; -+ } -+} -+ -+static bool _CFLS_LAB_modified = false; -+ -+void CompactibleFreeListSpaceLAB::modify_initialization(size_t n, unsigned wt) { -+ assert(!_CFLS_LAB_modified, "Call only once"); -+ _CFLS_LAB_modified = true; -+ for (size_t i = CompactibleFreeListSpace::IndexSetStart; -+ i < CompactibleFreeListSpace::IndexSetSize; -+ i += CompactibleFreeListSpace::IndexSetStride) { -+ _blocks_to_claim[i].modify(n, wt, true /* force */); -+ } -+} -+ -+HeapWord* CompactibleFreeListSpaceLAB::alloc(size_t word_sz) { -+ FreeChunk* res; -+ assert(word_sz == _cfls->adjustObjectSize(word_sz), "Error"); -+ if (word_sz >= CompactibleFreeListSpace::IndexSetSize) { -+ // This locking manages sync with other large object allocations. -+ MutexLockerEx x(_cfls->parDictionaryAllocLock(), -+ Mutex::_no_safepoint_check_flag); -+ res = _cfls->getChunkFromDictionaryExact(word_sz); -+ if (res == NULL) return NULL; -+ } else { -+ AdaptiveFreeList* fl = &_indexedFreeList[word_sz]; -+ if (fl->count() == 0) { -+ // Attempt to refill this local free list. -+ get_from_global_pool(word_sz, fl); -+ // If it didn't work, give up. -+ if (fl->count() == 0) return NULL; -+ } -+ res = fl->get_chunk_at_head(); -+ assert(res != NULL, "Why was count non-zero?"); -+ } -+ res->markNotFree(); -+ assert(!res->is_free(), "shouldn't be marked free"); -+ assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); -+ // mangle a just allocated object with a distinct pattern. -+ debug_only(res->mangleAllocated(word_sz)); -+ return (HeapWord*)res; -+} -+ -+// Get a chunk of blocks of the right size and update related -+// book-keeping stats -+void CompactibleFreeListSpaceLAB::get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl) { -+ // Get the #blocks we want to claim -+ size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); -+ assert(n_blks > 0, "Error"); -+ assert(ResizeOldPLAB || n_blks == OldPLABSize, "Error"); -+ // In some cases, when the application has a phase change, -+ // there may be a sudden and sharp shift in the object survival -+ // profile, and updating the counts at the end of a scavenge -+ // may not be quick enough, giving rise to large scavenge pauses -+ // during these phase changes. It is beneficial to detect such -+ // changes on-the-fly during a scavenge and avoid such a phase-change -+ // pothole. The following code is a heuristic attempt to do that. -+ // It is protected by a product flag until we have gained -+ // enough experience with this heuristic and fine-tuned its behavior. -+ // WARNING: This might increase fragmentation if we overreact to -+ // small spikes, so some kind of historical smoothing based on -+ // previous experience with the greater reactivity might be useful. -+ // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by -+ // default. -+ if (ResizeOldPLAB && CMSOldPLABResizeQuicker) { -+ // -+ // On a 32-bit VM, the denominator can become zero because of integer overflow, -+ // which is why there is a cast to double. -+ // -+ size_t multiple = (size_t) (_num_blocks[word_sz]/(((double)CMSOldPLABToleranceFactor)*CMSOldPLABNumRefills*n_blks)); -+ n_blks += CMSOldPLABReactivityFactor*multiple*n_blks; -+ n_blks = MIN2(n_blks, CMSOldPLABMax); -+ } -+ assert(n_blks > 0, "Error"); -+ _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl); -+ // Update stats table entry for this block size -+ _num_blocks[word_sz] += fl->count(); -+} -+ -+void CompactibleFreeListSpaceLAB::compute_desired_plab_size() { -+ for (size_t i = CompactibleFreeListSpace::IndexSetStart; -+ i < CompactibleFreeListSpace::IndexSetSize; -+ i += CompactibleFreeListSpace::IndexSetStride) { -+ assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0), -+ "Counter inconsistency"); -+ if (_global_num_workers[i] > 0) { -+ // Need to smooth wrt historical average -+ if (ResizeOldPLAB) { -+ _blocks_to_claim[i].sample( -+ MAX2(CMSOldPLABMin, -+ MIN2(CMSOldPLABMax, -+ _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills))); -+ } -+ // Reset counters for next round -+ _global_num_workers[i] = 0; -+ _global_num_blocks[i] = 0; -+ log_trace(gc, plab)("[" SIZE_FORMAT "]: " SIZE_FORMAT, i, (size_t)_blocks_to_claim[i].average()); -+ } -+ } -+} -+ -+// If this is changed in the future to allow parallel -+// access, one would need to take the FL locks and, -+// depending on how it is used, stagger access from -+// parallel threads to reduce contention. -+void CompactibleFreeListSpaceLAB::retire(int tid) { -+ // We run this single threaded with the world stopped; -+ // so no need for locks and such. -+ NOT_PRODUCT(Thread* t = Thread::current();) -+ assert(Thread::current()->is_VM_thread(), "Error"); -+ for (size_t i = CompactibleFreeListSpace::IndexSetStart; -+ i < CompactibleFreeListSpace::IndexSetSize; -+ i += CompactibleFreeListSpace::IndexSetStride) { -+ assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), -+ "Can't retire more than what we obtained"); -+ if (_num_blocks[i] > 0) { -+ size_t num_retire = _indexedFreeList[i].count(); -+ assert(_num_blocks[i] > num_retire, "Should have used at least one"); -+ { -+ // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], -+ // Mutex::_no_safepoint_check_flag); -+ -+ // Update globals stats for num_blocks used -+ _global_num_blocks[i] += (_num_blocks[i] - num_retire); -+ _global_num_workers[i]++; -+ assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); -+ if (num_retire > 0) { -+ _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); -+ // Reset this list. -+ _indexedFreeList[i] = AdaptiveFreeList(); -+ _indexedFreeList[i].set_size(i); -+ } -+ } -+ log_trace(gc, plab)("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT, -+ tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); -+ // Reset stats for next round -+ _num_blocks[i] = 0; -+ } -+ } -+} -+ -+// Used by par_get_chunk_of_blocks() for the chunks from the -+// indexed_free_lists. Looks for a chunk with size that is a multiple -+// of "word_sz" and if found, splits it into "word_sz" chunks and add -+// to the free list "fl". "n" is the maximum number of chunks to -+// be added to "fl". -+bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl) { -+ -+ // We'll try all multiples of word_sz in the indexed set, starting with -+ // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, -+ // then try getting a big chunk and splitting it. -+ { -+ bool found; -+ int k; -+ size_t cur_sz; -+ for (k = 1, cur_sz = k * word_sz, found = false; -+ (cur_sz < CompactibleFreeListSpace::IndexSetSize) && -+ (CMSSplitIndexedFreeListBlocks || k <= 1); -+ k++, cur_sz = k * word_sz) { -+ AdaptiveFreeList fl_for_cur_sz; // Empty. -+ fl_for_cur_sz.set_size(cur_sz); -+ { -+ MutexLockerEx x(_indexedFreeListParLocks[cur_sz], -+ Mutex::_no_safepoint_check_flag); -+ AdaptiveFreeList* gfl = &_indexedFreeList[cur_sz]; -+ if (gfl->count() != 0) { -+ // nn is the number of chunks of size cur_sz that -+ // we'd need to split k-ways each, in order to create -+ // "n" chunks of size word_sz each. -+ const size_t nn = MAX2(n/k, (size_t)1); -+ gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); -+ found = true; -+ if (k > 1) { -+ // Update split death stats for the cur_sz-size blocks list: -+ // we increment the split death count by the number of blocks -+ // we just took from the cur_sz-size blocks list and which -+ // we will be splitting below. -+ ssize_t deaths = gfl->split_deaths() + -+ fl_for_cur_sz.count(); -+ gfl->set_split_deaths(deaths); -+ } -+ } -+ } -+ // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. -+ if (found) { -+ if (k == 1) { -+ fl->prepend(&fl_for_cur_sz); -+ } else { -+ // Divide each block on fl_for_cur_sz up k ways. -+ FreeChunk* fc; -+ while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) { -+ // Must do this in reverse order, so that anybody attempting to -+ // access the main chunk sees it as a single free block until we -+ // change it. -+ size_t fc_size = fc->size(); -+ assert(fc->is_free(), "Error"); -+ for (int i = k-1; i >= 0; i--) { -+ FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); -+ assert((i != 0) || -+ ((fc == ffc) && ffc->is_free() && -+ (ffc->size() == k*word_sz) && (fc_size == word_sz)), -+ "Counting error"); -+ ffc->set_size(word_sz); -+ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -+ ffc->link_next(NULL); -+ // Above must occur before BOT is updated below. -+ OrderAccess::storestore(); -+ // splitting from the right, fc_size == i * word_sz -+ _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); -+ fc_size -= word_sz; -+ assert(fc_size == i*word_sz, "Error"); -+ _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); -+ _bt.verify_single_block((HeapWord*)fc, fc_size); -+ _bt.verify_single_block((HeapWord*)ffc, word_sz); -+ // Push this on "fl". -+ fl->return_chunk_at_head(ffc); -+ } -+ // TRAP -+ assert(fl->tail()->next() == NULL, "List invariant."); -+ } -+ } -+ // Update birth stats for this block size. -+ size_t num = fl->count(); -+ MutexLockerEx x(_indexedFreeListParLocks[word_sz], -+ Mutex::_no_safepoint_check_flag); -+ ssize_t births = _indexedFreeList[word_sz].split_births() + num; -+ _indexedFreeList[word_sz].set_split_births(births); -+ return true; -+ } -+ } -+ return found; -+ } -+} -+ -+FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { -+ -+ FreeChunk* fc = NULL; -+ FreeChunk* rem_fc = NULL; -+ size_t rem; -+ { -+ MutexLockerEx x(parDictionaryAllocLock(), -+ Mutex::_no_safepoint_check_flag); -+ while (n > 0) { -+ fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size())); -+ if (fc != NULL) { -+ break; -+ } else { -+ n--; -+ } -+ } -+ if (fc == NULL) return NULL; -+ // Otherwise, split up that block. -+ assert((ssize_t)n >= 1, "Control point invariant"); -+ assert(fc->is_free(), "Error: should be a free block"); -+ _bt.verify_single_block((HeapWord*)fc, fc->size()); -+ const size_t nn = fc->size() / word_sz; -+ n = MIN2(nn, n); -+ assert((ssize_t)n >= 1, "Control point invariant"); -+ rem = fc->size() - n * word_sz; -+ // If there is a remainder, and it's too small, allocate one fewer. -+ if (rem > 0 && rem < MinChunkSize) { -+ n--; rem += word_sz; -+ } -+ // Note that at this point we may have n == 0. -+ assert((ssize_t)n >= 0, "Control point invariant"); -+ -+ // If n is 0, the chunk fc that was found is not large -+ // enough to leave a viable remainder. We are unable to -+ // allocate even one block. Return fc to the -+ // dictionary and return, leaving "fl" empty. -+ if (n == 0) { -+ returnChunkToDictionary(fc); -+ return NULL; -+ } -+ -+ _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk -+ dictionary()->dict_census_update(fc->size(), -+ true /*split*/, -+ false /*birth*/); -+ -+ // First return the remainder, if any. -+ // Note that we hold the lock until we decide if we're going to give -+ // back the remainder to the dictionary, since a concurrent allocation -+ // may otherwise see the heap as empty. (We're willing to take that -+ // hit if the block is a small block.) -+ if (rem > 0) { -+ size_t prefix_size = n * word_sz; -+ rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); -+ rem_fc->set_size(rem); -+ rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -+ rem_fc->link_next(NULL); -+ // Above must occur before BOT is updated below. -+ assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); -+ OrderAccess::storestore(); -+ _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); -+ assert(fc->is_free(), "Error"); -+ fc->set_size(prefix_size); -+ if (rem >= IndexSetSize) { -+ returnChunkToDictionary(rem_fc); -+ dictionary()->dict_census_update(rem, true /*split*/, true /*birth*/); -+ rem_fc = NULL; -+ } -+ // Otherwise, return it to the small list below. -+ } -+ } -+ if (rem_fc != NULL) { -+ MutexLockerEx x(_indexedFreeListParLocks[rem], -+ Mutex::_no_safepoint_check_flag); -+ _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); -+ _indexedFreeList[rem].return_chunk_at_head(rem_fc); -+ smallSplitBirth(rem); -+ } -+ assert(n * word_sz == fc->size(), -+ "Chunk size " SIZE_FORMAT " is not exactly splittable by " -+ SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, -+ fc->size(), n, word_sz); -+ return fc; -+} -+ -+void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList* fl) { -+ -+ FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); -+ -+ if (fc == NULL) { -+ return; -+ } -+ -+ size_t n = fc->size() / word_sz; -+ -+ assert((ssize_t)n > 0, "Consistency"); -+ // Now do the splitting up. -+ // Must do this in reverse order, so that anybody attempting to -+ // access the main chunk sees it as a single free block until we -+ // change it. -+ size_t fc_size = n * word_sz; -+ // All but first chunk in this loop -+ for (ssize_t i = n-1; i > 0; i--) { -+ FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); -+ ffc->set_size(word_sz); -+ ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -+ ffc->link_next(NULL); -+ // Above must occur before BOT is updated below. -+ OrderAccess::storestore(); -+ // splitting from the right, fc_size == (n - i + 1) * wordsize -+ _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); -+ fc_size -= word_sz; -+ _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); -+ _bt.verify_single_block((HeapWord*)ffc, ffc->size()); -+ _bt.verify_single_block((HeapWord*)fc, fc_size); -+ // Push this on "fl". -+ fl->return_chunk_at_head(ffc); -+ } -+ // First chunk -+ assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block"); -+ // The blocks above should show their new sizes before the first block below -+ fc->set_size(word_sz); -+ fc->link_prev(NULL); // idempotent wrt free-ness, see assert above -+ fc->link_next(NULL); -+ _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -+ _bt.verify_single_block((HeapWord*)fc, fc->size()); -+ fl->return_chunk_at_head(fc); -+ -+ assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); -+ { -+ // Update the stats for this block size. -+ MutexLockerEx x(_indexedFreeListParLocks[word_sz], -+ Mutex::_no_safepoint_check_flag); -+ const ssize_t births = _indexedFreeList[word_sz].split_births() + n; -+ _indexedFreeList[word_sz].set_split_births(births); -+ // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; -+ // _indexedFreeList[word_sz].set_surplus(new_surplus); -+ } -+ -+ // TRAP -+ assert(fl->tail()->next() == NULL, "List invariant."); -+} -+ -+void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { -+ assert(fl->count() == 0, "Precondition."); -+ assert(word_sz < CompactibleFreeListSpace::IndexSetSize, -+ "Precondition"); -+ -+ if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { -+ // Got it -+ return; -+ } -+ -+ // Otherwise, we'll split a block from the dictionary. -+ par_get_chunk_of_blocks_dictionary(word_sz, n, fl); -+} -+ -+const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { -+ const size_t ergo_max = _old_gen->reserved().word_size() / (CardTable::card_size_in_words * BitsPerWord); -+ return ergo_max; -+} -+ -+// Set up the space's par_seq_tasks structure for work claiming -+// for parallel rescan. See CMSParRemarkTask where this is currently used. -+// XXX Need to suitably abstract and generalize this and the next -+// method into one. -+void -+CompactibleFreeListSpace:: -+initialize_sequential_subtasks_for_rescan(int n_threads) { -+ // The "size" of each task is fixed according to rescan_task_size. -+ assert(n_threads > 0, "Unexpected n_threads argument"); -+ const size_t task_size = rescan_task_size(); -+ size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size; -+ assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect"); -+ assert(n_tasks == 0 || -+ ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) && -+ (used_region().start() + n_tasks*task_size >= used_region().end())), -+ "n_tasks calculation incorrect"); -+ SequentialSubTasksDone* pst = conc_par_seq_tasks(); -+ assert(!pst->valid(), "Clobbering existing data?"); -+ // Sets the condition for completion of the subtask (how many threads -+ // need to finish in order to be done). -+ pst->set_n_threads(n_threads); -+ pst->set_n_tasks((int)n_tasks); -+} -+ -+// Set up the space's par_seq_tasks structure for work claiming -+// for parallel concurrent marking. See CMSConcMarkTask where this is currently used. -+void -+CompactibleFreeListSpace:: -+initialize_sequential_subtasks_for_marking(int n_threads, -+ HeapWord* low) { -+ // The "size" of each task is fixed according to rescan_task_size. -+ assert(n_threads > 0, "Unexpected n_threads argument"); -+ const size_t task_size = marking_task_size(); -+ assert(task_size > CardTable::card_size_in_words && -+ (task_size % CardTable::card_size_in_words == 0), -+ "Otherwise arithmetic below would be incorrect"); -+ MemRegion span = _old_gen->reserved(); -+ if (low != NULL) { -+ if (span.contains(low)) { -+ // Align low down to a card boundary so that -+ // we can use block_offset_careful() on span boundaries. -+ HeapWord* aligned_low = align_down(low, CardTable::card_size); -+ // Clip span prefix at aligned_low -+ span = span.intersection(MemRegion(aligned_low, span.end())); -+ } else if (low > span.end()) { -+ span = MemRegion(low, low); // Null region -+ } // else use entire span -+ } -+ assert(span.is_empty() || -+ ((uintptr_t)span.start() % CardTable::card_size == 0), -+ "span should start at a card boundary"); -+ size_t n_tasks = (span.word_size() + task_size - 1)/task_size; -+ assert((n_tasks == 0) == span.is_empty(), "Inconsistency"); -+ assert(n_tasks == 0 || -+ ((span.start() + (n_tasks - 1)*task_size < span.end()) && -+ (span.start() + n_tasks*task_size >= span.end())), -+ "n_tasks calculation incorrect"); -+ SequentialSubTasksDone* pst = conc_par_seq_tasks(); -+ assert(!pst->valid(), "Clobbering existing data?"); -+ // Sets the condition for completion of the subtask (how many threads -+ // need to finish in order to be done). -+ pst->set_n_threads(n_threads); -+ pst->set_n_tasks((int)n_tasks); -+} -diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp -new file mode 100644 -index 00000000000..9fd2ea58320 ---- /dev/null -+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp -@@ -0,0 +1,759 @@ -+/* -+ * Copyright (c) 2001, 2018, 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_CMS_COMPACTIBLEFREELISTSPACE_HPP -+#define SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP -+ -+#include "gc/cms/adaptiveFreeList.hpp" -+#include "gc/cms/promotionInfo.hpp" -+#include "gc/shared/blockOffsetTable.hpp" -+#include "gc/shared/cardTable.hpp" -+#include "gc/shared/space.hpp" -+#include "logging/log.hpp" -+#include "memory/binaryTreeDictionary.hpp" -+#include "memory/freeList.hpp" -+ -+// Classes in support of keeping track of promotions into a non-Contiguous -+// space, in this case a CompactibleFreeListSpace. -+ -+// Forward declarations -+class CMSCollector; -+class CompactibleFreeListSpace; -+class ConcurrentMarkSweepGeneration; -+class BlkClosure; -+class BlkClosureCareful; -+class FreeChunk; -+class UpwardsObjectClosure; -+class ObjectClosureCareful; -+class Klass; -+ -+class AFLBinaryTreeDictionary : public BinaryTreeDictionary > { -+ public: -+ AFLBinaryTreeDictionary(MemRegion mr) -+ : BinaryTreeDictionary >(mr) {} -+ -+ // Find the list with size "size" in the binary tree and update -+ // the statistics in the list according to "split" (chunk was -+ // split or coalesce) and "birth" (chunk was added or removed). -+ void dict_census_update(size_t size, bool split, bool birth); -+ // Return true if the dictionary is overpopulated (more chunks of -+ // this size than desired) for size "size". -+ bool coal_dict_over_populated(size_t size); -+ // Methods called at the beginning of a sweep to prepare the -+ // statistics for the sweep. -+ void begin_sweep_dict_census(double coalSurplusPercent, -+ float inter_sweep_current, -+ float inter_sweep_estimate, -+ float intra_sweep_estimate); -+ // Methods called after the end of a sweep to modify the -+ // statistics for the sweep. -+ void end_sweep_dict_census(double splitSurplusPercent); -+ // Accessors for statistics -+ void set_tree_surplus(double splitSurplusPercent); -+ void set_tree_hints(void); -+ // Reset statistics for all the lists in the tree. -+ void clear_tree_census(void); -+ // Print the statistics for all the lists in the tree. Also may -+ // print out summaries. -+ void print_dict_census(outputStream* st) const; -+}; -+ -+class LinearAllocBlock { -+ public: -+ LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), -+ _allocation_size_limit(0) {} -+ void set(HeapWord* ptr, size_t word_size, size_t refill_size, -+ size_t allocation_size_limit) { -+ _ptr = ptr; -+ _word_size = word_size; -+ _refillSize = refill_size; -+ _allocation_size_limit = allocation_size_limit; -+ } -+ HeapWord* _ptr; -+ size_t _word_size; -+ size_t _refillSize; -+ size_t _allocation_size_limit; // Largest size that will be allocated -+ -+ void print_on(outputStream* st) const; -+}; -+ -+// Concrete subclass of CompactibleSpace that implements -+// a free list space, such as used in the concurrent mark sweep -+// generation. -+ -+class CompactibleFreeListSpace: public CompactibleSpace { -+ friend class VMStructs; -+ friend class ConcurrentMarkSweepGeneration; -+ friend class CMSCollector; -+ // Local alloc buffer for promotion into this space. -+ friend class CompactibleFreeListSpaceLAB; -+ // Allow scan_and_* functions to call (private) overrides of the auxiliary functions on this class -+ template -+ friend void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space); -+ template -+ friend void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run); -+ template -+ friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); -+ template -+ friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); -+ -+ // "Size" of chunks of work (executed during parallel remark phases -+ // of CMS collection); this probably belongs in CMSCollector, although -+ // it's cached here because it's used in -+ // initialize_sequential_subtasks_for_rescan() which modifies -+ // par_seq_tasks which also lives in Space. XXX -+ const size_t _rescan_task_size; -+ const size_t _marking_task_size; -+ -+ // Yet another sequential tasks done structure. This supports -+ // CMS GC, where we have threads dynamically -+ // claiming sub-tasks from a larger parallel task. -+ SequentialSubTasksDone _conc_par_seq_tasks; -+ -+ BlockOffsetArrayNonContigSpace _bt; -+ -+ CMSCollector* _collector; -+ ConcurrentMarkSweepGeneration* _old_gen; -+ -+ // Data structures for free blocks (used during allocation/sweeping) -+ -+ // Allocation is done linearly from two different blocks depending on -+ // whether the request is small or large, in an effort to reduce -+ // fragmentation. We assume that any locking for allocation is done -+ // by the containing generation. Thus, none of the methods in this -+ // space are re-entrant. -+ enum SomeConstants { -+ SmallForLinearAlloc = 16, // size < this then use _sLAB -+ SmallForDictionary = 257, // size < this then use _indexedFreeList -+ IndexSetSize = SmallForDictionary // keep this odd-sized -+ }; -+ static size_t IndexSetStart; -+ static size_t IndexSetStride; -+ static size_t _min_chunk_size_in_bytes; -+ -+ private: -+ enum FitStrategyOptions { -+ FreeBlockStrategyNone = 0, -+ FreeBlockBestFitFirst -+ }; -+ -+ PromotionInfo _promoInfo; -+ -+ // Helps to impose a global total order on freelistLock ranks; -+ // assumes that CFLSpace's are allocated in global total order -+ static int _lockRank; -+ -+ // A lock protecting the free lists and free blocks; -+ // mutable because of ubiquity of locking even for otherwise const methods -+ mutable Mutex _freelistLock; -+ -+ // Locking verifier convenience function -+ void assert_locked() const PRODUCT_RETURN; -+ void assert_locked(const Mutex* lock) const PRODUCT_RETURN; -+ -+ // Linear allocation blocks -+ LinearAllocBlock _smallLinearAllocBlock; -+ -+ AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks -+ -+ // Indexed array for small size blocks -+ AdaptiveFreeList _indexedFreeList[IndexSetSize]; -+ -+ // Allocation strategy -+ bool _fitStrategy; // Use best fit strategy -+ -+ // This is an address close to the largest free chunk in the heap. -+ // It is currently assumed to be at the end of the heap. Free -+ // chunks with addresses greater than nearLargestChunk are coalesced -+ // in an effort to maintain a large chunk at the end of the heap. -+ HeapWord* _nearLargestChunk; -+ -+ // Used to keep track of limit of sweep for the space -+ HeapWord* _sweep_limit; -+ -+ // Stable value of used(). -+ size_t _used_stable; -+ -+ // Used to make the young collector update the mod union table -+ MemRegionClosure* _preconsumptionDirtyCardClosure; -+ -+ // Support for compacting cms -+ HeapWord* cross_threshold(HeapWord* start, HeapWord* end); -+ HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); -+ HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); -+ -+ // Initialization helpers. -+ void initializeIndexedFreeListArray(); -+ -+ // Extra stuff to manage promotion parallelism. -+ -+ // A lock protecting the dictionary during par promotion allocation. -+ mutable Mutex _parDictionaryAllocLock; -+ Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } -+ -+ // Locks protecting the exact lists during par promotion allocation. -+ Mutex* _indexedFreeListParLocks[IndexSetSize]; -+ -+ // Attempt to obtain up to "n" blocks of the size "word_sz" (which is -+ // required to be smaller than "IndexSetSize".) If successful, -+ // adds them to "fl", which is required to be an empty free list. -+ // If the count of "fl" is negative, it's absolute value indicates a -+ // number of free chunks that had been previously "borrowed" from global -+ // list of size "word_sz", and must now be decremented. -+ void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl); -+ -+ // Used by par_get_chunk_of_blocks() for the chunks from the -+ // indexed_free_lists. -+ bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl); -+ -+ // Used by par_get_chunk_of_blocks_dictionary() to get a chunk -+ // evenly splittable into "n" "word_sz" chunks. Returns that -+ // evenly splittable chunk. May split a larger chunk to get the -+ // evenly splittable chunk. -+ FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); -+ -+ // Used by par_get_chunk_of_blocks() for the chunks from the -+ // dictionary. -+ void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList* fl); -+ -+ // Allocation helper functions -+ // Allocate using a strategy that takes from the indexed free lists -+ // first. This allocation strategy assumes a companion sweeping -+ // strategy that attempts to keep the needed number of chunks in each -+ // indexed free lists. -+ HeapWord* allocate_adaptive_freelists(size_t size); -+ -+ // Gets a chunk from the linear allocation block (LinAB). If there -+ // is not enough space in the LinAB, refills it. -+ HeapWord* getChunkFromLinearAllocBlock(LinearAllocBlock* blk, size_t size); -+ HeapWord* getChunkFromSmallLinearAllocBlock(size_t size); -+ // Get a chunk from the space remaining in the linear allocation block. Do -+ // not attempt to refill if the space is not available, return NULL. Do the -+ // repairs on the linear allocation block as appropriate. -+ HeapWord* getChunkFromLinearAllocBlockRemainder(LinearAllocBlock* blk, size_t size); -+ inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); -+ -+ // Helper function for getChunkFromIndexedFreeList. -+ // Replenish the indexed free list for this "size". Do not take from an -+ // underpopulated size. -+ FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); -+ -+ // Get a chunk from the indexed free list. If the indexed free list -+ // does not have a free chunk, try to replenish the indexed free list -+ // then get the free chunk from the replenished indexed free list. -+ inline FreeChunk* getChunkFromIndexedFreeList(size_t size); -+ -+ // The returned chunk may be larger than requested (or null). -+ FreeChunk* getChunkFromDictionary(size_t size); -+ // The returned chunk is the exact size requested (or null). -+ FreeChunk* getChunkFromDictionaryExact(size_t size); -+ -+ // Find a chunk in the indexed free list that is the best -+ // fit for size "numWords". -+ FreeChunk* bestFitSmall(size_t numWords); -+ // For free list "fl" of chunks of size > numWords, -+ // remove a chunk, split off a chunk of size numWords -+ // and return it. The split off remainder is returned to -+ // the free lists. The old name for getFromListGreater -+ // was lookInListGreater. -+ FreeChunk* getFromListGreater(AdaptiveFreeList* fl, size_t numWords); -+ // Get a chunk in the indexed free list or dictionary, -+ // by considering a larger chunk and splitting it. -+ FreeChunk* getChunkFromGreater(size_t numWords); -+ // Verify that the given chunk is in the indexed free lists. -+ bool verifyChunkInIndexedFreeLists(FreeChunk* fc) const; -+ // Remove the specified chunk from the indexed free lists. -+ void removeChunkFromIndexedFreeList(FreeChunk* fc); -+ // Remove the specified chunk from the dictionary. -+ void removeChunkFromDictionary(FreeChunk* fc); -+ // Split a free chunk into a smaller free chunk of size "new_size". -+ // Return the smaller free chunk and return the remainder to the -+ // free lists. -+ FreeChunk* splitChunkAndReturnRemainder(FreeChunk* chunk, size_t new_size); -+ // Add a chunk to the free lists. -+ void addChunkToFreeLists(HeapWord* chunk, size_t size); -+ // Add a chunk to the free lists, preferring to suffix it -+ // to the last free chunk at end of space if possible, and -+ // updating the block census stats as well as block offset table. -+ // Take any locks as appropriate if we are multithreaded. -+ void addChunkToFreeListsAtEndRecordingStats(HeapWord* chunk, size_t size); -+ // Add a free chunk to the indexed free lists. -+ void returnChunkToFreeList(FreeChunk* chunk); -+ // Add a free chunk to the dictionary. -+ void returnChunkToDictionary(FreeChunk* chunk); -+ -+ // Functions for maintaining the linear allocation buffers (LinAB). -+ // Repairing a linear allocation block refers to operations -+ // performed on the remainder of a LinAB after an allocation -+ // has been made from it. -+ void repairLinearAllocationBlocks(); -+ void repairLinearAllocBlock(LinearAllocBlock* blk); -+ void refillLinearAllocBlock(LinearAllocBlock* blk); -+ void refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk); -+ void refillLinearAllocBlocksIfNeeded(); -+ -+ void verify_objects_initialized() const; -+ -+ // Statistics reporting helper functions -+ void reportFreeListStatistics(const char* title) const; -+ void reportIndexedFreeListStatistics(outputStream* st) const; -+ size_t maxChunkSizeInIndexedFreeLists() const; -+ size_t numFreeBlocksInIndexedFreeLists() const; -+ // Accessor -+ HeapWord* unallocated_block() const { -+ if (BlockOffsetArrayUseUnallocatedBlock) { -+ HeapWord* ub = _bt.unallocated_block(); -+ assert(ub >= bottom() && -+ ub <= end(), "space invariant"); -+ return ub; -+ } else { -+ return end(); -+ } -+ } -+ void freed(HeapWord* start, size_t size) { -+ _bt.freed(start, size); -+ } -+ -+ // Auxiliary functions for scan_and_{forward,adjust_pointers,compact} support. -+ // See comments for CompactibleSpace for more information. -+ inline HeapWord* scan_limit() const { -+ return end(); -+ } -+ -+ inline bool scanned_block_is_obj(const HeapWord* addr) const { -+ return CompactibleFreeListSpace::block_is_obj(addr); // Avoid virtual call -+ } -+ -+ inline size_t scanned_block_size(const HeapWord* addr) const { -+ return CompactibleFreeListSpace::block_size(addr); // Avoid virtual call -+ } -+ -+ inline size_t adjust_obj_size(size_t size) const { -+ return adjustObjectSize(size); -+ } -+ -+ inline size_t obj_size(const HeapWord* addr) const; -+ -+ protected: -+ // Reset the indexed free list to its initial empty condition. -+ void resetIndexedFreeListArray(); -+ // Reset to an initial state with a single free block described -+ // by the MemRegion parameter. -+ void reset(MemRegion mr); -+ // Return the total number of words in the indexed free lists. -+ size_t totalSizeInIndexedFreeLists() const; -+ -+ public: -+ // Constructor -+ CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); -+ // Accessors -+ bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } -+ AFLBinaryTreeDictionary* dictionary() const { return _dictionary; } -+ HeapWord* nearLargestChunk() const { return _nearLargestChunk; } -+ void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; } -+ -+ // Set CMS global values. -+ static void set_cms_values(); -+ -+ // Return the free chunk at the end of the space. If no such -+ // chunk exists, return NULL. -+ FreeChunk* find_chunk_at_end(); -+ -+ void set_collector(CMSCollector* collector) { _collector = collector; } -+ -+ // Support for parallelization of rescan and marking. -+ const size_t rescan_task_size() const { return _rescan_task_size; } -+ const size_t marking_task_size() const { return _marking_task_size; } -+ // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. -+ const size_t max_flag_size_for_task_size() const; -+ SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } -+ void initialize_sequential_subtasks_for_rescan(int n_threads); -+ void initialize_sequential_subtasks_for_marking(int n_threads, -+ HeapWord* low = NULL); -+ -+ virtual MemRegionClosure* preconsumptionDirtyCardClosure() const { -+ return _preconsumptionDirtyCardClosure; -+ } -+ -+ void setPreconsumptionDirtyCardClosure(MemRegionClosure* cl) { -+ _preconsumptionDirtyCardClosure = cl; -+ } -+ -+ // Space enquiries -+ size_t used() const; -+ size_t free() const; -+ size_t max_alloc_in_words() const; -+ // XXX: should have a less conservative used_region() than that of -+ // Space; we could consider keeping track of highest allocated -+ // address and correcting that at each sweep, as the sweeper -+ // goes through the entire allocated part of the generation. We -+ // could also use that information to keep the sweeper from -+ // sweeping more than is necessary. The allocator and sweeper will -+ // of course need to synchronize on this, since the sweeper will -+ // try to bump down the address and the allocator will try to bump it up. -+ // For now, however, we'll just use the default used_region() -+ // which overestimates the region by returning the entire -+ // committed region (this is safe, but inefficient). -+ -+ // Returns monotonically increasing stable used space bytes for CMS. -+ // This is required for jstat and other memory monitoring tools -+ // that might otherwise see inconsistent used space values during a garbage -+ // collection, promotion or allocation into compactibleFreeListSpace. -+ // The value returned by this function might be smaller than the -+ // actual value. -+ size_t used_stable() const; -+ // Recalculate and cache the current stable used() value. Only to be called -+ // in places where we can be sure that the result is stable. -+ void recalculate_used_stable(); -+ -+ // Returns a subregion of the space containing all the objects in -+ // the space. -+ MemRegion used_region() const { -+ return MemRegion(bottom(), -+ BlockOffsetArrayUseUnallocatedBlock ? -+ unallocated_block() : end()); -+ } -+ -+ virtual bool is_free_block(const HeapWord* p) const; -+ -+ // Resizing support -+ void set_end(HeapWord* value); // override -+ -+ // Never mangle CompactibleFreeListSpace -+ void mangle_unused_area() {} -+ void mangle_unused_area_complete() {} -+ -+ // Mutual exclusion support -+ Mutex* freelistLock() const { return &_freelistLock; } -+ -+ // Iteration support -+ void oop_iterate(OopIterateClosure* cl); -+ -+ void object_iterate(ObjectClosure* blk); -+ // Apply the closure to each object in the space whose references -+ // point to objects in the heap. The usage of CompactibleFreeListSpace -+ // by the ConcurrentMarkSweepGeneration for concurrent GC's allows -+ // objects in the space with references to objects that are no longer -+ // valid. For example, an object may reference another object -+ // that has already been sweep up (collected). This method uses -+ // obj_is_alive() to determine whether it is safe to iterate of -+ // an object. -+ void safe_object_iterate(ObjectClosure* blk); -+ -+ // Iterate over all objects that intersect with mr, calling "cl->do_object" -+ // on each. There is an exception to this: if this closure has already -+ // been invoked on an object, it may skip such objects in some cases. This is -+ // Most likely to happen in an "upwards" (ascending address) iteration of -+ // MemRegions. -+ void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); -+ -+ // Requires that "mr" be entirely within the space. -+ // Apply "cl->do_object" to all objects that intersect with "mr". -+ // If the iteration encounters an unparseable portion of the region, -+ // terminate the iteration and return the address of the start of the -+ // subregion that isn't done. Return of "NULL" indicates that the -+ // iteration completed. -+ HeapWord* object_iterate_careful_m(MemRegion mr, -+ ObjectClosureCareful* cl); -+ -+ // Override: provides a DCTO_CL specific to this kind of space. -+ DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, -+ CardTable::PrecisionStyle precision, -+ HeapWord* boundary, -+ bool parallel); -+ -+ void blk_iterate(BlkClosure* cl); -+ void blk_iterate_careful(BlkClosureCareful* cl); -+ HeapWord* block_start_const(const void* p) const; -+ HeapWord* block_start_careful(const void* p) const; -+ size_t block_size(const HeapWord* p) const; -+ size_t block_size_no_stall(HeapWord* p, const CMSCollector* c) const; -+ bool block_is_obj(const HeapWord* p) const; -+ bool obj_is_alive(const HeapWord* p) const; -+ size_t block_size_nopar(const HeapWord* p) const; -+ bool block_is_obj_nopar(const HeapWord* p) const; -+ -+ // Iteration support for promotion -+ void save_marks(); -+ bool no_allocs_since_save_marks(); -+ -+ // Iteration support for sweeping -+ void save_sweep_limit() { -+ _sweep_limit = BlockOffsetArrayUseUnallocatedBlock ? -+ unallocated_block() : end(); -+ log_develop_trace(gc, sweep)(">>>>> Saving sweep limit " PTR_FORMAT -+ " for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<", -+ p2i(_sweep_limit), p2i(bottom()), p2i(end())); -+ } -+ NOT_PRODUCT( -+ void clear_sweep_limit() { _sweep_limit = NULL; } -+ ) -+ HeapWord* sweep_limit() { return _sweep_limit; } -+ -+ // Apply "blk->do_oop" to the addresses of all reference fields in objects -+ // promoted into this generation since the most recent save_marks() call. -+ // Fields in objects allocated by applications of the closure -+ // *are* included in the iteration. Thus, when the iteration completes -+ // there should be no further such objects remaining. -+ template -+ void oop_since_save_marks_iterate(OopClosureType* blk); -+ -+ // Allocation support -+ HeapWord* allocate(size_t size); -+ HeapWord* par_allocate(size_t size); -+ -+ oop promote(oop obj, size_t obj_size); -+ void gc_prologue(); -+ void gc_epilogue(); -+ -+ // This call is used by a containing CMS generation / collector -+ // to inform the CFLS space that a sweep has been completed -+ // and that the space can do any related house-keeping functions. -+ void sweep_completed(); -+ -+ // For an object in this space, the mark-word's two -+ // LSB's having the value [11] indicates that it has been -+ // promoted since the most recent call to save_marks() on -+ // this generation and has not subsequently been iterated -+ // over (using oop_since_save_marks_iterate() above). -+ // This property holds only for single-threaded collections, -+ // and is typically used for Cheney scans; for MT scavenges, -+ // the property holds for all objects promoted during that -+ // scavenge for the duration of the scavenge and is used -+ // by card-scanning to avoid scanning objects (being) promoted -+ // during that scavenge. -+ bool obj_allocated_since_save_marks(const oop obj) const { -+ assert(is_in_reserved(obj), "Wrong space?"); -+ return ((PromotedObject*)obj)->hasPromotedMark(); -+ } -+ -+ // A worst-case estimate of the space required (in HeapWords) to expand the -+ // heap when promoting an obj of size obj_size. -+ size_t expansionSpaceRequired(size_t obj_size) const; -+ -+ FreeChunk* allocateScratch(size_t size); -+ -+ // Returns true if either the small or large linear allocation buffer is empty. -+ bool linearAllocationWouldFail() const; -+ -+ // Adjust the chunk for the minimum size. This version is called in -+ // most cases in CompactibleFreeListSpace methods. -+ inline static size_t adjustObjectSize(size_t size) { -+ return align_object_size(MAX2(size, (size_t)MinChunkSize)); -+ } -+ // This is a virtual version of adjustObjectSize() that is called -+ // only occasionally when the compaction space changes and the type -+ // of the new compaction space is is only known to be CompactibleSpace. -+ size_t adjust_object_size_v(size_t size) const { -+ return adjustObjectSize(size); -+ } -+ // Minimum size of a free block. -+ virtual size_t minimum_free_block_size() const { return MinChunkSize; } -+ void removeFreeChunkFromFreeLists(FreeChunk* chunk); -+ void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, -+ bool coalesced); -+ -+ // Support for compaction. -+ void prepare_for_compaction(CompactPoint* cp); -+ void adjust_pointers(); -+ void compact(); -+ // Reset the space to reflect the fact that a compaction of the -+ // space has been done. -+ virtual void reset_after_compaction(); -+ -+ // Debugging support. -+ void print() const; -+ void print_on(outputStream* st) const; -+ void prepare_for_verify(); -+ void verify() const; -+ void verifyFreeLists() const PRODUCT_RETURN; -+ void verifyIndexedFreeLists() const; -+ void verifyIndexedFreeList(size_t size) const; -+ // Verify that the given chunk is in the free lists: -+ // i.e. either the binary tree dictionary, the indexed free lists -+ // or the linear allocation block. -+ bool verify_chunk_in_free_list(FreeChunk* fc) const; -+ // Verify that the given chunk is the linear allocation block. -+ bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; -+ // Do some basic checks on the the free lists. -+ void check_free_list_consistency() const PRODUCT_RETURN; -+ -+ // Printing support -+ void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); -+ void print_indexed_free_lists(outputStream* st) const; -+ void print_dictionary_free_lists(outputStream* st) const; -+ void print_promo_info_blocks(outputStream* st) const; -+ -+ NOT_PRODUCT ( -+ void initializeIndexedFreeListArrayReturnedBytes(); -+ size_t sumIndexedFreeListArrayReturnedBytes(); -+ // Return the total number of chunks in the indexed free lists. -+ size_t totalCountInIndexedFreeLists() const; -+ // Return the total number of chunks in the space. -+ size_t totalCount(); -+ ) -+ -+ // The census consists of counts of the quantities such as -+ // the current count of the free chunks, number of chunks -+ // created as a result of the split of a larger chunk or -+ // coalescing of smaller chucks, etc. The counts in the -+ // census is used to make decisions on splitting and -+ // coalescing of chunks during the sweep of garbage. -+ -+ // Print the statistics for the free lists. -+ void printFLCensus(size_t sweep_count) const; -+ -+ // Statistics functions -+ // Initialize census for lists before the sweep. -+ void beginSweepFLCensus(float inter_sweep_current, -+ float inter_sweep_estimate, -+ float intra_sweep_estimate); -+ // Set the surplus for each of the free lists. -+ void setFLSurplus(); -+ // Set the hint for each of the free lists. -+ void setFLHints(); -+ // Clear the census for each of the free lists. -+ void clearFLCensus(); -+ // Perform functions for the census after the end of the sweep. -+ void endSweepFLCensus(size_t sweep_count); -+ // Return true if the count of free chunks is greater -+ // than the desired number of free chunks. -+ bool coalOverPopulated(size_t size); -+ -+// Record (for each size): -+// -+// split-births = #chunks added due to splits in (prev-sweep-end, -+// this-sweep-start) -+// split-deaths = #chunks removed for splits in (prev-sweep-end, -+// this-sweep-start) -+// num-curr = #chunks at start of this sweep -+// num-prev = #chunks at end of previous sweep -+// -+// The above are quantities that are measured. Now define: -+// -+// num-desired := num-prev + split-births - split-deaths - num-curr -+// -+// Roughly, num-prev + split-births is the supply, -+// split-deaths is demand due to other sizes -+// and num-curr is what we have left. -+// -+// Thus, num-desired is roughly speaking the "legitimate demand" -+// for blocks of this size and what we are striving to reach at the -+// end of the current sweep. -+// -+// For a given list, let num-len be its current population. -+// Define, for a free list of a given size: -+// -+// coal-overpopulated := num-len >= num-desired * coal-surplus -+// (coal-surplus is set to 1.05, i.e. we allow a little slop when -+// coalescing -- we do not coalesce unless we think that the current -+// supply has exceeded the estimated demand by more than 5%). -+// -+// For the set of sizes in the binary tree, which is neither dense nor -+// closed, it may be the case that for a particular size we have never -+// had, or do not now have, or did not have at the previous sweep, -+// chunks of that size. We need to extend the definition of -+// coal-overpopulated to such sizes as well: -+// -+// For a chunk in/not in the binary tree, extend coal-overpopulated -+// defined above to include all sizes as follows: -+// -+// . a size that is non-existent is coal-overpopulated -+// . a size that has a num-desired <= 0 as defined above is -+// coal-overpopulated. -+// -+// Also define, for a chunk heap-offset C and mountain heap-offset M: -+// -+// close-to-mountain := C >= 0.99 * M -+// -+// Now, the coalescing strategy is: -+// -+// Coalesce left-hand chunk with right-hand chunk if and -+// only if: -+// -+// EITHER -+// . left-hand chunk is of a size that is coal-overpopulated -+// OR -+// . right-hand chunk is close-to-mountain -+ void smallCoalBirth(size_t size); -+ void smallCoalDeath(size_t size); -+ void coalBirth(size_t size); -+ void coalDeath(size_t size); -+ void smallSplitBirth(size_t size); -+ void smallSplitDeath(size_t size); -+ void split_birth(size_t size); -+ void splitDeath(size_t size); -+ void split(size_t from, size_t to1); -+ -+ double flsFrag() const; -+}; -+ -+// A parallel-GC-thread-local allocation buffer for allocation into a -+// CompactibleFreeListSpace. -+class CompactibleFreeListSpaceLAB : public CHeapObj { -+ // The space that this buffer allocates into. -+ CompactibleFreeListSpace* _cfls; -+ -+ // Our local free lists. -+ AdaptiveFreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; -+ -+ // Initialized from a command-line arg. -+ -+ // Allocation statistics in support of dynamic adjustment of -+ // #blocks to claim per get_from_global_pool() call below. -+ static AdaptiveWeightedAverage -+ _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; -+ static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; -+ static uint _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; -+ size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; -+ -+ // Internal work method -+ void get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl); -+ -+public: -+ static const int _default_dynamic_old_plab_size = 16; -+ static const int _default_static_old_plab_size = 50; -+ -+ CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls); -+ -+ // Allocate and return a block of the given size, or else return NULL. -+ HeapWord* alloc(size_t word_sz); -+ -+ // Return any unused portions of the buffer to the global pool. -+ void retire(int tid); -+ -+ // Dynamic OldPLABSize sizing -+ static void compute_desired_plab_size(); -+ // When the settings are modified from default static initialization -+ static void modify_initialization(size_t n, unsigned wt); -+}; -+ -+size_t PromotionInfo::refillSize() const { -+ const size_t CMSSpoolBlockSize = 256; -+ const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) -+ * CMSSpoolBlockSize); -+ return CompactibleFreeListSpace::adjustObjectSize(sz); -+} -+ -+#endif // SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP -diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp -index 28c5990c66e..72f571645a5 100644 ---- a/src/hotspot/share/gc/serial/genMarkSweep.cpp -+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp -@@ -325,10 +325,14 @@ void GenMarkSweep::mark_sweep_phase4() { - // in the same order in phase2, phase3 and phase4. We don't quite do that - // here (perm_gen first rather than last), so we tell the validate code - // to use a higher index (saved from phase2) when verifying perm_gen. -+ assert(_rescued_oops == NULL, "must be empty before processing"); - GenCollectedHeap* gch = GenCollectedHeap::heap(); - - GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer); - -+// MarkSweep::copy_rescued_objects_back(); -+ - GenCompactClosure blk; - gch->generation_iterate(&blk, true); -+ MarkSweep::copy_rescued_objects_back(); - } -diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp -index ebe0da25766..c7befd2f63d 100644 ---- a/src/hotspot/share/gc/serial/markSweep.cpp -+++ b/src/hotspot/share/gc/serial/markSweep.cpp -@@ -57,6 +57,8 @@ ReferenceProcessor* MarkSweep::_ref_processor = NULL; - STWGCTimer* MarkSweep::_gc_timer = NULL; - SerialOldTracer* MarkSweep::_gc_tracer = NULL; - -+GrowableArray* MarkSweep::_rescued_oops = NULL; -+ - MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; - - MarkAndPushClosure MarkSweep::mark_and_push_closure; -@@ -222,3 +224,100 @@ void MarkSweep::initialize() { - MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); - MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); - } -+ -+// (DCEVM) Copy the rescued objects to their destination address after compaction. -+void MarkSweep::copy_rescued_objects_back() { -+ -+ if (_rescued_oops != NULL) { -+ -+ for (int i=0; i<_rescued_oops->length(); i++) { -+ HeapWord* rescued_ptr = _rescued_oops->at(i); -+ oop rescued_obj = (oop) rescued_ptr; -+ -+ int size = rescued_obj->size(); -+ oop new_obj = rescued_obj->forwardee(); -+ -+ assert(rescued_obj->klass()->new_version() != NULL, "just checking"); -+ -+ if (rescued_obj->klass()->new_version()->update_information() != NULL) { -+ MarkSweep::update_fields(rescued_obj, new_obj); -+ } else { -+ rescued_obj->set_klass(rescued_obj->klass()->new_version()); -+ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -+ } -+ -+ FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); -+ -+ new_obj->init_mark(); -+ assert(oopDesc::is_oop(new_obj), "must be a valid oop"); -+ } -+ _rescued_oops->clear(); -+ _rescued_oops = NULL; -+ } -+} -+ -+// (DCEVM) Update instances of a class whose fields changed. -+void MarkSweep::update_fields(oop q, oop new_location) { -+ -+ assert(q->klass()->new_version() != NULL, "class of old object must have new version"); -+ -+ Klass* old_klass_oop = q->klass(); -+ Klass* new_klass_oop = q->klass()->new_version(); -+ -+ InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); -+ InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); -+ -+ int size = q->size_given_klass(old_klass); -+ int new_size = q->size_given_klass(new_klass); -+ -+ HeapWord* tmp = NULL; -+ oop tmp_obj = q; -+ -+ // Save object somewhere, there is an overlap in fields -+ if (new_klass_oop->is_copying_backwards()) { -+ if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || -+ ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { -+ tmp = NEW_RESOURCE_ARRAY(HeapWord, size); -+ q = (oop) tmp; -+ Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); -+ } -+ } -+ -+ q->set_klass(new_klass_oop); -+ int *cur = new_klass_oop->update_information(); -+ assert(cur != NULL, "just checking"); -+ MarkSweep::update_fields(new_location, q, cur); -+ -+ if (tmp != NULL) { -+ FREE_RESOURCE_ARRAY(HeapWord, tmp, size); -+ } -+} -+ -+void MarkSweep::update_fields(oop new_location, oop tmp_obj, int *cur) { -+ assert(cur != NULL, "just checking"); -+ char* to = (char*)(HeapWord*)new_location; -+ while (*cur != 0) { -+ int size = *cur; -+ if (size > 0) { -+ cur++; -+ int offset = *cur; -+ HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); -+ if (size == HeapWordSize) { -+ *((HeapWord*)to) = *from; -+ } else if (size == HeapWordSize * 2) { -+ *((HeapWord*)to) = *from; -+ *(((HeapWord*)to) + 1) = *(from + 1); -+ } else { -+ Copy::conjoint_jbytes(from, to, size); -+ } -+ to += size; -+ cur++; -+ } else { -+ assert(size < 0, ""); -+ int skip = -*cur; -+ Copy::fill_to_bytes(to, skip, 0); -+ to += skip; -+ cur++; -+ } -+ } -+} -diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp -index e9588a527e1..e12ac327d90 100644 ---- a/src/hotspot/share/gc/serial/markSweep.hpp -+++ b/src/hotspot/share/gc/serial/markSweep.hpp -@@ -87,6 +87,10 @@ class MarkSweep : AllStatic { - friend class AdjustPointerClosure; - friend class KeepAliveClosure; - friend class VM_MarkSweep; -+ friend class GenMarkSweep; -+ -+ public: -+ static GrowableArray* _rescued_oops; - - // - // Vars -@@ -144,6 +148,9 @@ class MarkSweep : AllStatic { - - static int adjust_pointers(oop obj); - -+ static void copy_rescued_objects_back(); -+ static void update_fields(oop q, oop new_location); -+ static void update_fields(oop new_location, oop tmp_obj, int *cur); - static void follow_stack(); // Empty marking stack. - - static void follow_klass(Klass* klass); -diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp -index 39d860b20a1..fdb1c806559 100644 ---- a/src/hotspot/share/gc/shared/gcConfig.cpp -+++ b/src/hotspot/share/gc/shared/gcConfig.cpp -@@ -98,7 +98,10 @@ void GCConfig::fail_if_non_included_gc_is_selected() { - } - - void GCConfig::select_gc_ergonomically() { -- if (os::is_server_class_machine()) { -+ if (AllowEnhancedClassRedefinition) { -+ // Enhanced class redefinition only supports serial GC at the moment -+ FLAG_SET_ERGO(bool, UseSerialGC, true); -+ } else if (os::is_server_class_machine()) { - #if INCLUDE_G1GC - FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); - #elif INCLUDE_PARALLELGC -diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp -index 6e215c8e6b7..0fefc5da478 100644 ---- a/src/hotspot/share/gc/shared/space.cpp -+++ b/src/hotspot/share/gc/shared/space.cpp -@@ -350,9 +350,8 @@ void CompactibleSpace::clear(bool mangle_space) { - _compaction_top = bottom(); - } - --HeapWord* CompactibleSpace::forward(oop q, size_t size, -- CompactPoint* cp, HeapWord* compact_top) { -- // q is alive -+// (DCEVM) Calculates the compact_top that will be used for placing the next object with the giving size on the heap. -+HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top) { - // First check if we should switch compaction space - assert(this == cp->space, "'this' should be current compaction space."); - size_t compaction_max_size = pointer_delta(end(), compact_top); -@@ -372,8 +371,15 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, - compaction_max_size = pointer_delta(cp->space->end(), compact_top); - } - -+ return compact_top; -+} -+ -+HeapWord* CompactibleSpace::forward(oop q, size_t size, -+ CompactPoint* cp, HeapWord* compact_top) { -+ compact_top = forward_compact_top(size, cp, compact_top); -+ - // store the forwarding pointer into the mark word -- if (cast_from_oop(q) != compact_top) { -+ if (cast_from_oop(q) != compact_top || (size_t)q->size() != size) { - q->forward_to(oop(compact_top)); - assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); - } else { -@@ -397,7 +403,132 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, - #if INCLUDE_SERIALGC - - void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { -- scan_and_forward(this, cp); -+ if (!Universe::is_redefining_gc_run()) { -+ scan_and_forward(this, cp, false); -+ } else { -+ // Redefinition run -+ scan_and_forward(this, cp, true); -+ } -+} -+ -+ -+#ifdef ASSERT -+ -+int CompactibleSpace::space_index(oop obj) { -+ GenCollectedHeap* heap = GenCollectedHeap::heap(); -+ -+ //if (heap->is_in_permanent(obj)) { -+ // return -1; -+ //} -+ -+ int index = 0; -+ CompactibleSpace* space = heap->old_gen()->first_compaction_space(); -+ while (space != NULL) { -+ if (space->is_in_reserved(obj)) { -+ return index; -+ } -+ space = space->next_compaction_space(); -+ index++; -+ } -+ -+ space = heap->young_gen()->first_compaction_space(); -+ while (space != NULL) { -+ if (space->is_in_reserved(obj)) { -+ return index; -+ } -+ space = space->next_compaction_space(); -+ index++; -+ } -+ -+ tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj); -+ index = 0; -+ -+ Generation* gen = heap->old_gen(); -+ tty->print_cr(" generation %s: %08xh - %08xh", gen->name(), gen->reserved().start(), gen->reserved().end()); -+ -+ space = gen->first_compaction_space(); -+ while (space != NULL) { -+ tty->print_cr(" %2d space %08xh - %08xh", index, space->bottom(), space->end()); -+ space = space->next_compaction_space(); -+ index++; -+ } -+ -+ gen = heap->young_gen(); -+ tty->print_cr(" generation %s: %08xh - %08xh", gen->name(), gen->reserved().start(), gen->reserved().end()); -+ -+ space = gen->first_compaction_space(); -+ while (space != NULL) { -+ tty->print_cr(" %2d space %08xh - %08xh", index, space->bottom(), space->end()); -+ space = space->next_compaction_space(); -+ index++; -+ } -+ -+ ShouldNotReachHere(); -+ return 0; -+} -+#endif -+ -+bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { -+ // Only redefined objects can have the need to be rescued. -+ if (oop(old_obj)->klass()->new_version() == NULL) return false; -+ -+ //if (old_obj->is_perm()) { -+ // // This object is in perm gen: Always rescue to satisfy invariant obj->klass() <= obj. -+ // return true; -+ //} -+ -+ int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); -+ int original_size = old_obj->size(); -+ -+ Generation* tenured_gen = GenCollectedHeap::heap()->old_gen(); -+ bool old_in_tenured = tenured_gen->is_in_reserved(old_obj); -+ bool new_in_tenured = tenured_gen->is_in_reserved(new_obj); -+ if (old_in_tenured == new_in_tenured) { -+ // Rescue if object may overlap with a higher memory address. -+ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); -+ if (old_in_tenured) { -+ // Old and new address are in same space, so just compare the address. -+ // Must rescue if object moves towards the top of the space. -+ assert(space_index(old_obj) == space_index(new_obj), "old_obj and new_obj must be in same space"); -+ } else { -+ // In the new generation, eden is located before the from space, so a -+ // simple pointer comparison is sufficient. -+ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); -+ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration"); -+ assert(overlap == (space_index(old_obj) < space_index(new_obj)), "slow and fast computation must yield same result"); -+ } -+ return overlap; -+ -+ } else { -+ assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces"); -+ if (tenured_gen->is_in_reserved(new_obj)) { -+ // Must never rescue when moving from the new into the old generation. -+ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); -+ assert(space_index(old_obj) > space_index(new_obj), "must be"); -+ return false; -+ -+ } else /* if (tenured_gen->is_in_reserved(old_obj)) */ { -+ // Must always rescue when moving from the old into the new generation. -+ assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(new_obj), "new_obj must be in DefNewGeneration"); -+ assert(space_index(old_obj) < space_index(new_obj), "must be"); -+ return true; -+ } -+ } -+} -+ -+HeapWord* CompactibleSpace::rescue(HeapWord* old_obj) { -+ assert(must_rescue(oop(old_obj), oop(old_obj)->forwardee()), "do not call otherwise"); -+ -+ int size = oop(old_obj)->size(); -+ HeapWord* rescued_obj = NEW_RESOURCE_ARRAY(HeapWord, size); -+ Copy::aligned_disjoint_words(old_obj, rescued_obj, size); -+ -+ if (MarkSweep::_rescued_oops == NULL) { -+ MarkSweep::_rescued_oops = new GrowableArray(128); -+ } -+ -+ MarkSweep::_rescued_oops->append(rescued_obj); -+ return rescued_obj; - } - - void CompactibleSpace::adjust_pointers() { -@@ -410,7 +541,12 @@ void CompactibleSpace::adjust_pointers() { - } - - void CompactibleSpace::compact() { -- scan_and_compact(this); -+ if(!Universe::is_redefining_gc_run()) { -+ scan_and_compact(this, false); -+ } else { -+ // Redefinition run -+ scan_and_compact(this, true); -+ } - } - - #endif // INCLUDE_SERIALGC -@@ -685,6 +821,58 @@ void OffsetTableContigSpace::verify() const { - guarantee(p == top(), "end of last object must match end of space"); - } - -+// Compute the forward sizes and leave out objects whose position could -+// possibly overlap other objects. -+HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, -+ CompactPoint* cp, HeapWord* compact_top) { -+ size_t forward_size = size; -+ -+ // (DCEVM) There is a new version of the class of q => different size -+ if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) { -+ -+ size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); -+ assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -+ forward_size = new_size; -+ } -+ -+ compact_top = forward_compact_top(forward_size, cp, compact_top); -+ -+ if (must_rescue(oop(q), oop(compact_top))) { -+ if (MarkSweep::_rescued_oops == NULL) { -+ MarkSweep::_rescued_oops = new GrowableArray(128); -+ } -+ MarkSweep::_rescued_oops->append(q); -+ return compact_top; -+ } -+ -+ return forward(oop(q), forward_size, cp, compact_top); -+} -+ -+// Compute the forwarding addresses for the objects that need to be rescued. -+HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_top) { -+ // TODO: empty the _rescued_oops after ALL spaces are compacted! -+ if (MarkSweep::_rescued_oops != NULL) { -+ for (int i=0; ilength(); i++) { -+ HeapWord* q = MarkSweep::_rescued_oops->at(i); -+ -+ /* size_t size = oop(q)->size(); changing this for cms for perm gen */ -+ size_t size = block_size(q); -+ -+ // (DCEVM) There is a new version of the class of q => different size -+ if (oop(q)->klass()->new_version() != NULL) { -+ size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); -+ assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -+ size = new_size; -+ } -+ -+ compact_top = cp->space->forward(oop(q), size, cp, compact_top); -+ assert(compact_top <= end(), "must not write over end of space!"); -+ } -+ MarkSweep::_rescued_oops->clear(); -+ MarkSweep::_rescued_oops = NULL; -+ } -+ return compact_top; -+} - - size_t TenuredSpace::allowed_dead_ratio() const { - return MarkSweepDeadRatio; -diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp -index 0b760364bbc..c9bfc365f0f 100644 ---- a/src/hotspot/share/gc/shared/space.hpp -+++ b/src/hotspot/share/gc/shared/space.hpp -@@ -404,6 +404,9 @@ public: - // indicates when the next such action should be taken. - virtual void prepare_for_compaction(CompactPoint* cp) = 0; - // MarkSweep support phase3 -+ DEBUG_ONLY(int space_index(oop obj)); -+ bool must_rescue(oop old_obj, oop new_obj); -+ HeapWord* rescue(HeapWord* old_obj); - virtual void adjust_pointers(); - // MarkSweep support phase4 - virtual void compact(); -@@ -434,6 +437,15 @@ public: - // accordingly". - virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, - HeapWord* compact_top); -+ // (DCEVM) same as forwad, but can rescue objects. Invoked only during -+ // redefinition runs -+ HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp, -+ HeapWord* compact_top); -+ -+ HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top); -+ -+ // (tw) Compute new compact top without actually forwarding the object. -+ virtual HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); - - // Return a size with adjustments as required of the space. - virtual size_t adjust_object_size_v(size_t size) const { return size; } -@@ -467,12 +479,12 @@ protected: - - // Frequently calls obj_size(). - template -- static inline void scan_and_compact(SpaceType* space); -+ static inline void scan_and_compact(SpaceType* space, bool redefinition_run); - - // Frequently calls scanned_block_is_obj() and scanned_block_size(). - // Requires the scan_limit() function. - template -- static inline void scan_and_forward(SpaceType* space, CompactPoint* cp); -+ static inline void scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); - }; - - class GenSpaceMangler; -@@ -483,7 +495,7 @@ class ContiguousSpace: public CompactibleSpace { - friend class VMStructs; - // Allow scan_and_forward function to call (private) overrides for auxiliary functions on this class - template -- friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp); -+ friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); - - private: - // Auxiliary functions for scan_and_forward support. -diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp -index 37ae2765e71..8e3722b01b1 100644 ---- a/src/hotspot/share/gc/shared/space.inline.hpp -+++ b/src/hotspot/share/gc/shared/space.inline.hpp -@@ -133,7 +133,7 @@ public: - }; - - template --inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { -+inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run) { - // Compute the new addresses for the live objects and store it in the mark - // Used by universe::mark_sweep_phase2() - -@@ -171,7 +171,18 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - // prefetch beyond cur_obj - Prefetch::write(cur_obj, interval); - size_t size = space->scanned_block_size(cur_obj); -- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); -+ -+ if (redefinition_run) { -+ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top); -+ if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) { -+ /* Was moved (otherwise, forward would reset mark), -+ set first_dead to here */ -+ first_dead = cur_obj; -+ } -+ } else { -+ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); -+ } -+ - cur_obj += size; - end_of_live = cur_obj; - } else { -@@ -206,6 +217,10 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - } - } - -+ if (redefinition_run) { -+ compact_top = space->forward_rescued(cp, compact_top); -+ } -+ - assert(cur_obj == scan_limit, "just checking"); - space->_end_of_live = end_of_live; - if (first_dead != NULL) { -@@ -292,7 +307,7 @@ inline void CompactibleSpace::clear_empty_region(SpaceType* space) { - } - - template --inline void CompactibleSpace::scan_and_compact(SpaceType* space) { -+inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run) { - // Copy all live objects to their new location - // Used by MarkSweep::mark_sweep_phase4() - -@@ -316,7 +331,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { - if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { - // All object before _first_dead can be skipped. They should not be moved. - // A pointer to the first live object is stored at the memory location for _first_dead. -- cur_obj = *(HeapWord**)(space->_first_dead); -+ cur_obj = space->_first_dead; - } - - debug_only(HeapWord* prev_obj = NULL); -@@ -334,11 +349,35 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { - size_t size = space->obj_size(cur_obj); - HeapWord* compaction_top = cast_from_oop(oop(cur_obj)->forwardee()); - -+ if (redefinition_run && space->must_rescue(oop(cur_obj), oop(cur_obj)->forwardee())) { -+ space->rescue(cur_obj); -+ debug_only(Copy::fill_to_words(cur_obj, size, 0)); -+ cur_obj += size; -+ continue; -+ } -+ - // prefetch beyond compaction_top - Prefetch::write(compaction_top, copy_interval); - - // copy object and reinit its mark -- assert(cur_obj != compaction_top, "everything in this pass should be moving"); -+ assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL, -+ "everything in this pass should be moving"); -+ if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) { -+ Klass* new_version = oop(cur_obj)->klass()->new_version(); -+ if (new_version->update_information() == NULL) { -+ Copy::aligned_conjoint_words(cur_obj, compaction_top, size); -+ oop(compaction_top)->set_klass(new_version); -+ } else { -+ MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); -+ } -+ oop(compaction_top)->init_mark(); -+ assert(oop(compaction_top)->klass() != NULL, "should have a class"); -+ -+ debug_only(prev_obj = cur_obj); -+ cur_obj += size; -+ continue; -+ } -+ - Copy::aligned_conjoint_words(cur_obj, compaction_top, size); - oop(compaction_top)->init_mark_raw(); - assert(oop(compaction_top)->klass() != NULL, "should have a class"); -diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp -index d8e01e80d2e..ed15db841c6 100644 ---- a/src/hotspot/share/interpreter/linkResolver.cpp -+++ b/src/hotspot/share/interpreter/linkResolver.cpp -@@ -284,7 +284,7 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass, - } - - Reflection::VerifyClassAccessResults vca_result = -- Reflection::verify_class_access(ref_klass, InstanceKlass::cast(base_klass), true); -+ Reflection::verify_class_access(ref_klass->newest_version(), InstanceKlass::cast(base_klass->newest_version()), true); - if (vca_result != Reflection::ACCESS_OK) { - ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(ref_klass, -@@ -566,7 +566,7 @@ void LinkResolver::check_method_accessability(Klass* ref_klass, - // We'll check for the method name first, as that's most likely - // to be false (so we'll short-circuit out of these tests). - if (sel_method->name() == vmSymbols::clone_name() && -- sel_klass == SystemDictionary::Object_klass() && -+ sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version() && - resolved_klass->is_array_klass()) { - // We need to change "protected" to "public". - assert(flags.is_protected(), "clone not protected?"); -@@ -1011,7 +1011,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, - // or by the method (in case of an instance field). - if (is_put && fd.access_flags().is_final()) { - -- if (sel_klass != current_klass) { -+ if (sel_klass != current_klass && sel_klass != current_klass->active_version()) { - ResourceMark rm(THREAD); - stringStream ss; - ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", -@@ -1400,6 +1400,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, - assert(resolved_method->can_be_statically_bound(), "cannot override this method"); - selected_method = resolved_method; - } else { -+ assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent"); - selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); - } - } -diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -index 793ee757879..96fc139bea3 100644 ---- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -+++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -@@ -1471,6 +1471,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre - cld, - &cl_info, - ClassFileParser::INTERNAL, // internal visibility -+ false, - THREAD); - if (HAS_PENDING_EXCEPTION) { - log_pending_exception(PENDING_EXCEPTION); -diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp -index dfb9edf6721..1f3f746b2b7 100644 ---- a/src/hotspot/share/memory/universe.cpp -+++ b/src/hotspot/share/memory/universe.cpp -@@ -156,6 +156,7 @@ int Universe::_base_vtable_size = 0; - bool Universe::_bootstrapping = false; - bool Universe::_module_initialized = false; - bool Universe::_fully_initialized = false; -+bool Universe::_is_redefining_gc_run = false; // FIXME: review - - size_t Universe::_heap_capacity_at_last_gc; - size_t Universe::_heap_used_at_last_gc = 0; -@@ -177,6 +178,44 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { - #define DO_PRIMITIVE_MIRROR(m) \ - f->do_oop((oop*) &m); - -+// FIXME: This method should iterate all pointers that are not within heap objects. -+void Universe::root_oops_do(OopClosure *oopClosure) { -+ -+ class AlwaysTrueClosure: public BoolObjectClosure { -+ public: -+ void do_object(oop p) { ShouldNotReachHere(); } -+ bool do_object_b(oop p) { return true; } -+ }; -+ AlwaysTrueClosure always_true; -+ -+ Universe::oops_do(oopClosure); -+// ReferenceProcessor::oops_do(oopClosure); (tw) check why no longer there -+ JNIHandles::oops_do(oopClosure); // Global (strong) JNI handles -+ Threads::oops_do(oopClosure, NULL); -+ ObjectSynchronizer::oops_do(oopClosure); -+ // TODO: review, flat profiler was removed in j10 -+ // FlatProfiler::oops_do(oopClosure); -+ JvmtiExport::oops_do(oopClosure); -+ -+ // Now adjust pointers in remaining weak roots. (All of which should -+ // have been cleared if they pointed to non-surviving objects.) -+ // Global (weak) JNI handles -+ JNIHandles::weak_oops_do(&always_true, oopClosure); -+ -+ CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); -+ CodeCache::blobs_do(&blobClosure); -+ StringTable::oops_do(oopClosure); -+ -+ // (DCEVM) TODO: Check if this is correct? -+ //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); -+ //Management::oops_do(oopClosure); -+ //ref_processor()->weak_oops_do(&oopClosure); -+ //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); -+ -+ // SO_AllClasses -+ SystemDictionary::oops_do(oopClosure); -+} -+ - void Universe::oops_do(OopClosure* f) { - PRIMITIVE_MIRRORS_DO(DO_PRIMITIVE_MIRROR); - -diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp -index 5d528f522d4..f382a709d18 100644 ---- a/src/hotspot/share/memory/universe.hpp -+++ b/src/hotspot/share/memory/universe.hpp -@@ -53,7 +53,13 @@ class LatestMethodCache : public CHeapObj { - Klass* _klass; - int _method_idnum; - -+ static bool _is_redefining_gc_run; -+ - public: -+ -+ static bool is_redefining_gc_run() { return _is_redefining_gc_run; } -+ static void set_redefining_gc_run(bool b) { _is_redefining_gc_run = b; } -+ - LatestMethodCache() { _klass = NULL; _method_idnum = -1; } - ~LatestMethodCache() { _klass = NULL; _method_idnum = -1; } - -@@ -211,10 +217,15 @@ class Universe: AllStatic { - - static uintptr_t _verify_oop_mask; - static uintptr_t _verify_oop_bits; -+ static bool _is_redefining_gc_run; - - public: - static void calculate_verify_data(HeapWord* low_boundary, HeapWord* high_boundary) PRODUCT_RETURN; - -+ // Advanced class redefinition. FIXME: review? -+ static bool is_redefining_gc_run() { return _is_redefining_gc_run; } -+ static void set_redefining_gc_run(bool b) { _is_redefining_gc_run = b; } -+ - // Known classes in the VM - static Klass* boolArrayKlassObj() { return typeArrayKlassObj(T_BOOLEAN); } - static Klass* byteArrayKlassObj() { return typeArrayKlassObj(T_BYTE); } -@@ -344,6 +355,7 @@ class Universe: AllStatic { - - // Iteration - -+ static void root_oops_do(OopClosure *oopClosure); // FIXME: kill... - // Apply "f" to the addresses of all the direct heap pointers maintained - // as static fields of "Universe". - static void oops_do(OopClosure* f); -diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp -index d939880ed12..ac1c7d397e8 100644 ---- a/src/hotspot/share/oops/cpCache.cpp -+++ b/src/hotspot/share/oops/cpCache.cpp -@@ -450,7 +450,8 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& - if (has_appendix) { - const int appendix_index = f2_as_index(); - assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); -- assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); -+ // FIXME (DCEVM) relaxing for now... -+ //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); - resolved_references->obj_at_put(appendix_index, appendix()); - } - -@@ -640,6 +641,35 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry() { - } - return m; - } -+ -+// Enhanced RedefineClasses() API support (DCEVM): -+// Clear cached entry, let it be re-resolved -+void ConstantPoolCacheEntry::clear_entry() { -+ // Always clear for invokehandle/invokedynamic to re-resolve them -+ bool clearData = bytecode_1() == Bytecodes::_invokehandle || bytecode_1() == Bytecodes::_invokedynamic; -+ _indices = constant_pool_index(); -+ -+ if (clearData) { -+ if (!is_resolved_reference()) { -+ _f2 = 0; -+ } -+ // FIXME: (DCEVM) we want to clear flags, but parameter size is actually used -+ // after we return from the method, before entry is re-initialized. So let's -+ // keep parameter size the same. -+ // For example, it's used in TemplateInterpreterGenerator::generate_return_entry_for -+ // Also, we need to keep flag marking entry as one containing resolved_reference -+ _flags &= parameter_size_mask | (1 << is_resolved_ref_shift); -+ _f1 = NULL; -+ } -+} -+ -+// Enhanced RedefineClasses() API support (DCEVM): -+// Clear all entries -+void ConstantPoolCache::clear_entries() { -+ for (int i = 0; i < length(); i++) { -+ entry_at(i)->clear_entry(); -+ } -+} - #endif // INCLUDE_JVMTI - - void ConstantPoolCacheEntry::print(outputStream* st, int index) const { -diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp -index 38d424c9019..121a13b1dda 100644 ---- a/src/hotspot/share/oops/cpCache.hpp -+++ b/src/hotspot/share/oops/cpCache.hpp -@@ -148,13 +148,13 @@ class ConstantPoolCacheEntry { - void set_bytecode_2(Bytecodes::Code code); - void set_f1(Metadata* f1) { - Metadata* existing_f1 = _f1; // read once -- assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); -+ //assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); - _f1 = f1; - } - void release_set_f1(Metadata* f1); - void set_f2(intx f2) { - intx existing_f2 = _f2; // read once -- assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); -+ //assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); - _f2 = f2; - } - void set_f2_as_vfinal_method(Method* f2) { -@@ -180,6 +180,8 @@ class ConstantPoolCacheEntry { - tos_state_bits = 4, - tos_state_mask = right_n_bits(tos_state_bits), - tos_state_shift = BitsPerInt - tos_state_bits, // see verify_tos_state_shift below -+ // (DCEVM) We need to remember entries which has resolved reference indices as we don't want to clean them -+ is_resolved_ref_shift = 27, - // misc. option bits; can be any bit position in [16..27] - is_field_entry_shift = 26, // (F) is it a field or a method? - has_local_signature_shift = 25, // (S) does the call site have a per-site signature (sig-poly methods)? -@@ -213,6 +215,7 @@ class ConstantPoolCacheEntry { - void initialize_resolved_reference_index(int ref_index) { - assert(_f2 == 0, "set once"); // note: ref_index might be zero also - _f2 = ref_index; -+ _flags = 1 << is_resolved_ref_shift; - } - - void set_field( // sets entry to resolved field state -@@ -353,6 +356,7 @@ class ConstantPoolCacheEntry { - bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } - bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } - bool is_long() const { return flag_state() == ltos; } -+ bool is_resolved_reference() const { return (_flags & (1 << is_resolved_ref_shift)) != 0; } - bool is_double() const { return flag_state() == dtos; } - TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); - return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } -@@ -379,6 +383,10 @@ class ConstantPoolCacheEntry { - bool* trace_name_printed); - bool check_no_old_or_obsolete_entries(); - Method* get_interesting_method_entry(); -+ -+ // Enhanced RedefineClasses() API support (DCEVM): -+ // Clear cached entry, let it be re-resolved -+ void clear_entry(); - #endif // INCLUDE_JVMTI - - // Debugging & Printing -@@ -501,6 +509,10 @@ class ConstantPoolCache: public MetaspaceObj { - void adjust_method_entries(bool* trace_name_printed); - bool check_no_old_or_obsolete_entries(); - void dump_cache(); -+ -+ // Enhanced RedefineClasses() API support (DCEVM): -+ // Clear all entries -+ void clear_entries(); - #endif // INCLUDE_JVMTI - - // RedefineClasses support -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index cfd7fe74321..51bee899aa9 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -998,7 +998,8 @@ bool InstanceKlass::link_class_impl(TRAPS) { - // itable().verify(tty, true); - #endif - set_init_state(linked); -- if (JvmtiExport::should_post_class_prepare()) { -+ // (DCEVM) Must check for old version in order to prevent infinite loops. -+ if (JvmtiExport::should_post_class_prepare() && old_version() == NULL /* JVMTI deadlock otherwise */) { - Thread *thread = THREAD; - assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_prepare((JavaThread *) thread, this); -@@ -1078,7 +1079,8 @@ void InstanceKlass::initialize_impl(TRAPS) { - // If we were to use wait() instead of waitInterruptibly() then - // we might end up throwing IE from link/symbol resolution sites - // that aren't expected to throw. This would wreak havoc. See 6320309. -- while (is_being_initialized() && !is_reentrant_initialization(jt)) { -+ while ((is_being_initialized() && !is_reentrant_initialization(jt)) -+ || (old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { - wait = true; - jt->set_class_to_be_initialized(this); - ol.wait_uninterruptibly(jt); -@@ -1362,6 +1364,18 @@ bool InstanceKlass::implements_interface(Klass* k) const { - return false; - } - -+bool InstanceKlass::implements_interface_any_version(Klass* k) const { -+ k = k->newest_version(); -+ if (this->newest_version() == k) return true; -+ assert(k->is_interface(), "should be an interface class"); -+ for (int i = 0; i < transitive_interfaces()->length(); i++) { -+ if (transitive_interfaces()->at(i)->newest_version() == k) { -+ return true; -+ } -+ } -+ return false; -+} -+ - bool InstanceKlass::is_same_or_direct_interface(Klass *k) const { - // Verify direct super interface - if (this == k) return true; -@@ -1628,6 +1642,23 @@ void InstanceKlass::methods_do(void f(Method* method)) { - } - } - -+/** -+ Update information contains mapping of fields from old class to the new class. -+ Info is stored on HEAP, you need to call clear_update_information to free the space. -+*/ -+void InstanceKlass::store_update_information(GrowableArray &values) { -+ int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass); -+ for (int i = 0; i < values.length(); i++) { -+ arr[i] = values.at(i); -+ } -+ set_update_information(arr); -+} -+ -+void InstanceKlass::clear_update_information() { -+ FREE_C_HEAP_ARRAY(int, update_information()); -+ set_update_information(NULL); -+} -+ - - void InstanceKlass::do_local_static_fields(FieldClosure* cl) { - for (JavaFieldStream fs(this); !fs.done(); fs.next()) { -@@ -2310,12 +2341,30 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { - - void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { - dependencies().remove_dependent_nmethod(nm); -+ // (DCEVM) Hack as dependencies get wrong version of Klass* -+// if (this->old_version() != NULL) { -+// InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true); -+// return; -+// } - } - - void InstanceKlass::clean_dependency_context() { - dependencies().clean_unloading_dependents(); - } - -+bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) { -+ size_t idnum = (size_t)method->method_idnum(); -+ jmethodID* jmeths = methods_jmethod_ids_acquire(); -+ size_t length; // length assigned as debugging crumb -+ jmethodID id = NULL; -+ if (jmeths != NULL && // If there is a cache -+ (length = (size_t)jmeths[0]) > idnum) { // and if it is long enough, -+ jmeths[idnum+1] = newMethodID; // Set method id (may be NULL) -+ return true; -+ } -+ return false; -+} -+ - #ifndef PRODUCT - void InstanceKlass::print_dependent_nmethods(bool verbose) { - dependencies().print_dependent_nmethods(verbose); -@@ -3718,7 +3767,7 @@ void InstanceKlass::verify_on(outputStream* st) { - } - - guarantee(sib->is_klass(), "should be klass"); -- guarantee(sib->super() == super, "siblings should have same superklass"); -+ guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); - } - - // Verify local interfaces -diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp -index b1894200fc1..aa3d38d95e0 100644 ---- a/src/hotspot/share/oops/instanceKlass.hpp -+++ b/src/hotspot/share/oops/instanceKlass.hpp -@@ -137,6 +137,7 @@ class InstanceKlass: public Klass { - friend class JVMCIVMStructs; - friend class ClassFileParser; - friend class CompileReplay; -+ friend class VM_EnhancedRedefineClasses; - - public: - static const KlassID ID = InstanceKlassID; -@@ -955,6 +956,7 @@ public: - size_t *length_p, jmethodID* id_p); - void ensure_space_for_methodids(int start_offset = 0); - jmethodID jmethod_id_or_null(Method* method); -+ bool update_jmethod_id(Method* method, jmethodID newMethodID); - - // annotations support - Annotations* annotations() const { return _annotations; } -@@ -1029,6 +1031,7 @@ public: - - // subclass/subinterface checks - bool implements_interface(Klass* k) const; -+ bool implements_interface_any_version(Klass* k) const; - bool is_same_or_direct_interface(Klass* k) const; - - #ifdef ASSERT -@@ -1060,6 +1063,10 @@ public: - void do_nonstatic_fields(FieldClosure* cl); // including inherited fields - void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS); - -+ // Advanced class redefinition: FIXME: why here? -+ void store_update_information(GrowableArray &values); -+ void clear_update_information(); -+ - void methods_do(void f(Method* method)); - void array_klasses_do(void f(Klass* k)); - void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); -diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp -index 98d0ce1b753..352d8f84631 100644 ---- a/src/hotspot/share/oops/klass.cpp -+++ b/src/hotspot/share/oops/klass.cpp -@@ -200,7 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word - Klass::Klass(KlassID id) : _id(id), - _java_mirror(NULL), - _prototype_header(markWord::prototype()), -- _shared_class_path_index(-1) { -+ _shared_class_path_index(-1), -+ _new_version(NULL), -+ _old_version(NULL), -+ _is_redefining(false), -+ _is_copying_backwards(false), -+ _redefinition_flags(Klass::NoRedefinition), -+ _update_information(NULL) { - CDS_ONLY(_shared_class_flags = 0;) - CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;) - _primary_supers[0] = this; -@@ -465,6 +471,27 @@ void Klass::clean_subklass() { - } - } - -+void Klass::remove_from_sibling_list() { -+ debug_only(verify();) -+ -+ // remove ourselves to superklass' subklass list -+ InstanceKlass* super = superklass(); -+ if (super == NULL) return; // special case: class Object -+ if (super->subklass() == this) { -+ // this klass is the first subklass -+ super->set_subklass(next_sibling()); -+ } else { -+ Klass* sib = super->subklass(); -+ assert(sib != NULL, "cannot find this class in sibling list!"); -+ while (sib->next_sibling() != this) { -+ sib = sib->next_sibling(); -+ assert(sib != NULL, "cannot find this class in sibling list!"); -+ } -+ sib->set_next_sibling(next_sibling()); -+ } -+ debug_only(verify();) -+} -+ - void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses) { - if (!ClassUnloading || !unloading_occurred) { - return; -diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp -index c90477cca96..e06c068cdd7 100644 ---- a/src/hotspot/share/oops/klass.hpp -+++ b/src/hotspot/share/oops/klass.hpp -@@ -165,6 +165,18 @@ class Klass : public Metadata { - markWord _prototype_header; // Used when biased locking is both enabled and disabled for this type - jint _biased_lock_revocation_count; - -+ // Advanced class redefinition -+ -+ // Old version (used in advanced class redefinition) -+ Klass* _old_version; -+ // New version (used in advanced class redefinition) -+ Klass* _new_version; -+ -+ int _redefinition_flags; // Level of class redefinition -+ bool _is_redefining; -+ int* _update_information; -+ bool _is_copying_backwards; // Does the class need to copy fields backwards? => possibly overwrite itself? -+ - private: - // This is an index into FileMapHeader::_shared_path_table[], to - // associate this class with the JAR file where it's loaded from during -@@ -291,6 +303,7 @@ protected: - - InstanceKlass* superklass() const; - void append_to_sibling_list(); // add newly created receiver to superklass' subklass list -+ void remove_from_sibling_list(); // enhanced class redefinition - - void set_next_link(Klass* k) { _next_link = k; } - Klass* next_link() const { return _next_link; } // The next klass defined by the class loader. -@@ -334,11 +347,45 @@ protected: - virtual ModuleEntry* module() const = 0; - virtual PackageEntry* package() const = 0; - -+ // Advanced class redefinition -+ Klass* old_version() const { return _old_version; } -+ void set_old_version(Klass* klass) { assert(_old_version == NULL || klass == NULL, "Old version can only be set once!"); _old_version = klass; } -+ Klass* new_version() const { return _new_version; } -+ void set_new_version(Klass* klass) { assert(_new_version == NULL || klass == NULL, "New version can only be set once!"); _new_version = klass; } -+ bool is_redefining() const { return _is_redefining; } -+ void set_redefining(bool b) { _is_redefining = b; } -+ int redefinition_flags() const { return _redefinition_flags; } -+ bool check_redefinition_flag(int flags) const { return (_redefinition_flags & flags) != 0; } -+ void clear_redefinition_flag(int flag) { _redefinition_flags &= ~flag; } -+ void set_redefinition_flag(int flag) { _redefinition_flags |= flag; } -+ void set_redefinition_flags(int flags) { _redefinition_flags = flags; } -+ -+ const Klass* newest_version() const { return _new_version == NULL ? this : _new_version->newest_version(); } -+ Klass* newest_version() { return _new_version == NULL ? this : _new_version->newest_version(); } -+ -+ const Klass* active_version() const { return _new_version == NULL || _new_version->is_redefining() ? this : _new_version->active_version(); } -+ Klass* active_version() { return _new_version == NULL || _new_version->is_redefining() ? this : _new_version->active_version(); } -+ -+ // update information -+ int *update_information() const { return _update_information; } -+ void set_update_information(int *info) { _update_information = info; } -+ bool is_copying_backwards() const { return _is_copying_backwards; } -+ void set_copying_backwards(bool b) { _is_copying_backwards = b; } -+ - protected: // internal accessors - void set_subklass(Klass* s); - void set_next_sibling(Klass* s); - - public: -+ enum RedefinitionFlags { -+ NoRedefinition, // This class is not redefined at all! -+ ModifyClass = 1, // There are changes to the class meta data. -+ ModifyClassSize = ModifyClass << 1, // The size of the class meta data changes. -+ ModifyInstances = ModifyClassSize << 1, // There are change to the instance format. -+ ModifyInstanceSize = ModifyInstances << 1, // The size of instances changes. -+ RemoveSuperType = ModifyInstanceSize << 1, // A super type of this class is removed. -+ MarkedAsAffected = RemoveSuperType << 1 // This class has been marked as an affected class. -+ }; - - // Compiler support - static ByteSize super_offset() { return in_ByteSize(offset_of(Klass, _super)); } -diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp -index 3d8ade5496c..516f2bb8f2f 100644 ---- a/src/hotspot/share/oops/method.cpp -+++ b/src/hotspot/share/oops/method.cpp -@@ -1540,6 +1540,8 @@ methodHandle Method::clone_with_new_data(const methodHandle& m, u_char* new_code - - // Reset correct method/const method, method size, and parameter info - newm->set_constMethod(newcm); -+ newm->set_new_version(newm->new_version()); -+ newm->set_old_version(newm->old_version()); - newm->constMethod()->set_code_size(new_code_length); - newm->constMethod()->set_constMethod_size(new_const_method_size); - assert(newm->code_size() == new_code_length, "check"); -@@ -2204,6 +2206,10 @@ void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) { - - // Add a method id to the jmethod_ids - jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) { -+ // FIXME: (DCEVM) ??? -+ if (m != m->newest_version()) { -+ m = m->newest_version(); -+ } - ClassLoaderData* cld = loader_data; - - if (!SafepointSynchronize::is_at_safepoint()) { -diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp -index 5b912ca6f5d..83ed2d9c3c1 100644 ---- a/src/hotspot/share/oops/method.hpp -+++ b/src/hotspot/share/oops/method.hpp -@@ -78,6 +78,9 @@ class Method : public Metadata { - MethodCounters* _method_counters; - AccessFlags _access_flags; // Access flags - int _vtable_index; // vtable index of this method (see VtableIndexFlag) -+ // (DCEVM) Newer version of method available? -+ Method* _new_version; -+ Method* _old_version; - // note: can have vtables with >2**16 elements (because of inheritance) - u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) - -@@ -154,6 +157,23 @@ class Method : public Metadata { - int name_index() const { return constMethod()->name_index(); } - void set_name_index(int index) { constMethod()->set_name_index(index); } - -+ Method* new_version() const { return _new_version; } -+ void set_new_version(Method* m) { _new_version = m; } -+ Method* newest_version() { return (_new_version == NULL) ? this : _new_version->newest_version(); } -+ -+ Method* old_version() const { return _old_version; } -+ void set_old_version(Method* m) { -+ /*if (m == NULL) { -+ _old_version = NULL; -+ return; -+ }*/ -+ -+ assert(_old_version == NULL, "may only be set once"); -+ assert(this->code_size() == m->code_size(), "must have same code length"); -+ _old_version = m; -+ } -+ const Method* oldest_version() const { return (_old_version == NULL) ? this : _old_version->oldest_version(); } -+ - // signature - Symbol* signature() const { return constants()->symbol_at(signature_index()); } - int signature_index() const { return constMethod()->signature_index(); } -diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp -index 3c91e8e2ead..51243524106 100644 ---- a/src/hotspot/share/prims/jni.cpp -+++ b/src/hotspot/share/prims/jni.cpp -@@ -338,6 +338,7 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR - class_loader, - Handle(), - &st, -+ NULL, - CHECK_NULL); - - if (log_is_enabled(Debug, class, resolve) && k != NULL) { -diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp -index 2d866dee6dd..333b65ccfc1 100644 ---- a/src/hotspot/share/prims/jvm.cpp -+++ b/src/hotspot/share/prims/jvm.cpp -@@ -963,6 +963,7 @@ static jclass jvm_define_class_common(JNIEnv *env, const char *name, - class_loader, - protection_domain, - &st, -+ NULL, - CHECK_NULL); - - if (log_is_enabled(Debug, class, resolve) && k != NULL) { -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -new file mode 100644 -index 00000000000..83c0952de37 ---- /dev/null -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -0,0 +1,2255 @@ -+/* -+ * Copyright (c) 2003, 2016, 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 "aot/aotLoader.hpp" -+#include "classfile/classFileStream.hpp" -+#include "classfile/metadataOnStackMark.hpp" -+#include "classfile/systemDictionary.hpp" -+#include "classfile/verifier.hpp" -+#include "interpreter/oopMapCache.hpp" -+#include "interpreter/rewriter.hpp" -+#include "logging/logStream.hpp" -+#include "memory/metadataFactory.hpp" -+#include "memory/metaspaceShared.hpp" -+#include "memory/resourceArea.hpp" -+#include "memory/iterator.inline.hpp" -+#include "gc/serial/markSweep.hpp" // FIXME: other GC? -+#include "oops/fieldStreams.hpp" -+#include "oops/klassVtable.hpp" -+#include "oops/oop.inline.hpp" -+#include "oops/constantPool.inline.hpp" -+#include "prims/jvmtiImpl.hpp" -+#include "prims/jvmtiClassFileReconstituter.hpp" -+#include "prims/jvmtiEnhancedRedefineClasses.hpp" -+#include "prims/methodComparator.hpp" -+#include "prims/resolvedMethodTable.hpp" -+#include "runtime/deoptimization.hpp" -+#include "runtime/jniHandles.inline.hpp" -+#include "runtime/relocator.hpp" -+#include "utilities/bitMap.inline.hpp" -+#include "prims/jvmtiThreadState.inline.hpp" -+#include "utilities/events.hpp" -+#include "oops/constantPool.inline.hpp" -+ -+Array* VM_EnhancedRedefineClasses::_old_methods = NULL; -+Array* VM_EnhancedRedefineClasses::_new_methods = NULL; -+Method** VM_EnhancedRedefineClasses::_matching_old_methods = NULL; -+Method** VM_EnhancedRedefineClasses::_matching_new_methods = NULL; -+Method** VM_EnhancedRedefineClasses::_deleted_methods = NULL; -+Method** VM_EnhancedRedefineClasses::_added_methods = NULL; -+int VM_EnhancedRedefineClasses::_matching_methods_length = 0; -+int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; -+int VM_EnhancedRedefineClasses::_added_methods_length = 0; -+Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; -+ -+/** -+ * Create new instance of enhanced class redefiner. -+ * -+ * This class implements VM_GC_Operation - the usual usage should be: -+ * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+ * VMThread::execute(&op); -+ * Which -+ * -+ * @param class_count size of class_defs -+ * @param class_defs class definition - either new class or redefined class -+ * note that this is not the final array of classes to be redefined -+ * we need to scan for all affected classes (e.g. subclasses) and -+ * caculcate redefinition for them as well. -+ * @param class_load_kind always jvmti_class_load_kind_redefine -+ */ -+VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : -+ VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { -+ _affected_klasses = NULL; -+ _class_count = class_count; -+ _class_defs = class_defs; -+ _class_load_kind = class_load_kind; -+ _res = JVMTI_ERROR_NONE; -+ _any_class_has_resolved_methods = false; -+} -+ -+static inline InstanceKlass* get_ik(jclass def) { -+ oop mirror = JNIHandles::resolve_non_null(def); -+ return InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); -+} -+ -+/** -+ * Start the redefinition: -+ * - Load new class definitions - @see load_new_class_versions -+ * - Start mark&sweep GC. -+ * @return true if success, otherwise all chnages are rollbacked. -+ */ -+bool VM_EnhancedRedefineClasses::doit_prologue() { -+ -+ if (_class_count == 0) { -+ _res = JVMTI_ERROR_NONE; -+ return false; -+ } -+ if (_class_defs == NULL) { -+ _res = JVMTI_ERROR_NULL_POINTER; -+ return false; -+ } -+ for (int i = 0; i < _class_count; i++) { -+ if (_class_defs[i].klass == NULL) { -+ _res = JVMTI_ERROR_INVALID_CLASS; -+ return false; -+ } -+ if (_class_defs[i].class_byte_count == 0) { -+ _res = JVMTI_ERROR_INVALID_CLASS_FORMAT; -+ return false; -+ } -+ if (_class_defs[i].class_bytes == NULL) { -+ _res = JVMTI_ERROR_NULL_POINTER; -+ return false; -+ } -+ -+ // classes for primitives and arrays and vm anonymous classes cannot be redefined -+ // check here so following code can assume these classes are InstanceKlass -+ oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); -+ if (!is_modifiable_class(mirror)) { -+ _res = JVMTI_ERROR_UNMODIFIABLE_CLASS; -+ return false; -+ } -+ } -+ -+ // Start timer after all the sanity checks; not quite accurate, but -+ // better than adding a bunch of stop() calls. -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_vm_op_prologue.start(); -+ } -+ -+ // We first load new class versions in the prologue, because somewhere down the -+ // call chain it is required that the current thread is a Java thread. -+ _res = load_new_class_versions(Thread::current()); -+ -+ // prepare GC, lock heap -+ if (_res == JVMTI_ERROR_NONE && !VM_GC_Operation::doit_prologue()) { -+ _res = JVMTI_ERROR_INTERNAL; -+ } -+ -+ if (_res != JVMTI_ERROR_NONE) { -+ rollback(); -+ // TODO free any successfully created classes -+ /*for (int i = 0; i < _class_count; i++) { -+ if (_new_classes[i] != NULL) { -+ ClassLoaderData* cld = _new_classes[i]->class_loader_data(); -+ // Free the memory for this class at class unloading time. Not before -+ // because CMS might think this is still live. -+ cld->add_to_deallocate_list(InstanceKlass::cast(_new_classes[i])); -+ } -+ }*/ -+ delete _new_classes; -+ _new_classes = NULL; -+ delete _affected_klasses; -+ _affected_klasses = NULL; -+ -+ _timer_vm_op_prologue.stop(); -+ return false; -+ } -+ -+ _timer_vm_op_prologue.stop(); -+ return true; -+} -+ -+/** -+ * Closer for static fields - copy value from old class to the new class. -+ */ -+class FieldCopier : public FieldClosure { -+ public: -+ void do_field(fieldDescriptor* fd) { -+ InstanceKlass* cur = InstanceKlass::cast(fd->field_holder()); -+ oop cur_oop = cur->java_mirror(); -+ -+ InstanceKlass* old = InstanceKlass::cast(cur->old_version()); -+ oop old_oop = old->java_mirror(); -+ -+ fieldDescriptor result; -+ bool found = old->find_local_field(fd->name(), fd->signature(), &result); -+ if (found && result.is_static()) { -+ log_trace(redefine, class, obsolete, metadata)("Copying static field value for field %s old_offset=%d new_offset=%d", -+ fd->name()->as_C_string(), result.offset(), fd->offset()); -+ memcpy(cur_oop->obj_field_addr_raw(fd->offset()), -+ old_oop->obj_field_addr_raw(result.offset()), -+ type2aelembytes(fd->field_type())); -+ -+ // Static fields may have references to java.lang.Class -+ if (fd->field_type() == T_OBJECT) { -+ oop oop = cur_oop->obj_field(fd->offset()); -+ if (oop != NULL && oop->is_instance() && InstanceKlass::cast(oop->klass())->is_mirror_instance_klass()) { -+ Klass* klass = java_lang_Class::as_Klass(oop); -+ if (klass != NULL && klass->is_instance_klass()) { -+ assert(oop == InstanceKlass::cast(klass)->java_mirror(), "just checking"); -+ if (klass->new_version() != NULL) { -+ oop = InstanceKlass::cast(klass->new_version())->java_mirror(); -+ cur_oop->obj_field_put(fd->offset(), oop); -+ } -+ } -+ } -+ } -+ } -+ } -+}; -+ -+ -+// TODO: review... -+void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { -+ if (!nm->on_scavenge_root_list()) { -+ CodeCache::add_scavenge_root_nmethod(nm); -+ } -+} -+ -+// TODO comment -+struct StoreBarrier { -+ // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store -+ template static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); } -+}; -+ -+ -+// TODO comment -+struct StoreNoBarrier { -+ template static void oop_store(T* p, oop v) { RawAccess::oop_store(p, v); } -+}; -+ -+/** -+ Closure to scan all heap objects and update method handles -+*/ -+template -+class ChangePointersOopClosure : public BasicOopIterateClosure { -+ // import java_lang_invoke_MemberName.* -+ enum { -+ REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT, -+ REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK, -+ }; -+ -+ -+ bool update_member_name(oop obj) { -+ int flags = java_lang_invoke_MemberName::flags(obj); -+ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; -+ if (MethodHandles::ref_kind_is_method(ref_kind)) { -+ Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj); -+ if (m != NULL && m->method_holder()->new_version() != NULL) { -+ // Let's try to re-resolve method -+ InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version()); -+ Method* new_method = newest->find_method(m->name(), m->signature()); -+ -+ if (new_method != NULL) { -+ // Note: we might set NULL at this point, which should force AbstractMethodError at runtime -+ Thread *thread = Thread::current(); -+ CallInfo info(new_method, newest, thread); -+ Handle objHandle(thread, obj); // TODO : review thread -+ MethodHandles::init_method_MemberName(objHandle, info); -+ } else { -+ java_lang_invoke_MemberName::set_method(obj, NULL); -+ } -+ } -+ } else if (MethodHandles::ref_kind_is_field(ref_kind)) { -+ Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj); -+ if (k == NULL) { -+ return false; // Was cleared before, this MemberName is invalid. -+ } -+ -+ if (k != NULL && k->new_version() != NULL) { -+ // Let's try to re-resolve field -+ fieldDescriptor fd; -+ int offset = java_lang_invoke_MemberName::vmindex(obj); -+ bool is_static = MethodHandles::ref_kind_is_static(ref_kind); -+ InstanceKlass* ik = InstanceKlass::cast(k); -+ if (ik->find_local_field_from_offset(offset, is_static, &fd)) { -+ InstanceKlass* newest = InstanceKlass::cast(k->newest_version()); -+ fieldDescriptor fd_new; -+ if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) { -+ Handle objHandle(Thread::current(), obj); // TODO : review thread -+ MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind)); -+ } else { -+ // Matching field is not found in new version, not much we can do here. -+ // JVM will crash once faulty MH is invoked. -+ // However, to avoid that all DMH's using this faulty MH are cleared (set to NULL) -+ // Eventually, we probably want to replace them with something more meaningful, -+ // like instance throwing NoSuchFieldError or DMH that will resort to dynamic -+ // field resolution (with possibility of type conversion) -+ java_lang_invoke_MemberName::set_method(obj, NULL); -+ java_lang_invoke_MemberName::set_vmindex(obj, 0); -+ return false; -+ } -+ } -+ } -+ } -+ return true; -+ } -+ -+ bool update_direct_method_handle(oop obj) { -+ // Always update member name first. -+ oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj); -+ if (!update_member_name(mem_name)) { -+ return false; -+ } -+ -+ // Here we rely on DirectMethodHandle implementation. -+ // The current implementation caches field offset in $StaticAccessor/$Accessor -+ int flags = java_lang_invoke_MemberName::flags(mem_name); -+ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; -+ if (MethodHandles::ref_kind_is_field(ref_kind)) { -+ // Note: we don't care about staticBase field (which is java.lang.Class) -+ // It should be processed during normal object update. -+ // Update offset in StaticAccessor -+ int offset = java_lang_invoke_MemberName::vmindex(mem_name); -+ if (offset != 0) { // index of 0 means that field no longer exist -+ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) { -+ java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(obj, offset); -+ } else if (java_lang_invoke_DirectMethodHandle_Accessor::is_instance(obj)) { -+ java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(obj, offset); -+ } -+ } -+ } -+ return true; -+ } -+ -+ // Forward pointers to InstanceKlass and mirror class to new versions -+ template -+ inline void do_oop_work(T* p) { -+ oop obj = RawAccess<>::oop_load(p); -+ if (obj == NULL) { -+ return; -+ } -+ if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { -+ Klass* klass = java_lang_Class::as_Klass(obj); -+ if (klass != NULL && klass->is_instance_klass()) { -+ assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking"); -+ if (klass->new_version() != NULL) { -+ obj = InstanceKlass::cast(klass->new_version())->java_mirror(); -+ S::oop_store(p, obj); -+ } -+ } -+ } -+ -+ // JSR 292 support, uptade java.lang.invoke.MemberName instances -+ if (java_lang_invoke_MemberName::is_instance(obj)) { -+ update_member_name(obj); -+ } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) { -+ if (!update_direct_method_handle(obj)) { -+ // DMH is no longer valid, replace it with null reference. -+ // See note above. We probably want to replace this with something more meaningful. -+ S::oop_store(p, NULL); -+ } -+ } -+ } -+ -+ virtual void do_oop(oop* o) { -+ do_oop_work(o); -+ } -+ -+ virtual void do_oop(narrowOop* o) { -+ do_oop_work(o); -+ } -+}; -+ -+/** -+ * Closure to scan all objects on heap for objects of changed classes -+ * - if the fields are compatible, only update class definition reference -+ * - otherwise if the new object size is smaller then old size, reshufle -+ * the fields and fill the gap with "dead_space" -+ * - otherwise set the _needs_instance_update flag, we need to do full GC -+ * and reshuffle object positions durring mark&sweep -+ */ -+class ChangePointersObjectClosure : public ObjectClosure { -+ private: -+ -+ OopIterateClosure *_closure; -+ bool _needs_instance_update; -+ oop _tmp_obj; -+ int _tmp_obj_size; -+ -+public: -+ ChangePointersObjectClosure(OopIterateClosure *closure) : _closure(closure), _needs_instance_update(false), _tmp_obj(NULL), _tmp_obj_size(0) {} -+ -+ bool needs_instance_update() { -+ return _needs_instance_update; -+ } -+ -+ void copy_to_tmp(oop o) { -+ int size = o->size(); -+ if (_tmp_obj_size < size) { -+ _tmp_obj_size = size; -+ _tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize); -+ } -+ Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size); -+ } -+ -+ virtual void do_object(oop obj) { -+ if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { -+ // static fields may have references to old java.lang.Class instances, update them -+ // at the same time, we don't want to update other oops in the java.lang.Class -+ // Causes SIGSEGV? -+ //instanceMirrorKlass::oop_fields_iterate(obj, _closure); -+ } else { -+ obj->oop_iterate(_closure); -+ } -+ -+ if (obj->klass()->new_version() != NULL) { -+ Klass* new_klass = obj->klass()->new_version(); -+ -+ if (new_klass->update_information() != NULL) { -+ int size_diff = obj->size() - obj->size_given_klass(new_klass); -+ -+ // Either new size is bigger or gap is to small to be filled -+ if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) { -+ // We need an instance update => set back to old klass -+ _needs_instance_update = true; -+ } else { -+ oop src = obj; -+ if (new_klass->is_copying_backwards()) { -+ copy_to_tmp(obj); -+ src = _tmp_obj; -+ } -+ src->set_klass(obj->klass()->new_version()); -+ // FIXME: instance updates... -+ //guarantee(false, "instance updates!"); -+ MarkSweep::update_fields(obj, src, new_klass->update_information()); -+ -+ if (size_diff > 0) { -+ HeapWord* dead_space = ((HeapWord *)obj) + obj->size(); -+ CollectedHeap::fill_with_object(dead_space, size_diff); -+ } -+ } -+ } else { -+ obj->set_klass(obj->klass()->new_version()); -+ } -+ } -+ } -+}; -+ -+ -+/** -+ Main transformation method - runs in VM thread. -+ -+ - UseSharedSpaces - TODO what does it mean? -+ - for each sratch class call redefine_single_class -+ - clear code cache (flush_dependent_code) -+ - iterate the heap and update object defintions, check it old/new class fields -+ are compatible. If new class size is smaller then old, it can be solved directly here. -+ - iterate the heap and update method handles to new version -+ - Swap marks to have same hashcodes -+ - copy static fields -+ - notify JVM of the modification -+*/ -+void VM_EnhancedRedefineClasses::doit() { -+ Thread *thread = Thread::current(); -+ -+ if (UseSharedSpaces) { -+ // Sharing is enabled so we remap the shared readonly space to -+ // shared readwrite, private just in case we need to redefine -+ // a shared class. We do the remap during the doit() phase of -+ // the safepoint to be safer. -+ if (!MetaspaceShared::remap_shared_readonly_as_readwrite()) { -+ log_info(redefine, class, load)("failed to remap shared readonly space to readwrite, private"); -+ _res = JVMTI_ERROR_INTERNAL; -+ return; -+ } -+ } -+ -+ // Mark methods seen on stack and everywhere else so old methods are not -+ // cleaned up if they're on the stack. -+ MetadataOnStackMark md_on_stack(true); -+ HandleMark hm(thread); // make sure any handles created are deleted -+ // before the stack walk again. -+ -+ for (int i = 0; i < _new_classes->length(); i++) { -+ redefine_single_class(_new_classes->at(i), thread); -+ } -+ -+ // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) -+ flush_dependent_code(NULL, thread); -+ -+ // JSR-292 support -+ if (_any_class_has_resolved_methods) { -+ bool trace_name_printed = false; -+ ResolvedMethodTable::adjust_method_entries(&trace_name_printed); -+ } -+ -+ ChangePointersOopClosure oopClosureNoBarrier; -+ ChangePointersOopClosure oopClosure; -+ ChangePointersObjectClosure objectClosure(&oopClosure); -+ -+ log_trace(redefine, class, obsolete, metadata)("Before updating instances"); -+ { -+ // Since we may update oops inside nmethod's code blob to point to java.lang.Class in new generation, we need to -+ // make sure such references are properly recognized by GC. For that, If ScavengeRootsInCode is true, we need to -+ // mark such nmethod's as "scavengable". -+ // For now, mark all nmethod's as scavengable that are not scavengable already -+ if (ScavengeRootsInCode) { -+ CodeCache::nmethods_do(mark_as_scavengable); -+ } -+ -+ Universe::heap()->ensure_parsability(false); -+ Universe::heap()->object_iterate(&objectClosure); -+ Universe::root_oops_do(&oopClosureNoBarrier); -+ } -+ log_trace(redefine, class, obsolete, metadata)("After updating instances"); -+ -+ for (int i = 0; i < _new_classes->length(); i++) { -+ InstanceKlass* cur = InstanceKlass::cast(_new_classes->at(i)); -+ InstanceKlass* old = InstanceKlass::cast(cur->old_version()); -+ -+ // Swap marks to have same hashcodes -+ markOop cur_mark = cur->prototype_header(); -+ markOop old_mark = old->prototype_header(); -+ cur->set_prototype_header(old_mark); -+ old->set_prototype_header(cur_mark); -+ -+ //swap_marks(cur, old); -+ cur_mark = cur->java_mirror()->mark(); -+ old_mark = old->java_mirror()->mark(); -+ cur->java_mirror()->set_mark(old_mark); -+ old->java_mirror()->set_mark(cur_mark); -+ -+ -+ // Revert pool holder for old version of klass (it was updated by one of ours closure!) -+ old->constants()->set_pool_holder(old); -+ -+ Klass* array_klasses = old->array_klasses(); -+ if (array_klasses != NULL) { -+ assert(cur->array_klasses() == NULL, "just checking"); -+ -+ // Transfer the array classes, otherwise we might get cast exceptions when casting array types. -+ // Also, set array klasses element klass. -+ cur->set_array_klasses(array_klasses); -+ ObjArrayKlass::cast(array_klasses)->set_element_klass(cur); -+ java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses); -+ java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror()); -+ } -+ -+ // Initialize the new class! Special static initialization that does not execute the -+ // static constructor but copies static field values from the old class if name -+ // and signature of a static field match. -+ FieldCopier copier; -+ cur->do_local_static_fields(&copier); // TODO (tw): What about internal static fields?? -+ //java_lang_Class::set_klass(old->java_mirror(), cur); // FIXME-isd (from JDK8): is that correct? -+ //FIXME-isd (from JDK8): do we need this: ??? old->set_java_mirror(cur->java_mirror()); -+ -+ // Transfer init state -+ InstanceKlass::ClassState state = old->init_state(); -+ if (state > InstanceKlass::linked) { -+ cur->set_init_state(state); -+ } -+ } -+ -+// if (objectClosure.needs_instance_update()) { -+ // Do a full garbage collection to update the instance sizes accordingly -+ Universe::set_redefining_gc_run(true); -+ notify_gc_begin(true); -+ Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); -+ notify_gc_end(); -+ Universe::set_redefining_gc_run(false); -+// } -+ -+ // Unmark Klass*s as "redefining" -+ for (int i = 0; i < _new_classes->length(); i++) { -+ InstanceKlass* cur = _new_classes->at(i); -+ cur->set_redefining(false); -+ cur->clear_update_information(); -+ } -+ -+ // TODO: explain... -+ SystemDictionary::update_constraints_after_redefinition(); -+ -+ // TODO: explain... -+ ciObjectFactory::resort_shared_ci_metadata(); -+ -+ // FIXME - check if it was in JDK8. Copied from standard JDK9 hotswap. -+ //MethodDataCleaner clean_weak_method_links; -+ //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); -+ -+ // Disable any dependent concurrent compilations -+ SystemDictionary::notice_modification(); -+ -+ // Set flag indicating that some invariants are no longer true. -+ // See jvmtiExport.hpp for detailed explanation. -+ JvmtiExport::set_has_redefined_a_class(); -+ -+ // check_class() is optionally called for product bits, but is -+ // always called for non-product bits. -+#ifdef PRODUCT -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+#endif -+ log_trace(redefine, class, obsolete, metadata)("calling check_class"); -+ CheckClass check_class(thread); -+ ClassLoaderDataGraph::classes_do(&check_class); -+#ifdef PRODUCT -+ } -+#endif -+} -+ -+/** -+ * Cleanup - runs in JVM thread -+ * - free used memory -+ * - end GC -+ */ -+void VM_EnhancedRedefineClasses::doit_epilogue() { -+ VM_GC_Operation::doit_epilogue(); -+ -+ if (_new_classes != NULL) { -+ delete _new_classes; -+ } -+ _new_classes = NULL; -+ if (_affected_klasses != NULL) { -+ delete _affected_klasses; -+ } -+ _affected_klasses = NULL; -+ -+ // Reset the_class_oop to null for error printing. -+ _the_class_oop = NULL; -+ -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ // Used to have separate timers for "doit" and "all", but the timer -+ // overhead skewed the measurements. -+ jlong doit_time = _timer_rsc_phase1.milliseconds() + -+ _timer_rsc_phase2.milliseconds(); -+ jlong all_time = _timer_vm_op_prologue.milliseconds() + doit_time; -+ -+ log_info(redefine, class, timer) -+ ("vm_op: all=" JLONG_FORMAT " prologue=" JLONG_FORMAT " doit=" JLONG_FORMAT, -+ all_time, _timer_vm_op_prologue.milliseconds(), doit_time); -+ log_info(redefine, class, timer) -+ ("redefine_single_class: phase1=" JLONG_FORMAT " phase2=" JLONG_FORMAT, -+ _timer_rsc_phase1.milliseconds(), _timer_rsc_phase2.milliseconds()); -+ } -+} -+ -+/** -+ * Exclude java primitives and arrays from redefinition -+ * @param klass_mirror pointer to the klass -+ * @return true if is modifiable -+ */ -+bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { -+ // classes for primitives cannot be redefined -+ if (java_lang_Class::is_primitive(klass_mirror)) { -+ return false; -+ } -+ Klass* k = java_lang_Class::as_Klass(klass_mirror); -+ // classes for arrays cannot be redefined -+ if (k == NULL || !k->is_instance_klass()) { -+ return false; -+ } -+ -+ // Cannot redefine or retransform an anonymous class. -+ if (InstanceKlass::cast(k)->is_anonymous()) { -+ return false; -+ } -+ return true; -+} -+ -+/** -+ Load and link new classes (either redefined or affected by redefinition - subclass, ...) -+ -+ - find sorted affected classes -+ - resolve new class -+ - calculate redefine flags (field change, method change, supertype change, ...) -+ - calculate modified fields and mapping to old fields -+ - link new classes -+ -+ The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. -+*/ -+jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { -+ -+ _affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); -+ _new_classes = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); -+ -+ ResourceMark rm(THREAD); -+ -+ // Retrieve an array of all classes that need to be redefined into _affected_klasses -+ jvmtiError err = find_sorted_affected_classes(THREAD); -+ if (err != JVMTI_ERROR_NONE) { -+ return err; -+ } -+ -+ // thread local state - used to transfer class_being_redefined object to SystemDictonery::resolve_from_stream -+ JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current()); -+ // state can only be NULL if the current thread is exiting which -+ // should not happen since we're trying to do a RedefineClasses -+ guarantee(state != NULL, "exiting thread calling load_new_class_versions"); -+ -+ _max_redefinition_flags = Klass::NoRedefinition; -+ -+ for (int i = 0; i < _affected_klasses->length(); i++) { -+ // Create HandleMark so that any handles created while loading new class -+ // versions are deleted. Constant pools are deallocated while merging -+ // constant pools -+ HandleMark hm(THREAD); -+ InstanceKlass* the_class = InstanceKlass::cast(_affected_klasses->at(i)); -+ Symbol* the_class_sym = the_class->name(); -+ -+ // Ensure class is linked before redefine -+ if (!the_class->is_linked()) { -+ the_class->link_class(THREAD); -+ if (HAS_PENDING_EXCEPTION) { -+ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); -+ log_info(redefine, class, load, exceptions)("link_class exception: '%s'", ex_name->as_C_string()); -+ CLEAR_PENDING_EXCEPTION; -+ if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { -+ return JVMTI_ERROR_OUT_OF_MEMORY; -+ } else { -+ return JVMTI_ERROR_INTERNAL; -+ } -+ } -+ } -+ -+ log_debug(redefine, class, load) -+ ("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)", -+ the_class->external_name(), _class_load_kind, os::available_memory() >> 10); -+ -+ // class bytes... -+ const unsigned char* class_bytes; -+ jint class_byte_count; -+ jvmtiError error; -+ jboolean not_changed; -+ if ((error = find_class_bytes(the_class, &class_bytes, &class_byte_count, ¬_changed)) != JVMTI_ERROR_NONE) { -+ log_info(redefine, class, load, exceptions)("error finding class bytes: %d", (int) error); -+ return error; -+ } -+ assert(class_bytes != NULL && class_byte_count != 0, "class bytes should be defined at this point!"); -+ -+ ClassFileStream st((u1*)class_bytes, -+ class_byte_count, -+ "__VM_EnhancedRedefineClasses__", -+ ClassFileStream::verify); -+ -+ // Parse the stream. -+ Handle the_class_loader(THREAD, the_class->class_loader()); -+ Handle protection_domain(THREAD, the_class->protection_domain()); -+ // Set redefined class handle in JvmtiThreadState class. -+ // This redefined class is sent to agent event handler for class file -+ // load hook event. -+ state->set_class_being_redefined(the_class, _class_load_kind); -+ -+ InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym, -+ the_class_loader, -+ protection_domain, -+ &st, -+ the_class, -+ THREAD); -+ // Clear class_being_redefined just to be sure. -+ state->clear_class_being_redefined(); -+ -+ if (HAS_PENDING_EXCEPTION) { -+ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); -+ log_info(redefine, class, load, exceptions)("parse_stream exception: '%s'", ex_name->as_C_string()); -+ CLEAR_PENDING_EXCEPTION; -+ -+ if (ex_name == vmSymbols::java_lang_UnsupportedClassVersionError()) { -+ return JVMTI_ERROR_UNSUPPORTED_VERSION; -+ } else if (ex_name == vmSymbols::java_lang_ClassFormatError()) { -+ return JVMTI_ERROR_INVALID_CLASS_FORMAT; -+ } else if (ex_name == vmSymbols::java_lang_ClassCircularityError()) { -+ return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; -+ } else if (ex_name == vmSymbols::java_lang_NoClassDefFoundError()) { -+ // The message will be "XXX (wrong name: YYY)" -+ return JVMTI_ERROR_NAMES_DONT_MATCH; -+ } else if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { -+ return JVMTI_ERROR_OUT_OF_MEMORY; -+ } else { // Just in case more exceptions can be thrown.. -+ return JVMTI_ERROR_FAILS_VERIFICATION; -+ } -+ } -+ -+ InstanceKlass* new_class = k; -+ the_class->set_new_version(new_class); -+ _new_classes->append(new_class); -+ -+ int redefinition_flags = Klass::NoRedefinition; -+ if (not_changed) { -+ redefinition_flags = Klass::NoRedefinition; -+ } else { -+ redefinition_flags = calculate_redefinition_flags(new_class); -+ if (redefinition_flags >= Klass::RemoveSuperType) { -+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; -+ } -+ } -+ -+ if (new_class->super() != NULL) { -+ redefinition_flags = redefinition_flags | new_class->super()->redefinition_flags(); -+ } -+ -+ for (int j = 0; j < new_class->local_interfaces()->length(); j++) { -+ redefinition_flags = redefinition_flags | (new_class->local_interfaces()->at(j))->redefinition_flags(); -+ } -+ -+ new_class->set_redefinition_flags(redefinition_flags); -+ -+ _max_redefinition_flags = _max_redefinition_flags | redefinition_flags; -+ -+ if ((redefinition_flags & Klass::ModifyInstances) != 0) { -+ calculate_instance_update_information(_new_classes->at(i)); -+ } else { -+ // Fields were not changed, transfer special flags only -+ assert(new_class->layout_helper() >> 1 == new_class->old_version()->layout_helper() >> 1, "must be equal"); -+ assert(new_class->fields()->length() == InstanceKlass::cast(new_class->old_version())->fields()->length(), "must be equal"); -+ -+ JavaFieldStream old_fs(the_class); -+ JavaFieldStream new_fs(new_class); -+ for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { -+ AccessFlags flags = new_fs.access_flags(); -+ flags.set_is_field_modification_watched(old_fs.access_flags().is_field_modification_watched()); -+ flags.set_is_field_access_watched(old_fs.access_flags().is_field_access_watched()); -+ flags.set_has_field_initialized_final_update(old_fs.access_flags().has_field_initialized_final_update()); -+ new_fs.set_access_flags(flags); -+ } -+ } -+ -+ log_debug(redefine, class, load) -+ ("loaded name=%s (avail_mem=" UINT64_FORMAT "K)", the_class->external_name(), os::available_memory() >> 10); -+ } -+ -+ // Link and verify new classes _after_ all classes have been updated in the system dictionary! -+ for (int i = 0; i < _affected_klasses->length(); i++) { -+ Klass* the_class = _affected_klasses->at(i); -+ assert (the_class->new_version() != NULL, "new version must be present"); -+ InstanceKlass* new_class(InstanceKlass::cast(the_class->new_version())); -+ -+ new_class->link_class(THREAD); -+ -+ if (HAS_PENDING_EXCEPTION) { -+ Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); -+ log_info(redefine, class, load, exceptions)("link_class exception: '%s'", new_class->name()->as_C_string()); -+ CLEAR_PENDING_EXCEPTION; -+ if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { -+ return JVMTI_ERROR_OUT_OF_MEMORY; -+ } else { -+ return JVMTI_ERROR_INTERNAL; -+ } -+ } -+ } -+ return JVMTI_ERROR_NONE; -+} -+ -+/** -+ Calculated the difference between new and old class (field change, method change, supertype change, ...). -+*/ -+int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { -+ int result = Klass::NoRedefinition; -+ log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); -+ -+ assert(new_class->old_version() != NULL, "must have old version"); -+ InstanceKlass* the_class = InstanceKlass::cast(new_class->old_version()); -+ -+ // Check whether class is in the error init state. -+ if (the_class->is_in_error_state()) { -+ // TBD #5057930: special error code is needed in 1.6 -+ //result = Klass::union_redefinition_level(result, Klass::Invalid); -+ } -+ -+ int i; -+ -+ // Check superclasses -+ assert(new_class->super() == NULL || new_class->super()->new_version() == NULL, "superclass must be of newest version"); -+ if (the_class->super() != new_class->super()) { -+ // Super class changed -+ Klass* cur_klass = the_class->super(); -+ while (cur_klass != NULL) { -+ if (!new_class->is_subclass_of(cur_klass->newest_version())) { -+ log_info(redefine, class, load)("removed super class %s", cur_klass->name()->as_C_string()); -+ result = result | Klass::RemoveSuperType | Klass::ModifyInstances | Klass::ModifyClass; -+ } -+ cur_klass = cur_klass->super(); -+ } -+ -+ cur_klass = new_class->super(); -+ while (cur_klass != NULL) { -+ if (!the_class->is_subclass_of(cur_klass->old_version())) { -+ log_info(redefine, class, load)("added super class %s", cur_klass->name()->as_C_string()); -+ result = result | Klass::ModifyClass | Klass::ModifyInstances; -+ } -+ cur_klass = cur_klass->super(); -+ } -+ } -+ -+ // Check interfaces -+ -+ // Interfaces removed? -+ Array* old_interfaces = the_class->transitive_interfaces(); -+ for (i = 0; i < old_interfaces->length(); i++) { -+ InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i)); -+ if (!new_class->implements_interface_any_version(old_interface)) { -+ result = result | Klass::RemoveSuperType | Klass::ModifyClass; -+ log_info(redefine, class, load)("removed interface %s", old_interface->name()->as_C_string()); -+ } -+ } -+ -+ // Interfaces added? -+ Array* new_interfaces = new_class->transitive_interfaces(); -+ for (i = 0; ilength(); i++) { -+ if (!the_class->implements_interface_any_version(new_interfaces->at(i))) { -+ result = result | Klass::ModifyClass; -+ log_info(redefine, class, load)("added interface %s", new_interfaces->at(i)->name()->as_C_string()); -+ } -+ } -+ -+ // Check whether class modifiers are the same. -+ jushort old_flags = (jushort) the_class->access_flags().get_flags(); -+ jushort new_flags = (jushort) new_class->access_flags().get_flags(); -+ if (old_flags != new_flags) { -+ // FIXME: Can this have any effects? -+ } -+ -+ // Check if the number, names, types and order of fields declared in these classes -+ // are the same. -+ JavaFieldStream old_fs(the_class); -+ JavaFieldStream new_fs(new_class); -+ for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { -+ // access -+ old_flags = old_fs.access_flags().as_short(); -+ new_flags = new_fs.access_flags().as_short(); -+ if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { -+ // FIXME: can this have any effect? -+ } -+ // offset -+ if (old_fs.offset() != new_fs.offset()) { -+ result = result | Klass::ModifyInstances; -+ } -+ // name and signature -+ Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index()); -+ Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index()); -+ Symbol* name_sym2 = new_class->constants()->symbol_at(new_fs.name_index()); -+ Symbol* sig_sym2 = new_class->constants()->symbol_at(new_fs.signature_index()); -+ if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { -+ result = result | Klass::ModifyInstances; -+ } -+ } -+ -+ // If both streams aren't done then we have a differing number of -+ // fields. -+ if (!old_fs.done() || !new_fs.done()) { -+ result = result | Klass::ModifyInstances; -+ } -+ -+ // Do a parallel walk through the old and new methods. Detect -+ // cases where they match (exist in both), have been added in -+ // the new methods, or have been deleted (exist only in the -+ // old methods). The class file parser places methods in order -+ // by method name, but does not order overloaded methods by -+ // signature. In order to determine what fate befell the methods, -+ // this code places the overloaded new methods that have matching -+ // old methods in the same order as the old methods and places -+ // new overloaded methods at the end of overloaded methods of -+ // that name. The code for this order normalization is adapted -+ // from the algorithm used in InstanceKlass::find_method(). -+ // Since we are swapping out of order entries as we find them, -+ // we only have to search forward through the overloaded methods. -+ // Methods which are added and have the same name as an existing -+ // method (but different signature) will be put at the end of -+ // the methods with that name, and the name mismatch code will -+ // handle them. -+ Array* k_old_methods(the_class->methods()); -+ Array* k_new_methods(new_class->methods()); -+ int n_old_methods = k_old_methods->length(); -+ int n_new_methods = k_new_methods->length(); -+ Thread* thread = Thread::current(); -+ -+ int ni = 0; -+ int oi = 0; -+ while (true) { -+ Method* k_old_method; -+ Method* k_new_method; -+ enum { matched, added, deleted, undetermined } method_was = undetermined; -+ -+ if (oi >= n_old_methods) { -+ if (ni >= n_new_methods) { -+ break; // we've looked at everything, done -+ } -+ // New method at the end -+ k_new_method = k_new_methods->at(ni); -+ method_was = added; -+ } else if (ni >= n_new_methods) { -+ // Old method, at the end, is deleted -+ k_old_method = k_old_methods->at(oi); -+ method_was = deleted; -+ } else { -+ // There are more methods in both the old and new lists -+ k_old_method = k_old_methods->at(oi); -+ k_new_method = k_new_methods->at(ni); -+ if (k_old_method->name() != k_new_method->name()) { -+ // Methods are sorted by method name, so a mismatch means added -+ // or deleted -+ if (k_old_method->name()->fast_compare(k_new_method->name()) > 0) { -+ method_was = added; -+ } else { -+ method_was = deleted; -+ } -+ } else if (k_old_method->signature() == k_new_method->signature()) { -+ // Both the name and signature match -+ method_was = matched; -+ } else { -+ // The name matches, but the signature doesn't, which means we have to -+ // search forward through the new overloaded methods. -+ int nj; // outside the loop for post-loop check -+ for (nj = ni + 1; nj < n_new_methods; nj++) { -+ Method* m = k_new_methods->at(nj); -+ if (k_old_method->name() != m->name()) { -+ // reached another method name so no more overloaded methods -+ method_was = deleted; -+ break; -+ } -+ if (k_old_method->signature() == m->signature()) { -+ // found a match so swap the methods -+ k_new_methods->at_put(ni, m); -+ k_new_methods->at_put(nj, k_new_method); -+ k_new_method = m; -+ method_was = matched; -+ break; -+ } -+ } -+ -+ if (nj >= n_new_methods) { -+ // reached the end without a match; so method was deleted -+ method_was = deleted; -+ } -+ } -+ } -+ -+ switch (method_was) { -+ case matched: -+ // methods match, be sure modifiers do too -+ old_flags = (jushort) k_old_method->access_flags().get_flags(); -+ new_flags = (jushort) k_new_method->access_flags().get_flags(); -+ if ((old_flags ^ new_flags) & ~(JVM_ACC_NATIVE)) { -+ // TODO Can this have any effects? Probably yes on vtables? -+ result = result | Klass::ModifyClass; -+ } -+ { -+ u2 new_num = k_new_method->method_idnum(); -+ u2 old_num = k_old_method->method_idnum(); -+ if (new_num != old_num) { -+ Method* idnum_owner = new_class->method_with_idnum(old_num); -+ if (idnum_owner != NULL) { -+ // There is already a method assigned this idnum -- switch them -+ // Take current and original idnum from the new_method -+ idnum_owner->set_method_idnum(new_num); -+ idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum()); -+ } -+ // Take current and original idnum from the old_method -+ k_new_method->set_method_idnum(old_num); -+ k_new_method->set_orig_method_idnum(k_old_method->orig_method_idnum()); -+ if (thread->has_pending_exception()) { -+ return JVMTI_ERROR_OUT_OF_MEMORY; -+ } -+ } -+ } -+ log_trace(redefine, class, normalize) -+ ("Method matched: new: %s [%d] == old: %s [%d]", -+ k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi); -+ // advance to next pair of methods -+ ++oi; -+ ++ni; -+ break; -+ case added: -+ // method added, see if it is OK -+ new_flags = (jushort) k_new_method->access_flags().get_flags(); -+ if ((new_flags & JVM_ACC_PRIVATE) == 0 -+ // hack: private should be treated as final, but alas -+ || (new_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 -+ ) { -+ // new methods must be private -+ result = result | Klass::ModifyClass; -+ } -+ { -+ u2 num = new_class->next_method_idnum(); -+ if (num == ConstMethod::UNSET_IDNUM) { -+ // cannot add any more methods -+ result = result | Klass::ModifyClass; -+ } -+ u2 new_num = k_new_method->method_idnum(); -+ Method* idnum_owner = new_class->method_with_idnum(num); -+ if (idnum_owner != NULL) { -+ // There is already a method assigned this idnum -- switch them -+ // Take current and original idnum from the new_method -+ idnum_owner->set_method_idnum(new_num); -+ idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum()); -+ } -+ k_new_method->set_method_idnum(num); -+ k_new_method->set_orig_method_idnum(num); -+ if (thread->has_pending_exception()) { -+ return JVMTI_ERROR_OUT_OF_MEMORY; -+ } -+ } -+ log_trace(redefine, class, normalize) -+ ("Method added: new: %s [%d]", k_new_method->name_and_sig_as_C_string(), ni); -+ ++ni; // advance to next new method -+ break; -+ case deleted: -+ // method deleted, see if it is OK -+ old_flags = (jushort) k_old_method->access_flags().get_flags(); -+ if ((old_flags & JVM_ACC_PRIVATE) == 0 -+ // hack: private should be treated as final, but alas -+ || (old_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 -+ ) { -+ // deleted methods must be private -+ result = result | Klass::ModifyClass; -+ } -+ log_trace(redefine, class, normalize) -+ ("Method deleted: old: %s [%d]", k_old_method->name_and_sig_as_C_string(), oi); -+ ++oi; // advance to next old method -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+ } -+ -+ if (new_class->size() != new_class->old_version()->size()) { -+ result |= Klass::ModifyClassSize; -+ } -+ -+ if (new_class->size_helper() != (InstanceKlass::cast((new_class->old_version()))->size_helper())) { -+ result |= Klass::ModifyInstanceSize; -+ } -+ -+ // TODO Check method bodies to be able to return NoChange? -+ return result; -+} -+ -+ -+/** -+ Searches for the class bytecode of the given class and returns it as a byte array. -+ -+ @param the_class definition of a class, either existing class or new_class -+ @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. -+ @param class_byte_count - size of class_bytes -+ @param not_changed - new_class not available or same as current class -+*/ -+jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) { -+ -+ *not_changed = false; -+ -+ // Search for the index in the redefinition array that corresponds to the current class -+ int i; -+ for (i = 0; i < _class_count; i++) { -+ if (the_class == get_ik(_class_defs[i].klass)) -+ break; -+ } -+ -+ if (i == _class_count) { -+ *not_changed = true; -+ -+ // Redefine with same bytecodes. This is a class that is only indirectly affected by redefinition, -+ // so the user did not specify a different bytecode for that class. -+ if (the_class->get_cached_class_file_bytes() == NULL) { -+ // Not cached, we need to reconstitute the class file from the -+ // VM representation. We don't attach the reconstituted class -+ // bytes to the InstanceKlass here because they have not been -+ // validated and we're not at a safepoint. -+ JvmtiClassFileReconstituter reconstituter(the_class); -+ if (reconstituter.get_error() != JVMTI_ERROR_NONE) { -+ return reconstituter.get_error(); -+ } -+ -+ *class_byte_count = (jint)reconstituter.class_file_size(); -+ *class_bytes = (unsigned char*) reconstituter.class_file_bytes(); -+ } else { -+ // it is cached, get it from the cache -+ *class_byte_count = the_class->get_cached_class_file_len(); -+ *class_bytes = the_class->get_cached_class_file_bytes(); -+ } -+ } else { -+ // Redefine with bytecodes at index j -+ *class_bytes = _class_defs[i].class_bytes; -+ *class_byte_count = _class_defs[i].class_byte_count; -+ } -+ -+ return JVMTI_ERROR_NONE; -+} -+ -+/** -+ Calculate difference between non static fields of old and new class and store the info into new class: -+ instanceKlass->store_update_information -+ instanceKlass->copy_backwards -+*/ -+void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) { -+ -+ class CalculateFieldUpdates : public FieldClosure { -+ -+ private: -+ InstanceKlass* _old_ik; -+ GrowableArray _update_info; -+ int _position; -+ bool _copy_backwards; -+ -+ public: -+ -+ bool does_copy_backwards() { -+ return _copy_backwards; -+ } -+ -+ CalculateFieldUpdates(InstanceKlass* old_ik) : -+ _old_ik(old_ik), _position(instanceOopDesc::base_offset_in_bytes()), _copy_backwards(false) { -+ _update_info.append(_position); -+ _update_info.append(0); -+ } -+ -+ GrowableArray &finish() { -+ _update_info.append(0); -+ return _update_info; -+ } -+ -+ void do_field(fieldDescriptor* fd) { -+ int alignment = fd->offset() - _position; -+ if (alignment > 0) { -+ // This field was aligned, so we need to make sure that we fill the gap -+ fill(alignment); -+ } -+ -+ assert(_position == fd->offset(), "must be correct offset!"); -+ -+ fieldDescriptor old_fd; -+ if (_old_ik->find_field(fd->name(), fd->signature(), false, &old_fd) != NULL) { -+ // Found field in the old class, copy -+ copy(old_fd.offset(), type2aelembytes(fd->field_type())); -+ -+ if (old_fd.offset() < fd->offset()) { -+ _copy_backwards = true; -+ } -+ -+ // Transfer special flags -+ fd->set_is_field_modification_watched(old_fd.is_field_modification_watched()); -+ fd->set_is_field_access_watched(old_fd.is_field_access_watched()); -+ } else { -+ // New field, fill -+ fill(type2aelembytes(fd->field_type())); -+ } -+ } -+ -+ private: -+ void fill(int size) { -+ if (_update_info.length() > 0 && _update_info.at(_update_info.length() - 1) < 0) { -+ (*_update_info.adr_at(_update_info.length() - 1)) -= size; -+ } else { -+ _update_info.append(-size); -+ } -+ _position += size; -+ } -+ -+ void copy(int offset, int size) { -+ int prev_end = -1; -+ if (_update_info.length() > 0 && _update_info.at(_update_info.length() - 1) > 0) { -+ prev_end = _update_info.at(_update_info.length() - 2) + _update_info.at(_update_info.length() - 1); -+ } -+ -+ if (prev_end == offset) { -+ (*_update_info.adr_at(_update_info.length() - 2)) += size; -+ } else { -+ _update_info.append(size); -+ _update_info.append(offset); -+ } -+ -+ _position += size; -+ } -+ }; -+ -+ InstanceKlass* ik = InstanceKlass::cast(new_version); -+ InstanceKlass* old_ik = InstanceKlass::cast(new_version->old_version()); -+ -+ // -+ CalculateFieldUpdates cl(old_ik); -+ ik->do_nonstatic_fields(&cl); -+ -+ GrowableArray result = cl.finish(); -+ ik->store_update_information(result); -+ ik->set_copying_backwards(cl.does_copy_backwards()); -+/* TODO logging -+ if (RC_TRACE_ENABLED(0x00000001)) { -+ RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string())); -+ if (cl.does_copy_backwards()) { -+ RC_TRACE(0x00000001, ("\tDoes copy backwards!")); -+ } -+ for (int i=0; i 0) { -+ RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1))); -+ i++; -+ } else { -+ RC_TRACE(0x00000001, ("\tEND")); -+ } -+ } -+ }*/ -+} -+ -+/** -+ Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. -+*/ -+void VM_EnhancedRedefineClasses::rollback() { -+ log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); -+ ClassLoaderDataGraph::rollback_redefinition(); -+ -+ for (int i = 0; i < _new_classes->length(); i++) { -+ SystemDictionary::remove_from_hierarchy(_new_classes->at(i)); -+ } -+ -+ for (int i = 0; i < _new_classes->length(); i++) { -+ InstanceKlass* new_class = _new_classes->at(i); -+ new_class->set_redefining(false); -+ new_class->old_version()->set_new_version(NULL); -+ new_class->set_old_version(NULL); -+ } -+ _new_classes->clear(); -+} -+ -+ -+// Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp -+// The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not -+// do that, they assume that cache entry is resolved already. -+void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { -+ RawBytecodeStream bcs(method); -+ Bytecodes::Code code; -+ Bytecodes::Code java_code; -+ while (!bcs.is_last_bytecode()) { -+ code = bcs.raw_next(); -+ -+ // dcevm : workaround check _illegal in case of lambda methods etc. -+ // TODO: skip lambda/intrinsic before while loop? (method()->is_method_handle_intrinsic() || method()->is_compiled_lambda_form()) -+ if (code == Bytecodes::_illegal) { -+ return; -+ } -+ -+ address bcp = bcs.bcp(); -+ -+ if (code == Bytecodes::_breakpoint) { -+ int bci = method->bci_from(bcp); -+ code = method->orig_bytecode_at(bci); -+ java_code = Bytecodes::java_code(code); -+ if (code != java_code && -+ (java_code == Bytecodes::_getfield || -+ java_code == Bytecodes::_putfield || -+ java_code == Bytecodes::_aload_0)) { -+ // Let breakpoint table handling unpatch bytecode -+ method->set_orig_bytecode_at(bci, java_code); -+ } -+ } else { -+ java_code = Bytecodes::java_code(code); -+ if (code != java_code && -+ (java_code == Bytecodes::_getfield || -+ java_code == Bytecodes::_putfield || -+ java_code == Bytecodes::_aload_0)) { -+ *bcp = java_code; -+ } -+ } -+ -+ // Additionally, we need to unpatch bytecode at bcp+1 for fast_xaccess (which would be fast field access) -+ if (code == Bytecodes::_fast_iaccess_0 || code == Bytecodes::_fast_aaccess_0 || code == Bytecodes::_fast_faccess_0) { -+ Bytecodes::Code code2 = Bytecodes::code_or_bp_at(bcp + 1); -+ assert(code2 == Bytecodes::_fast_igetfield || -+ code2 == Bytecodes::_fast_agetfield || -+ code2 == Bytecodes::_fast_fgetfield, ""); -+ *(bcp + 1) = Bytecodes::java_code(code2); -+ } -+ } -+ } -+ -+// Unevolving classes may point to methods of the_class directly -+// from their constant pool caches, itables, and/or vtables. We -+// use the ClassLoaderDataGraph::classes_do() facility and this helper -+// to fix up these pointers. -+// Adjust cpools and vtables closure -+void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { -+ // This is a very busy routine. We don't want too much tracing -+ // printed out. -+ bool trace_name_printed = false; -+ InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop); -+ -+ // If the class being redefined is java.lang.Object, we need to fix all -+ // array class vtables also -+ if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { -+ k->vtable().adjust_method_entries(the_class, &trace_name_printed); -+ } else if (k->is_instance_klass()) { -+ HandleMark hm(_thread); -+ InstanceKlass *ik = InstanceKlass::cast(k); -+ -+ // HotSpot specific optimization! HotSpot does not currently -+ // support delegation from the bootstrap class loader to a -+ // user-defined class loader. This means that if the bootstrap -+ // class loader is the initiating class loader, then it will also -+ // be the defining class loader. This also means that classes -+ // loaded by the bootstrap class loader cannot refer to classes -+ // loaded by a user-defined class loader. Note: a user-defined -+ // class loader can delegate to the bootstrap class loader. -+ // -+ // If the current class being redefined has a user-defined class -+ // loader as its defining class loader, then we can skip all -+ // classes loaded by the bootstrap class loader. -+ bool is_user_defined = -+ InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; -+ if (is_user_defined && ik->class_loader() == NULL) { -+ return; -+ } -+ -+ // Fix the vtable embedded in the_class and subclasses of the_class, -+ // if one exists. We discard scratch_class and we don't keep an -+ // InstanceKlass around to hold obsolete methods so we don't have -+ // any other InstanceKlass embedded vtables to update. The vtable -+ // holds the Method*s for virtual (but not final) methods. -+ // Default methods, or concrete methods in interfaces are stored -+ // in the vtable, so if an interface changes we need to check -+ // adjust_method_entries() for every InstanceKlass, which will also -+ // adjust the default method vtable indices. -+ // We also need to adjust any default method entries that are -+ // not yet in the vtable, because the vtable setup is in progress. -+ // This must be done after we adjust the default_methods and -+ // default_vtable_indices for methods already in the vtable. -+ // If redefining Unsafe, walk all the vtables looking for entries. -+// FIXME - code from standard redefine - if needed, it should switch to new_class -+// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() -+// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() -+// || ik->is_subtype_of(_the_class_oop))) { -+// // ik->vtable() creates a wrapper object; rm cleans it up -+// ResourceMark rm(_thread); -+// -+// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed); -+// ik->adjust_default_methods(the_class, &trace_name_printed); -+// } -+ -+ // If the current class has an itable and we are either redefining an -+ // interface or if the current class is a subclass of the_class, then -+ // we potentially have to fix the itable. If we are redefining an -+ // interface, then we have to call adjust_method_entries() for -+ // every InstanceKlass that has an itable since there isn't a -+ // subclass relationship between an interface and an InstanceKlass. -+ // If redefining Unsafe, walk all the itables looking for entries. -+// FIXME - code from standard redefine - if needed, it should switch to new_class -+// if (ik->itable_length() > 0 && (_the_class_oop->is_interface() -+// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() -+// || ik->is_subclass_of(_the_class_oop))) { -+// // ik->itable() creates a wrapper object; rm cleans it up -+// ResourceMark rm(_thread); -+// -+// ik->itable()->adjust_method_entries(the_class, &trace_name_printed); -+// } -+ -+ constantPoolHandle other_cp = constantPoolHandle(ik->constants()); -+ -+ // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. -+ if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { -+ ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); -+ } -+ -+ for (int i = 0; i < other_cp->length(); i++) { -+ if (other_cp->tag_at(i).is_klass()) { -+ Klass* klass = other_cp->resolved_klass_at(i); -+ if (klass->new_version() != NULL) { -+ // Constant pool entry points to redefined class -- update to the new version -+ other_cp->klass_at_put(i, klass->newest_version()); -+ } -+ klass = other_cp->resolved_klass_at(i); -+ assert(klass->new_version() == NULL, "Must be new klass!"); -+ } -+ } -+ -+ // DCEVM - clear whole cache (instead special methods for class/method update in standard redefinition) -+ ConstantPoolCache* cp_cache = other_cp->cache(); -+ if (cp_cache != NULL) { -+ cp_cache->clear_entries(); -+ } -+ -+ // If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries -+ if (RewriteBytecodes) { -+ ik->methods_do(unpatch_bytecode); -+ } -+ } -+} -+ -+// Clean method data for this class -+void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { -+ if (k->is_instance_klass()) { -+ InstanceKlass *ik = InstanceKlass::cast(k); -+ // Clean MethodData of this class's methods so they don't refer to -+ // old methods that are no longer running. -+ Array* methods = ik->methods(); -+ int num_methods = methods->length(); -+ for (int index = 0; index < num_methods; ++index) { -+ if (methods->at(index)->method_data() != NULL) { -+ methods->at(index)->method_data()->clean_weak_method_links(); -+ } -+ } -+ } -+} -+ -+void VM_EnhancedRedefineClasses::update_jmethod_ids() { -+ for (int j = 0; j < _matching_methods_length; ++j) { -+ Method* old_method = _matching_old_methods[j]; -+ jmethodID jmid = old_method->find_jmethod_id_or_null(); -+ if (old_method->new_version() != NULL && jmid == NULL) { -+ // (DCEVM) Have to create jmethodID in this case -+ jmid = old_method->jmethod_id(); -+ } -+ -+ if (jmid != NULL) { -+ // There is a jmethodID, change it to point to the new method -+ methodHandle new_method_h(_matching_new_methods[j]); -+ -+ if (old_method->new_version() == NULL) { -+ methodHandle old_method_h(_matching_old_methods[j]); -+ jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h()); -+ bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id); -+ } else { -+ jmethodID mid = new_method_h->jmethod_id(); -+ bool result = InstanceKlass::cast(new_method_h->method_holder())->update_jmethod_id(new_method_h(), jmid); -+ } -+ -+ Method::change_method_associated_with_jmethod_id(jmid, new_method_h()); -+ assert(Method::resolve_jmethod_id(jmid) == _matching_new_methods[j], "should be replaced"); -+ } -+ } -+} -+ -+/** -+ Set method as obsolete / old / deleted. -+*/ -+void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() { -+ for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) { -+ Method* old_method = _matching_old_methods[j]; -+ Method* new_method = _matching_new_methods[j]; -+ -+ if (MethodComparator::methods_EMCP(old_method, new_method)) { -+ old_method->set_new_version(new_method); -+ new_method->set_old_version(old_method); -+ -+ // Transfer breakpoints -+ InstanceKlass *ik = InstanceKlass::cast(old_method->method_holder()); -+ for (BreakpointInfo* bp = ik->breakpoints(); bp != NULL; bp = bp->next()) { -+ if (bp->match(old_method)) { -+ assert(bp->match(new_method), "if old method is method, then new method must match too"); -+ new_method->set_breakpoint(bp->bci()); -+ } -+ } -+ } else { -+ // mark obsolete methods as such -+ old_method->set_is_obsolete(); -+ -+ // obsolete methods need a unique idnum so they become new entries in -+ // the jmethodID cache in InstanceKlass -+ assert(old_method->method_idnum() == new_method->method_idnum(), "must match"); -+// u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum(); -+// if (num != ConstMethod::UNSET_IDNUM) { -+// old_method->set_method_idnum(num); -+// } -+ } -+ old_method->set_is_old(); -+ } -+ for (int i = 0; i < _deleted_methods_length; ++i) { -+ Method* old_method = _deleted_methods[i]; -+ -+ old_method->set_is_old(); -+ old_method->set_is_obsolete(); -+ // FIXME: this flag was added in dcevm10 since it is required in resolvedMethodTable.cpp -+ old_method->set_is_deleted(); -+ } -+} -+ -+// This internal class transfers the native function registration from old methods -+// to new methods. It is designed to handle both the simple case of unchanged -+// native methods and the complex cases of native method prefixes being added and/or -+// removed. -+// It expects only to be used during the VM_EnhancedRedefineClasses op (a safepoint). -+// -+// This class is used after the new methods have been installed in "the_class". -+// -+// So, for example, the following must be handled. Where 'm' is a method and -+// a number followed by an underscore is a prefix. -+// -+// Old Name New Name -+// Simple transfer to new method m -> m -+// Add prefix m -> 1_m -+// Remove prefix 1_m -> m -+// Simultaneous add of prefixes m -> 3_2_1_m -+// Simultaneous removal of prefixes 3_2_1_m -> m -+// Simultaneous add and remove 1_m -> 2_m -+// Same, caused by prefix removal only 3_2_1_m -> 3_2_m -+// -+class TransferNativeFunctionRegistration { -+ private: -+ InstanceKlass* the_class; -+ int prefix_count; -+ char** prefixes; -+ -+ // Recursively search the binary tree of possibly prefixed method names. -+ // Iteration could be used if all agents were well behaved. Full tree walk is -+ // more resilent to agents not cleaning up intermediate methods. -+ // Branch at each depth in the binary tree is: -+ // (1) without the prefix. -+ // (2) with the prefix. -+ // where 'prefix' is the prefix at that 'depth' (first prefix, second prefix,...) -+ Method* search_prefix_name_space(int depth, char* name_str, size_t name_len, -+ Symbol* signature) { -+ TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len); -+ if (name_symbol != NULL) { -+ Method* method = the_class->lookup_method(name_symbol, signature); -+ if (method != NULL) { -+ // Even if prefixed, intermediate methods must exist. -+ if (method->is_native()) { -+ // Wahoo, we found a (possibly prefixed) version of the method, return it. -+ return method; -+ } -+ if (depth < prefix_count) { -+ // Try applying further prefixes (other than this one). -+ method = search_prefix_name_space(depth+1, name_str, name_len, signature); -+ if (method != NULL) { -+ return method; // found -+ } -+ -+ // Try adding this prefix to the method name and see if it matches -+ // another method name. -+ char* prefix = prefixes[depth]; -+ size_t prefix_len = strlen(prefix); -+ size_t trial_len = name_len + prefix_len; -+ char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1); -+ strcpy(trial_name_str, prefix); -+ strcat(trial_name_str, name_str); -+ method = search_prefix_name_space(depth+1, trial_name_str, trial_len, -+ signature); -+ if (method != NULL) { -+ // If found along this branch, it was prefixed, mark as such -+ method->set_is_prefixed_native(); -+ return method; // found -+ } -+ } -+ } -+ } -+ return NULL; // This whole branch bore nothing -+ } -+ -+ // Return the method name with old prefixes stripped away. -+ char* method_name_without_prefixes(Method* method) { -+ Symbol* name = method->name(); -+ char* name_str = name->as_utf8(); -+ -+ // Old prefixing may be defunct, strip prefixes, if any. -+ for (int i = prefix_count-1; i >= 0; i--) { -+ char* prefix = prefixes[i]; -+ size_t prefix_len = strlen(prefix); -+ if (strncmp(prefix, name_str, prefix_len) == 0) { -+ name_str += prefix_len; -+ } -+ } -+ return name_str; -+ } -+ -+ // Strip any prefixes off the old native method, then try to find a -+ // (possibly prefixed) new native that matches it. -+ Method* strip_and_search_for_new_native(Method* method) { -+ ResourceMark rm; -+ char* name_str = method_name_without_prefixes(method); -+ return search_prefix_name_space(0, name_str, strlen(name_str), -+ method->signature()); -+ } -+ -+ public: -+ -+ // Construct a native method transfer processor for this class. -+ TransferNativeFunctionRegistration(InstanceKlass* _the_class) { -+ assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); -+ -+ the_class = _the_class; -+ prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); -+ } -+ -+ // Attempt to transfer any of the old or deleted methods that are native -+ void transfer_registrations(Method** old_methods, int methods_length) { -+ for (int j = 0; j < methods_length; j++) { -+ Method* old_method = old_methods[j]; -+ -+ if (old_method->is_native() && old_method->has_native_function()) { -+ Method* new_method = strip_and_search_for_new_native(old_method); -+ if (new_method != NULL) { -+ // Actually set the native function in the new method. -+ // Redefine does not send events (except CFLH), certainly not this -+ // behind the scenes re-registration. -+ new_method->set_native_function(old_method->native_function(), -+ !Method::native_bind_event_is_interesting); -+ } -+ } -+ } -+ } -+}; -+ -+// Don't lose the association between a native method and its JNI function. -+void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(InstanceKlass* the_class) { -+ TransferNativeFunctionRegistration transfer(the_class); -+ transfer.transfer_registrations(_deleted_methods, _deleted_methods_length); -+ transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); -+} -+ -+// DCEVM - it always deoptimases everything! (because it is very difficult to find only correct dependencies) -+// Deoptimize all compiled code that depends on this class. -+// -+// If the can_redefine_classes capability is obtained in the onload -+// phase then the compiler has recorded all dependencies from startup. -+// In that case we need only deoptimize and throw away all compiled code -+// that depends on the class. -+// -+// If can_redefine_classes is obtained sometime after the onload -+// phase then the dependency information may be incomplete. In that case -+// the first call to RedefineClasses causes all compiled code to be -+// thrown away. As can_redefine_classes has been obtained then -+// all future compilations will record dependencies so second and -+// subsequent calls to RedefineClasses need only throw away code -+// that depends on the class. -+// -+void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) { -+ assert_locked_or_safepoint(Compile_lock); -+ -+ // All dependencies have been recorded from startup or this is a second or -+ // subsequent use of RedefineClasses -+ // FIXME: for now, deoptimize all! -+ if (0 && JvmtiExport::all_dependencies_are_recorded()) { -+ CodeCache::flush_evol_dependents_on(k_h); -+ } else { -+ CodeCache::mark_all_nmethods_for_deoptimization(); -+ -+ ResourceMark rm(THREAD); -+ DeoptimizationMarker dm; -+ -+ // Deoptimize all activations depending on marked nmethods -+ Deoptimization::deoptimize_dependents(); -+ -+ // Make the dependent methods not entrant -+ CodeCache::make_marked_nmethods_not_entrant(); -+ -+ // From now on we know that the dependency information is complete -+ JvmtiExport::set_all_dependencies_are_recorded(true); -+ } -+} -+ -+/** -+ Compare _old_methods and _new_methods arrays and store the result into -+ _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods -+ -+ Setup _old_methods and _new_methods before the call - it should be called for one class only! -+*/ -+void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { -+ Method* old_method; -+ Method* new_method; -+ -+ _matching_old_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); -+ _matching_new_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); -+ _added_methods = NEW_RESOURCE_ARRAY(Method*, _new_methods->length()); -+ _deleted_methods = NEW_RESOURCE_ARRAY(Method*, _old_methods->length()); -+ -+ _matching_methods_length = 0; -+ _deleted_methods_length = 0; -+ _added_methods_length = 0; -+ -+ int nj = 0; -+ int oj = 0; -+ while (true) { -+ if (oj >= _old_methods->length()) { -+ if (nj >= _new_methods->length()) { -+ break; // we've looked at everything, done -+ } -+ // New method at the end -+ new_method = _new_methods->at(nj); -+ _added_methods[_added_methods_length++] = new_method; -+ ++nj; -+ } else if (nj >= _new_methods->length()) { -+ // Old method, at the end, is deleted -+ old_method = _old_methods->at(oj); -+ _deleted_methods[_deleted_methods_length++] = old_method; -+ ++oj; -+ } else { -+ old_method = _old_methods->at(oj); -+ new_method = _new_methods->at(nj); -+ if (old_method->name() == new_method->name()) { -+ if (old_method->signature() == new_method->signature()) { -+ _matching_old_methods[_matching_methods_length ] = old_method; -+ _matching_new_methods[_matching_methods_length++] = new_method; -+ ++nj; -+ ++oj; -+ } else { -+ // added overloaded have already been moved to the end, -+ // so this is a deleted overloaded method -+ _deleted_methods[_deleted_methods_length++] = old_method; -+ ++oj; -+ } -+ } else { // names don't match -+ if (old_method->name()->fast_compare(new_method->name()) > 0) { -+ // new method -+ _added_methods[_added_methods_length++] = new_method; -+ ++nj; -+ } else { -+ // deleted method -+ _deleted_methods[_deleted_methods_length++] = old_method; -+ ++oj; -+ } -+ } -+ } -+ } -+ assert(_matching_methods_length + _deleted_methods_length == _old_methods->length(), "sanity"); -+ assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity"); -+} -+ -+/** -+ FIXME - swap_annotations is never called, check that annotations work -+*/ -+void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class, -+ InstanceKlass* new_class) { -+ // FIXME - probably original implementation only -+ // Swap annotation fields values -+ Annotations* old_annotations = the_class->annotations(); -+ the_class->set_annotations(new_class->annotations()); -+ new_class->set_annotations(old_annotations); -+} -+ -+ -+// Install the redefinition of a class: -+// - house keeping (flushing breakpoints and caches, deoptimizing -+// dependent compiled code) -+// - replacing parts in the_class with parts from new_class -+// - adding a weak reference to track the obsolete but interesting -+// parts of the_class -+// - adjusting constant pool caches and vtables in other classes -+// that refer to methods in the_class. These adjustments use the -+// ClassLoaderDataGraph::classes_do() facility which only allows -+// a helper method to be specified. The interesting parameters -+// that we would like to pass to the helper method are saved in -+// static global fields in the VM operation. -+void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_oop, TRAPS) { -+ -+ HandleMark hm(THREAD); // make sure handles from this call are freed -+ -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_rsc_phase1.start(); -+ } -+ -+ InstanceKlass* new_class = new_class_oop; -+ InstanceKlass* the_class = InstanceKlass::cast(new_class_oop->old_version()); -+ assert(the_class != NULL, "must have old version"); -+ -+ // Remove all breakpoints in methods of this class -+ JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); -+ jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); -+ -+ // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined -+ // Deoptimize all compiled code that depends on this class -+ // flush_dependent_code(the_class, THREAD); -+ -+ _old_methods = the_class->methods(); -+ _new_methods = new_class->methods(); -+ _the_class_oop = the_class; -+ compute_added_deleted_matching_methods(); -+ -+ // track number of methods that are EMCP for add_previous_version() call below -+ check_methods_and_mark_as_obsolete(); -+ update_jmethod_ids(); -+ -+ _any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods; -+ -+ transfer_old_native_function_registrations(the_class); -+ -+ -+ // JSR-292 support -+ /* FIXME: j10 dropped support for it? -+ MemberNameTable* mnt = the_class->member_names(); -+ assert(new_class->member_names() == NULL, ""); -+ if (mnt != NULL) { -+ new_class->set_member_names(mnt); -+ the_class->set_member_names(NULL); -+ -+ // FIXME: adjust_method_entries is used in standard hotswap JDK9 -+ // bool trace_name_printed = false; -+ // mnt->adjust_method_entries(new_class(), &trace_name_printed); -+ } -+ */ -+ -+ // Adjust constantpool caches for all classes that reference methods of the evolved class. -+ ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD); -+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); -+ -+ { -+ ResourceMark rm(THREAD); -+ // increment the classRedefinedCount field in the_class and in any -+ // direct and indirect subclasses of the_class -+ increment_class_counter(the_class, THREAD); -+ log_info(redefine, class, load) -+ ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", -+ the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10); -+ Events::log_redefinition(THREAD, "redefined class name=%s, count=%d", -+ the_class->external_name(), -+ java_lang_Class::classRedefinedCount(the_class->java_mirror())); -+ -+ } -+ _timer_rsc_phase2.stop(); -+} // end redefine_single_class() -+ -+ -+// Increment the classRedefinedCount field in the specific InstanceKlass -+// and in all direct and indirect subclasses. -+void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { -+ oop class_mirror = ik->java_mirror(); -+ Klass* class_oop = java_lang_Class::as_Klass(class_mirror); -+ int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; -+ java_lang_Class::set_classRedefinedCount(class_mirror, new_count); -+ -+ if (class_oop != _the_class_oop) { -+ // _the_class_oop count is printed at end of redefine_single_class() -+ log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count); -+ } -+ -+ for (Klass *subk = ik->subklass(); subk != NULL; -+ subk = subk->next_sibling()) { -+ if (subk->is_instance_klass()) { -+ // Only update instanceKlasses -+ InstanceKlass *subik = InstanceKlass::cast(subk); -+ // recursively do subclasses of the current subclass -+ increment_class_counter(subik, THREAD); -+ } -+ } -+} -+ -+// FIXME - class check is currently disabled -+void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) { -+ return; -+ bool no_old_methods = true; // be optimistic -+ -+ // Both array and instance classes have vtables. -+ // a vtable should never contain old or obsolete methods -+ ResourceMark rm(_thread); -+ if (k->vtable_length() > 0 && -+ !k->vtable().check_no_old_or_obsolete_entries()) { -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+ log_trace(redefine, class, obsolete, metadata) -+ ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -+ k->signature_name()); -+ k->vtable().dump_vtable(); -+ } -+ no_old_methods = false; -+ } -+ -+ if (k->is_instance_klass()) { -+ HandleMark hm(_thread); -+ InstanceKlass *ik = InstanceKlass::cast(k); -+ -+ // an itable should never contain old or obsolete methods -+ if (ik->itable_length() > 0 && -+ !ik->itable().check_no_old_or_obsolete_entries()) { -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+ log_trace(redefine, class, obsolete, metadata) -+ ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -+ ik->signature_name()); -+ ik->itable().dump_itable(); -+ } -+ no_old_methods = false; -+ } -+ -+ // the constant pool cache should never contain non-deleted old or obsolete methods -+ if (ik->constants() != NULL && -+ ik->constants()->cache() != NULL && -+ !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+ log_trace(redefine, class, obsolete, metadata) -+ ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -+ ik->signature_name()); -+ ik->constants()->cache()->dump_cache(); -+ } -+ no_old_methods = false; -+ } -+ } -+ -+ // print and fail guarantee if old methods are found. -+ if (!no_old_methods) { -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+ dump_methods(); -+ } else { -+ log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option " -+ "to see more info about the following guarantee() failure."); -+ } -+ guarantee(false, "OLD and/or OBSOLETE method(s) found"); -+ } -+} -+ -+/** -+ * Logging of all methods (old, new, changed, ...) -+ */ -+void VM_EnhancedRedefineClasses::dump_methods() { -+ int j; -+ log_trace(redefine, class, dump)("_old_methods --"); -+ for (j = 0; j < _old_methods->length(); ++j) { -+ LogStreamHandle(Trace, redefine, class, dump) log_stream; -+ Method* m = _old_methods->at(j); -+ log_stream.print("%4d (%5d) ", j, m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.print(" -- "); -+ m->print_name(&log_stream); -+ log_stream.cr(); -+ } -+ log_trace(redefine, class, dump)("_new_methods --"); -+ for (j = 0; j < _new_methods->length(); ++j) { -+ LogStreamHandle(Trace, redefine, class, dump) log_stream; -+ Method* m = _new_methods->at(j); -+ log_stream.print("%4d (%5d) ", j, m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.print(" -- "); -+ m->print_name(&log_stream); -+ log_stream.cr(); -+ } -+ log_trace(redefine, class, dump)("_matching_methods --"); -+ for (j = 0; j < _matching_methods_length; ++j) { -+ LogStreamHandle(Trace, redefine, class, dump) log_stream; -+ Method* m = _matching_old_methods[j]; -+ log_stream.print("%4d (%5d) ", j, m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.print(" -- "); -+ m->print_name(); -+ log_stream.cr(); -+ -+ m = _matching_new_methods[j]; -+ log_stream.print(" (%5d) ", m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.cr(); -+ } -+ log_trace(redefine, class, dump)("_deleted_methods --"); -+ for (j = 0; j < _deleted_methods_length; ++j) { -+ LogStreamHandle(Trace, redefine, class, dump) log_stream; -+ Method* m = _deleted_methods[j]; -+ log_stream.print("%4d (%5d) ", j, m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.print(" -- "); -+ m->print_name(&log_stream); -+ log_stream.cr(); -+ } -+ log_trace(redefine, class, dump)("_added_methods --"); -+ for (j = 0; j < _added_methods_length; ++j) { -+ LogStreamHandle(Trace, redefine, class, dump) log_stream; -+ Method* m = _added_methods[j]; -+ log_stream.print("%4d (%5d) ", j, m->vtable_index()); -+ m->access_flags().print_on(&log_stream); -+ log_stream.print(" -- "); -+ m->print_name(&log_stream); -+ log_stream.cr(); -+ } -+} -+ -+// TODO - is it called anywhere? -+void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const { -+ VM_Operation::print_on_error(st); -+ if (_the_class_oop != NULL) { -+ ResourceMark rm; -+ st->print_cr(", redefining class %s", _the_class_oop->external_name()); -+ } -+} -+ -+/** -+ Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. -+*/ -+class AffectedKlassClosure : public KlassClosure { -+ private: -+ GrowableArray* _affected_klasses; -+ public: -+ AffectedKlassClosure(GrowableArray* affected_klasses) : _affected_klasses(affected_klasses) {} -+ -+ void do_klass(Klass* klass) { -+ assert(!_affected_klasses->contains(klass), "must not occur more than once!"); -+ -+ if (klass->new_version() != NULL) { -+ return; -+ } -+ assert(klass->new_version() == NULL, "only last version is valid"); -+ -+ if (klass->check_redefinition_flag(Klass::MarkedAsAffected)) { -+ _affected_klasses->append(klass); -+ return; -+ } -+ -+ int super_depth = klass->super_depth(); -+ int idx; -+ for (idx = 0; idx < super_depth; idx++) { -+ Klass* primary = klass->primary_super_of_depth(idx); -+ if (primary == NULL) { -+ break; -+ } -+ if (primary->check_redefinition_flag(Klass::MarkedAsAffected)) { -+ log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); -+ klass->set_redefinition_flag(Klass::MarkedAsAffected); -+ _affected_klasses->append(klass); -+ return; -+ } -+ } -+ -+ int secondary_length = klass->secondary_supers()->length(); -+ for (idx = 0; idx < secondary_length; idx++) { -+ Klass* secondary = klass->secondary_supers()->at(idx); -+ if (secondary->check_redefinition_flag(Klass::MarkedAsAffected)) { -+ log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); -+ klass->set_redefinition_flag(Klass::MarkedAsAffected); -+ _affected_klasses->append(klass); -+ return; -+ } -+ } -+ } -+}; -+ -+/** -+ Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). -+ Affected classes are stored in _affected_klasses and parent classes always precedes child class. -+*/ -+jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { -+ for (int i = 0; i < _class_count; i++) { -+ InstanceKlass* klass_handle = get_ik(_class_defs[i].klass); -+ klass_handle->set_redefinition_flag(Klass::MarkedAsAffected); -+ assert(klass_handle->new_version() == NULL, "must be new class"); -+ -+ log_trace(redefine, class, load)("marking class as being redefined: %s", klass_handle->name()->as_C_string()); -+ } -+ -+ // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) -+ AffectedKlassClosure closure(_affected_klasses); -+ // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure); -+ ClassLoaderDataGraph::dictionary_classes_do(&closure); -+ log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); -+ -+ // Sort the affected klasses such that a supertype is always on a smaller array index than its subtype. -+ jvmtiError result = do_topological_class_sorting(THREAD); -+ -+ if (log_is_enabled(Trace, redefine, class, load)) { -+ log_trace(redefine, class, load)("redefine order:"); -+ for (int i = 0; i < _affected_klasses->length(); i++) { -+ log_trace(redefine, class, load)("%s", _affected_klasses->at(i)->name()->as_C_string()); -+ } -+ } -+ return JVMTI_ERROR_NONE; -+} -+ -+/** -+ Pairs of class dependencies (for topological sort) -+*/ -+struct KlassPair { -+ const Klass* _left; -+ const Klass* _right; -+ -+ KlassPair() { } -+ KlassPair(const Klass* left, const Klass* right) : _left(left), _right(right) { } -+}; -+ -+static bool match_second(void* value, KlassPair elem) { -+ return elem._right == value; -+} -+ -+/** -+ For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. -+ First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). -+ Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) -+ -+ For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. -+ -+ TODO - the class file is potentionally parsed multiple times - introduce a cache? -+*/ -+jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { -+ ResourceMark mark(THREAD); -+ -+ // Collect dependencies -+ GrowableArray links; -+ for (int i = 0; i < _class_count; i++) { -+ InstanceKlass* klass = get_ik(_class_defs[i].klass); -+ -+ ClassFileStream st((u1*)_class_defs[i].class_bytes, -+ _class_defs[i].class_byte_count, -+ "__VM_EnhancedRedefineClasses__", -+ ClassFileStream::verify); -+ -+ Handle protection_domain(THREAD, klass->protection_domain()); -+ -+ ClassFileParser parser(&st, -+ klass->name(), -+ klass->class_loader_data(), -+ protection_domain, -+ NULL, // host_klass -+ NULL, // cp_patches -+ ClassFileParser::INTERNAL, // publicity level -+ true, -+ THREAD); -+ -+ const Klass* super_klass = parser.super_klass(); -+ if (super_klass != NULL && _affected_klasses->contains((Klass*) super_klass)) { -+ links.append(KlassPair(super_klass, klass)); -+ } -+ -+ Array* local_interfaces = parser.local_interfaces(); -+ for (int j = 0; j < local_interfaces->length(); j++) { -+ Klass* iface = local_interfaces->at(j); -+ if (iface != NULL && _affected_klasses->contains(iface)) { -+ links.append(KlassPair(iface, klass)); -+ } -+ } -+ -+ assert(klass->check_redefinition_flag(Klass::MarkedAsAffected), ""); -+ klass->clear_redefinition_flag(Klass::MarkedAsAffected); -+ } -+ -+ // Append dependencies based on current class definition -+ for (int i = 0; i < _affected_klasses->length(); i++) { -+ InstanceKlass* klass = InstanceKlass::cast(_affected_klasses->at(i)); -+ -+ if (klass->check_redefinition_flag(Klass::MarkedAsAffected)) { -+ klass->clear_redefinition_flag(Klass::MarkedAsAffected); -+ Klass* super_klass = klass->super(); -+ if (_affected_klasses->contains(super_klass)) { -+ links.append(KlassPair(super_klass, klass)); -+ } -+ -+ Array* local_interfaces = klass->local_interfaces(); -+ for (int j = 0; j < local_interfaces->length(); j++) { -+ Klass* interfaceKlass = local_interfaces->at(j); -+ if (_affected_klasses->contains(interfaceKlass)) { -+ links.append(KlassPair(interfaceKlass, klass)); -+ } -+ } -+ } -+ } -+ -+ for (int i = 0; i < _affected_klasses->length(); i++) { -+ int j; -+ for (j = i; j < _affected_klasses->length(); j++) { -+ // Search for node with no incoming edges -+ Klass* klass = _affected_klasses->at(j); -+ int k = links.find(klass, match_second); -+ if (k == -1) break; -+ } -+ if (j == _affected_klasses->length()) { -+ return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; -+ } -+ -+ // Remove all links from this node -+ const Klass* klass = _affected_klasses->at(j); -+ int k = 0; -+ while (k < links.length()) { -+ if (links.at(k)._left == klass) { -+ links.delete_at(k); -+ } else { -+ k++; -+ } -+ } -+ -+ // Swap node -+ Klass* tmp = _affected_klasses->at(j); -+ _affected_klasses->at_put(j, _affected_klasses->at(i)); -+ _affected_klasses->at_put(i, tmp); -+ } -+ -+ return JVMTI_ERROR_NONE; -+} -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -new file mode 100644 -index 00000000000..b712d69a193 ---- /dev/null -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -0,0 +1,202 @@ -+/* -+ * Copyright (c) 2003, 2016, 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_PRIMS_JVMTIREDEFINECLASSES2_HPP -+#define SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP -+ -+#include "jvmtifiles/jvmtiEnv.hpp" -+#include "memory/oopFactory.hpp" -+#include "memory/resourceArea.hpp" -+#include "oops/objArrayKlass.hpp" -+#include "oops/objArrayOop.hpp" -+#include "runtime/vm_operations.hpp" -+#include "gc/shared/vmGCOperations.hpp" -+#include "../../../java.base/unix/native/include/jni_md.h" -+ -+/** -+ * Enhanced class redefiner. -+ * -+ * This class implements VM_GC_Operation - the usual usage should be: -+ * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+ * VMThread::execute(&op); -+ * Which in turn runs: -+ * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions -+ * - doit() - main redefition, adjust existing objects on the heap, clear caches -+ * - doit_epilogue() - cleanup -+*/ -+class VM_EnhancedRedefineClasses: public VM_GC_Operation { -+ private: -+ // These static fields are needed by ClassLoaderDataGraph::classes_do() -+ // facility and the AdjustCpoolCacheAndVtable helper: -+ static Array* _old_methods; -+ static Array* _new_methods; -+ static Method** _matching_old_methods; -+ static Method** _matching_new_methods; -+ static Method** _deleted_methods; -+ static Method** _added_methods; -+ static int _matching_methods_length; -+ static int _deleted_methods_length; -+ static int _added_methods_length; -+ static Klass* _the_class_oop; -+ -+ // The instance fields are used to pass information from -+ // doit_prologue() to doit() and doit_epilogue(). -+ jint _class_count; -+ const jvmtiClassDefinition *_class_defs; // ptr to _class_count defs -+ -+ // This operation is used by both RedefineClasses and -+ // RetransformClasses. Indicate which. -+ JvmtiClassLoadKind _class_load_kind; -+ -+ // _index_map_count is just an optimization for knowing if -+ // _index_map_p contains any entries. -+ int _index_map_count; -+ intArray * _index_map_p; -+ -+ // _operands_index_map_count is just an optimization for knowing if -+ // _operands_index_map_p contains any entries. -+ int _operands_cur_length; -+ int _operands_index_map_count; -+ intArray * _operands_index_map_p; -+ -+ GrowableArray* _new_classes; -+ jvmtiError _res; -+ -+ // Set if any of the InstanceKlasses have entries in the ResolvedMethodTable -+ // to avoid walking after redefinition if the redefined classes do not -+ // have any entries. -+ bool _any_class_has_resolved_methods; -+ -+ // Enhanced class redefinition, affected klasses contain all classes which should be redefined -+ // either because of redefine, class hierarchy or interface change -+ GrowableArray* _affected_klasses; -+ -+ int _max_redefinition_flags; -+ -+ // Performance measurement support. These timers do not cover all -+ // the work done for JVM/TI RedefineClasses() but they do cover -+ // the heavy lifting. -+ elapsedTimer _timer_rsc_phase1; -+ elapsedTimer _timer_rsc_phase2; -+ elapsedTimer _timer_vm_op_prologue; -+ -+ // These routines are roughly in call order unless otherwise noted. -+ -+ /** -+ Load and link new classes (either redefined or affected by redefinition - subclass, ...) -+ -+ - find sorted affected classes -+ - resolve new class -+ - calculate redefine flags (field change, method change, supertype change, ...) -+ - calculate modified fields and mapping to old fields -+ - link new classes -+ -+ The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. -+ */ -+ jvmtiError load_new_class_versions(TRAPS); -+ -+ // Searches for all affected classes and performs a sorting such tha -+ // a supertype is always before a subtype. -+ jvmtiError find_sorted_affected_classes(TRAPS); -+ -+ jvmtiError do_topological_class_sorting(TRAPS); -+ -+ jvmtiError find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed); -+ int calculate_redefinition_flags(InstanceKlass* new_class); -+ void calculate_instance_update_information(Klass* new_version); -+ -+ void rollback(); -+ static void mark_as_scavengable(nmethod* nm); -+ static void unpatch_bytecode(Method* method); -+ -+ // Figure out which new methods match old methods in name and signature, -+ // which methods have been added, and which are no longer present -+ void compute_added_deleted_matching_methods(); -+ -+ // Change jmethodIDs to point to the new methods -+ void update_jmethod_ids(); -+ -+ // marking methods as old and/or obsolete -+ void check_methods_and_mark_as_obsolete(); -+ void transfer_old_native_function_registrations(InstanceKlass* the_class); -+ -+ // Install the redefinition of a class -+ void redefine_single_class(InstanceKlass* new_class_oop, TRAPS); -+ -+ void swap_annotations(InstanceKlass* new_class, -+ InstanceKlass* scratch_class); -+ -+ // Increment the classRedefinedCount field in the specific InstanceKlass -+ // and in all direct and indirect subclasses. -+ void increment_class_counter(InstanceKlass *ik, TRAPS); -+ -+ void flush_dependent_code(InstanceKlass* k_h, TRAPS); -+ -+ static void dump_methods(); -+ -+ // Check that there are no old or obsolete methods -+ class CheckClass : public KlassClosure { -+ Thread* _thread; -+ public: -+ CheckClass(Thread* t) : _thread(t) {} -+ void do_klass(Klass* k); -+ }; -+ -+ // Unevolving classes may point to methods of the_class directly -+ // from their constant pool caches, itables, and/or vtables. We -+ // use the ClassLoaderDataGraph::classes_do() facility and this helper -+ // to fix up these pointers. -+ class ClearCpoolCacheAndUnpatch : public KlassClosure { -+ Thread* _thread; -+ public: -+ ClearCpoolCacheAndUnpatch(Thread* t) : _thread(t) {} -+ void do_klass(Klass* k); -+ }; -+ -+ // Clean MethodData out -+ class MethodDataCleaner : public KlassClosure { -+ public: -+ MethodDataCleaner() {} -+ void do_klass(Klass* k); -+ }; -+ public: -+ VM_EnhancedRedefineClasses(jint class_count, -+ const jvmtiClassDefinition *class_defs, -+ JvmtiClassLoadKind class_load_kind); -+ VMOp_Type type() const { return VMOp_RedefineClasses; } -+ bool doit_prologue(); -+ void doit(); -+ void doit_epilogue(); -+ -+ bool allow_nested_vm_operations() const { return true; } -+ jvmtiError check_error() { return _res; } -+ -+ // Modifiable test must be shared between IsModifiableClass query -+ // and redefine implementation -+ static bool is_modifiable_class(oop klass_mirror); -+ -+ // Error printing -+ void print_on_error(outputStream* st) const; -+}; -+#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP -diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp -index 342a0467112..b6838ac034d 100644 ---- a/src/hotspot/share/prims/jvmtiEnv.cpp -+++ b/src/hotspot/share/prims/jvmtiEnv.cpp -@@ -51,6 +51,7 @@ - #include "prims/jvmtiManageCapabilities.hpp" - #include "prims/jvmtiRawMonitor.hpp" - #include "prims/jvmtiRedefineClasses.hpp" -+#include "prims/jvmtiEnhancedRedefineClasses.hpp" - #include "prims/jvmtiTagMap.hpp" - #include "prims/jvmtiThreadState.inline.hpp" - #include "prims/jvmtiUtil.hpp" -@@ -383,8 +384,13 @@ JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr - // is_modifiable_class_ptr - pre-checked for NULL - jvmtiError - JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) { -- *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? -- JNI_TRUE : JNI_FALSE; -+ if (AllowEnhancedClassRedefinition) { -+ *is_modifiable_class_ptr = VM_EnhancedRedefineClasses::is_modifiable_class(k_mirror)? -+ JNI_TRUE : JNI_FALSE; -+ } else { -+ *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? -+ JNI_TRUE : JNI_FALSE; -+ } - return JVMTI_ERROR_NONE; - } /* end IsModifiableClass */ - -@@ -414,7 +420,8 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { - return JVMTI_ERROR_INVALID_CLASS; - } - -- if (!VM_RedefineClasses::is_modifiable_class(k_mirror)) { -+ if ((!AllowEnhancedClassRedefinition && !VM_RedefineClasses::is_modifiable_class(k_mirror)) || -+ (AllowEnhancedClassRedefinition && !VM_EnhancedRedefineClasses::is_modifiable_class(k_mirror))) { - return JVMTI_ERROR_UNMODIFIABLE_CLASS; - } - -@@ -446,10 +453,20 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { - } - class_definitions[index].klass = jcls; - } -+ - EventRetransformClasses event; -- VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); -- VMThread::execute(&op); -- jvmtiError error = op.check_error(); -+ jvmtiError error; -+ -+ if (AllowEnhancedClassRedefinition) { -+ MutexLocker sd_mutex(EnhancedRedefineClasses_lock); -+ VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); -+ VMThread::execute(&op); -+ error = (op.check_error()); -+ } else { -+ VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); -+ VMThread::execute(&op); -+ error = op.check_error(); -+ } - if (error == JVMTI_ERROR_NONE) { - event.set_classCount(class_count); - event.set_redefinitionId(op.id()); -@@ -465,9 +482,18 @@ jvmtiError - JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { - //TODO: add locking - EventRedefineClasses event; -- VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -- VMThread::execute(&op); -- jvmtiError error = op.check_error(); -+ jvmtiError error; -+ -+ if (AllowEnhancedClassRedefinition) { -+ MutexLocker sd_mutex(EnhancedRedefineClasses_lock); -+ VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+ VMThread::execute(&op); -+ error = (op.check_error()); -+ } else { -+ VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+ VMThread::execute(&op); -+ error = op.check_error(); -+ } - if (error == JVMTI_ERROR_NONE) { - event.set_classCount(class_count); - event.set_redefinitionId(op.id()); -diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp -index d4579dfa43d..8e20fb64a8b 100644 ---- a/src/hotspot/share/prims/jvmtiExport.cpp -+++ b/src/hotspot/share/prims/jvmtiExport.cpp -@@ -2796,7 +2796,7 @@ JvmtiDynamicCodeEventCollector::JvmtiDynamicCodeEventCollector() : _code_blobs(N - // iterate over any code blob descriptors collected and post a - // DYNAMIC_CODE_GENERATED event to the profiler. - JvmtiDynamicCodeEventCollector::~JvmtiDynamicCodeEventCollector() { -- assert(!JavaThread::current()->owns_locks(), "all locks must be released to post deferred events"); -+ assert(AllowEnhancedClassRedefinition || !JavaThread::current()->owns_locks(), "all locks must be released to post deferred events"); - // iterate over any code blob descriptors that we collected - if (_code_blobs != NULL) { - for (int i=0; i<_code_blobs->length(); i++) { -diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp -index f903b32be64..345cb21af33 100644 ---- a/src/hotspot/share/prims/jvmtiExport.hpp -+++ b/src/hotspot/share/prims/jvmtiExport.hpp -@@ -176,6 +176,7 @@ class JvmtiExport : public AllStatic { - // systems as needed to relax invariant checks. - static uint64_t _redefinition_count; - friend class VM_RedefineClasses; -+ friend class VM_EnhancedRedefineClasses; - inline static void increment_redefinition_count() { - JVMTI_ONLY(_redefinition_count++;) - } -diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -index 4918d90212f..1c7677f270f 100644 ---- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -@@ -70,12 +70,19 @@ public: - - void do_klass(Klass* k) { - // Collect all jclasses -- _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); -- if (_dictionary_walk) { -- // Collect array classes this way when walking the dictionary (because array classes are -- // not in the dictionary). -- for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) { -- _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror()))); -+ // Collect all jclasses -+ // DCEVM : LoadedClassesClosure in dcevm7 iterates over classes from SystemDictionary therefore the class "k" is always -+ // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was -+ // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we -+ // must use new versions only. -+ if (k->new_version()==NULL) { -+ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); -+ if (_dictionary_walk) { -+ // Collect array classes this way when walking the dictionary (because array classes are -+ // not in the dictionary). -+ for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) { -+ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror()))); -+ } - } - } - } -diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp -index c22eb9a3dc8..a1ea25de1ea 100644 ---- a/src/hotspot/share/prims/jvmtiImpl.cpp -+++ b/src/hotspot/share/prims/jvmtiImpl.cpp -@@ -247,6 +247,11 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { - Symbol* m_name = _method->name(); - Symbol* m_signature = _method->signature(); - -+ // (DCEVM) Go through old versions of method -+ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { -+ (m->*meth_act)(_bci); -+ } -+ - // search previous versions if they exist - for (InstanceKlass* pv_node = ik->previous_versions(); - pv_node != NULL; -diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index 18307a4c6d8..6148bce5b9b 100644 ---- a/src/hotspot/share/runtime/arguments.cpp -+++ b/src/hotspot/share/runtime/arguments.cpp -@@ -2122,6 +2122,36 @@ unsigned int addopens_count = 0; - unsigned int addmods_count = 0; - unsigned int patch_mod_count = 0; - -+// Check consistency of GC selection -+bool Arguments::check_gc_consistency() { -+ // Ensure that the user has not selected conflicting sets -+ // of collectors. -+ uint i = 0; -+ if (UseSerialGC) i++; -+ if (UseConcMarkSweepGC) i++; -+ if (UseParallelGC || UseParallelOldGC) i++; -+ if (UseG1GC) i++; -+ if (AllowEnhancedClassRedefinition) { -+ // Must use serial GC. This limitation applies because the instance size changing GC modifications -+ // are only built into the mark and compact algorithm. -+ if (!UseSerialGC && i >= 1) { -+ jio_fprintf(defaultStream::error_stream(), -+ "Must use the serial GC with enhanced class redefinition\n"); -+ return false; -+ } -+ } -+ -+ if (i > 1) { -+ jio_fprintf(defaultStream::error_stream(), -+ "Conflicting collector combinations in option list; " -+ "please refer to the release notes for the combinations " -+ "allowed\n"); -+ return false; -+ } -+ -+ return true; -+} -+ - // Check the consistency of vm_init_args - bool Arguments::check_vm_args_consistency() { - // Method for adding checks for flag consistency. -@@ -2138,6 +2168,8 @@ bool Arguments::check_vm_args_consistency() { - status = false; - } - -+ status = status && check_gc_consistency(); -+ - if (PrintNMTStatistics) { - #if INCLUDE_NMT - if (MemTracker::tracking_level() == NMT_off) { -diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp -index c652ee3f9fe..9c656124d5b 100644 ---- a/src/hotspot/share/runtime/arguments.hpp -+++ b/src/hotspot/share/runtime/arguments.hpp -@@ -511,6 +511,7 @@ class Arguments : AllStatic { - static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized); - - static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; } -+ - // Return the maximum size a heap with compressed oops can take - static size_t max_heap_for_compressed_oops(); - -diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp -index 0fa47b34c40..de9193ca447 100644 ---- a/src/hotspot/share/runtime/globals.hpp -+++ b/src/hotspot/share/runtime/globals.hpp -@@ -2458,6 +2458,11 @@ const size_t minimumSymbolTableSize = 1024; - \ - diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \ - "Make nmethod barriers deoptimise a lot.") \ -+ \ -+ product(bool, AllowEnhancedClassRedefinition, true, \ -+ "Allow enhanced class redefinition beyond swapping method " \ -+ "bodies") -+ - - // Interface macros - #define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; -diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp -index 3793aaa8d75..9126dd7dffc 100644 ---- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp -+++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp -@@ -220,8 +220,8 @@ class ThreadToNativeFromVM : public ThreadStateTransition { - public: - ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) { - // We are leaving the VM at this point and going directly to native code. -- // Block, if we are in the middle of a safepoint synchronization. -- assert(!thread->owns_locks(), "must release all locks when leaving VM"); -+ // DCEVM allow locks on leaving JVM -+ assert(AllowEnhancedClassRedefinition || !thread->owns_locks(), "must release all locks when leaving VM"); - thread->frame_anchor()->make_walkable(thread); - trans(_thread_in_vm, _thread_in_native); - // Check for pending. async. exceptions or suspends. -diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp -index e08b1232777..a543935c995 100644 ---- a/src/hotspot/share/runtime/javaCalls.cpp -+++ b/src/hotspot/share/runtime/javaCalls.cpp -@@ -56,7 +56,8 @@ JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle recei - bool clear_pending_exception = true; - - guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code"); -- assert(!thread->owns_locks(), "must release all locks when leaving VM"); -+ // DCEVM allow locks on leaving JVM -+ assert(AllowEnhancedClassRedefinition || !thread->owns_locks(), "must release all locks when leaving VM"); - guarantee(thread->can_call_java(), "cannot make java calls from the native compiler"); - _result = result; - -diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp -index e45e8982768..6f982072909 100644 ---- a/src/hotspot/share/runtime/mutexLocker.cpp -+++ b/src/hotspot/share/runtime/mutexLocker.cpp -@@ -5,7 +5,7 @@ - * 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 -@@ -115,6 +115,7 @@ Mutex* FreeList_lock = NULL; - Mutex* OldSets_lock = NULL; - Monitor* RootRegionScan_lock = NULL; - -+Mutex* EnhancedRedefineClasses_lock = NULL; - Mutex* Management_lock = NULL; - Monitor* Service_lock = NULL; - Monitor* Notification_lock = NULL; -@@ -286,6 +287,7 @@ void mutex_init() { - def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never); - def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never); - def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); -+ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel - def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions - def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always); - -diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp -index 90b17b0c234..29d1b67d921 100644 ---- a/src/hotspot/share/runtime/mutexLocker.hpp -+++ b/src/hotspot/share/runtime/mutexLocker.hpp -@@ -106,6 +106,8 @@ extern Mutex* PerfDataMemAlloc_lock; // a lock on the allocator for - extern Mutex* PerfDataManager_lock; // a long on access to PerfDataManager resources - extern Mutex* OopMapCacheAlloc_lock; // protects allocation of oop_map caches - -+extern Mutex* EnhancedRedefineClasses_lock; // locks classes from parallel enhanced redefinition -+ - extern Mutex* FreeList_lock; // protects the free region list during safepoints - extern Mutex* OldSets_lock; // protects the old region sets - extern Monitor* RootRegionScan_lock; // used to notify that the CM threads have finished scanning the IM snapshot regions -diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp -index 02e7b1973fa..0e7722dba7d 100644 ---- a/src/hotspot/share/runtime/reflection.cpp -+++ b/src/hotspot/share/runtime/reflection.cpp -@@ -626,6 +626,12 @@ bool Reflection::verify_member_access(const Klass* current_class, - bool classloader_only, - bool protected_restriction, - TRAPS) { -+ -+ // (DCEVM) Decide accessibility based on active version -+ if (current_class != NULL) { -+ current_class = current_class->active_version(); -+ } -+ - // Verify that current_class can access a member of member_class, where that - // field's access bits are "access". We assume that we've already verified - // that current_class can access member_class. --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch b/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch deleted file mode 100644 index 5415fe6897f3..000000000000 --- a/jb/project/tools/patches/dcevm/0002-dcevm11-fixes.patch +++ /dev/null @@ -1,1569 +0,0 @@ -From 356238c4099e3dfb6cd15d4ee4cf25f030bb2ca3 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Wed, 14 Nov 2018 21:18:22 +0100 -Subject: [PATCH 02/34] dcevm11 fixes - -1. We need to set classRedefinitionCount on new class, not old class. - -2.Fix crashes in MetadataOnStackMark::~MetadataOnSta - -MetadataOnStackMark should not remove dcevm stuff. It was added -accidentaly in dcevm9 and never was part of doit() in previous versions. - -3. Fix problem with nested members - -Reported at : -https://stackoverflow.com/questions/53370380/hotswapagent-incompatibleclasschangeerror-type-headerpanel1-is-not-a-nest-mem - -4. Use init_mark_raw() - -method changed since j8 - it used init_mark() - -5. Fix methodHandles and fieldHandles - -6. Code cleanup - -7. Fix force_forward in dead space - -8. Fix check_class - -9. increment_class_counter() using orig dcevm code - -Probably it is cause of SISEGV on: -_ -VM_EnhancedRedefineClasses::redefine_single_class->java_mirror() - -10 Fix 11.0.7 compilation issues - -11. Refactor ClearCpoolCacheAndUnpatch - -12. not nullable oop_store_not_null() method+handle NULL in mem_name in -dmh - -13. Use INCLUDE_CDS condition on "UseSharedSpaces" block from master - -14. Add codecache flush optimization, but just flush all cache. - -15. Cleanup - -16. Use original code for adjust_method_entries in standard redefinition - -17. iterate old method version only in dcevm - -18. Revert code for !AllowEnhancedClassRedefinition - -19. Code cleanup - -20. Activate cpCache definition asserts for !dcevm - -21. Skip GC runs for redefinitions without instance size change - -22. This is the 2nd commit message: ---- - .../share/classfile/classFileParser.cpp | 4 +- - .../share/classfile/classFileParser.hpp | 2 +- - .../share/classfile/classLoaderDataGraph.cpp | 2 + - src/hotspot/share/classfile/dictionary.cpp | 4 + - src/hotspot/share/classfile/dictionary.hpp | 1 + - .../share/classfile/loaderConstraints.cpp | 3 +- - .../share/classfile/systemDictionary.cpp | 8 +- - src/hotspot/share/gc/shared/space.cpp | 2 +- - src/hotspot/share/gc/shared/space.inline.hpp | 3 +- - .../share/interpreter/linkResolver.cpp | 1 + - src/hotspot/share/memory/universe.cpp | 4 +- - src/hotspot/share/oops/cpCache.cpp | 3 +- - src/hotspot/share/oops/instanceKlass.cpp | 22 +- - src/hotspot/share/oops/instanceKlass.hpp | 1 + - .../prims/jvmtiEnhancedRedefineClasses.cpp | 537 +++++++----------- - .../prims/jvmtiEnhancedRedefineClasses.hpp | 63 +- - src/hotspot/share/prims/jvmtiImpl.cpp | 6 +- - .../share/prims/resolvedMethodTable.cpp | 63 ++ - .../share/prims/resolvedMethodTable.hpp | 1 + - 19 files changed, 329 insertions(+), 401 deletions(-) - -diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp -index 0192e9e006f..6b54b1d63eb 100644 ---- a/src/hotspot/share/classfile/classFileParser.cpp -+++ b/src/hotspot/share/classfile/classFileParser.cpp -@@ -964,6 +964,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, - CHECK); - } - -+ // (DCEVM) pick newest - interf = (Klass *) maybe_newest(interf); - - if (!interf->is_interface()) { -@@ -4014,6 +4015,7 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, - // However, make sure it is not an array type. - bool is_array = false; - if (cp->tag_at(super_class_index).is_klass()) { -+ // (DCEVM) pick newest - super_klass = InstanceKlass::cast(maybe_newest(cp->resolved_klass_at(super_class_index))); - if (need_verify) - is_array = super_klass->is_array_klass(); -@@ -4617,7 +4619,7 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { - if (!_has_empty_finalizer) { - if (_has_finalizer || - (super != NULL && super->has_finalizer())) { -- // FIXME - condition from previous DCEVM version, however after reload new finelize() method is not active -+ // FIXME - (DCEVM) this is condition from previous DCEVM version, however after reload a new finalize() method is not active - if (ik->old_version() == NULL || ik->old_version()->has_finalizer()) { - ik->set_has_finalizer(); - } -diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp -index 6660616ccad..e5761e61767 100644 ---- a/src/hotspot/share/classfile/classFileParser.hpp -+++ b/src/hotspot/share/classfile/classFileParser.hpp -@@ -544,7 +544,7 @@ class ClassFileParser { - TRAPS); - - void update_class_name(Symbol* new_name); -- // Enhanced class redefinition -+ // (DCEVM) Enhanced class redefinition - inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; } - - public: -diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp -index db0fbcc45dc..53f6b78c380 100644 ---- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp -+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp -@@ -439,12 +439,14 @@ void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), - } - } - -+// (DCEVM) - iterate over dict classes - void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->classes_do(klass_closure); - } - } - -+// (DCEVM) rollback redefined classes - void ClassLoaderDataGraph::rollback_redefinition() { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->rollback_redefinition(); -diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp -index 45c979a1738..55fbcf85f73 100644 ---- a/src/hotspot/share/classfile/dictionary.cpp -+++ b/src/hotspot/share/classfile/dictionary.cpp -@@ -216,6 +216,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) { - } - } - -+ -+// (DCEVM) iterate over dict entry - void Dictionary::classes_do(KlassClosure* closure) { - for (int index = 0; index < table_size(); index++) { - for (DictionaryEntry* probe = bucket(index); -@@ -310,6 +312,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, - return NULL; - } - -+// (DCEVM) replace old_class by new class in dictionary - bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass) { - // There are several entries for the same class in the dictionary: One extra entry for each parent classloader of the classloader of the class. - bool found = false; -@@ -324,6 +327,7 @@ bool Dictionary::update_klass(unsigned int hash, Symbol* name, ClassLoaderData* - return found; - } - -+// (DCEVM) rollback redefinition - void Dictionary::rollback_redefinition() { - for (int index = 0; index < table_size(); index++) { - for (DictionaryEntry* entry = bucket(index); -diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp -index b4f5cd5c4df..114a983e783 100644 ---- a/src/hotspot/share/classfile/dictionary.hpp -+++ b/src/hotspot/share/classfile/dictionary.hpp -@@ -111,6 +111,7 @@ public: - - void rollback_redefinition(); - -+ // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k" - static InstanceKlass* old_if_redefined(InstanceKlass* k) { - return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; - } -diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp -index fd1bd46b8bd..2c6a729fa19 100644 ---- a/src/hotspot/share/classfile/loaderConstraints.cpp -+++ b/src/hotspot/share/classfile/loaderConstraints.cpp -@@ -4,7 +4,7 @@ - * - * 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. -+ * published by the Free Software Foundation) replace old_class by new class in dictionary. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -@@ -91,6 +91,7 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( - return pp; - } - -+// (DCEVM) update constraint entries to new classes, called from dcevm redefinition code only - void LoaderConstraintTable::update_after_redefinition() { - for (int index = 0; index < table_size(); index++) { - LoaderConstraintEntry** p = bucket_addr(index); -diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp -index e6b25e90f18..bd0cae7cb9b 100644 ---- a/src/hotspot/share/classfile/systemDictionary.cpp -+++ b/src/hotspot/share/classfile/systemDictionary.cpp -@@ -967,7 +967,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, - ClassLoaderData* loader_data = k->class_loader_data(); - MutexLocker mu(THREAD, SystemDictionary_lock); - InstanceKlass* kk = find_class(name, loader_data); -- // FIXME: (kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) -+ // FIXME: (DCEVM) -+ // assert(kk == k() && !k->is_redefining()) || (k->is_redefining() && kk == k->old_version()) - assert(kk == k, "should be present in dictionary"); - } - #endif -@@ -1178,7 +1179,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - InstanceKlass* k = NULL; - - #if INCLUDE_CDS -- // FIXME: what to do during redefinition? -+ // FIXME: (DCEVM) what to do during redefinition? - if (!DumpSharedSpaces) { - k = SystemDictionaryShared::lookup_from_stream(class_name, - class_loader, -@@ -1989,7 +1990,7 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) { - } - } - --// Enhanced class redefinition -+// (DCEVM) - remove from klass hierarchy - void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { - assert(k != NULL, "just checking"); - -@@ -1997,6 +1998,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { - k->remove_from_sibling_list(); - } - -+// (DCEVM) - void SystemDictionary::update_constraints_after_redefinition() { - constraints()->update_after_redefinition(); - } -diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp -index 0fefc5da478..875a6dc854f 100644 ---- a/src/hotspot/share/gc/shared/space.cpp -+++ b/src/hotspot/share/gc/shared/space.cpp -@@ -828,7 +828,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, - size_t forward_size = size; - - // (DCEVM) There is a new version of the class of q => different size -- if (oop(q)->klass()->new_version() != NULL && oop(q)->klass()->new_version()->update_information() != NULL) { -+ if (oop(q)->klass()->new_version() != NULL) { - - size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); - assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp -index 8e3722b01b1..875c3fdf319 100644 ---- a/src/hotspot/share/gc/shared/space.inline.hpp -+++ b/src/hotspot/share/gc/shared/space.inline.hpp -@@ -209,6 +209,7 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - // see if this is the first dead region. - if (first_dead == NULL) { - first_dead = cur_obj; -+ force_forward = true; - } - } - -@@ -370,7 +371,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti - } else { - MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); - } -- oop(compaction_top)->init_mark(); -+ oop(compaction_top)->init_mark_raw(); - assert(oop(compaction_top)->klass() != NULL, "should have a class"); - - debug_only(prev_obj = cur_obj); -diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp -index ed15db841c6..3425e3f893d 100644 ---- a/src/hotspot/share/interpreter/linkResolver.cpp -+++ b/src/hotspot/share/interpreter/linkResolver.cpp -@@ -1400,6 +1400,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, - assert(resolved_method->can_be_statically_bound(), "cannot override this method"); - selected_method = resolved_method; - } else { -+ // TODO: (DCEVM) explain - assert(recv_klass->is_subtype_of(resolved_method->method_holder()), "receiver and resolved method holder are inconsistent"); - selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); - } -diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp -index 1f3f746b2b7..d38cd348e1b 100644 ---- a/src/hotspot/share/memory/universe.cpp -+++ b/src/hotspot/share/memory/universe.cpp -@@ -178,7 +178,7 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { - #define DO_PRIMITIVE_MIRROR(m) \ - f->do_oop((oop*) &m); - --// FIXME: This method should iterate all pointers that are not within heap objects. -+// FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects. - void Universe::root_oops_do(OopClosure *oopClosure) { - - class AlwaysTrueClosure: public BoolObjectClosure { -@@ -205,7 +205,7 @@ void Universe::root_oops_do(OopClosure *oopClosure) { - CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); - CodeCache::blobs_do(&blobClosure); - StringTable::oops_do(oopClosure); -- -+ - // (DCEVM) TODO: Check if this is correct? - //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); - //Management::oops_do(oopClosure); -diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp -index ac1c7d397e8..79a38dbeff0 100644 ---- a/src/hotspot/share/oops/cpCache.cpp -+++ b/src/hotspot/share/oops/cpCache.cpp -@@ -450,8 +450,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& - if (has_appendix) { - const int appendix_index = f2_as_index(); - assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); -- // FIXME (DCEVM) relaxing for now... -- //assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); -+ assert(AllowEnhancedClassRedefinition || resolved_references->obj_at(appendix_index) == NULL, "init just once"); - resolved_references->obj_at_put(appendix_index, appendix()); - } - -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index 51bee899aa9..994fc8a3bc8 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -199,6 +199,7 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { - // able to perform that loading but we can't exclude the compiler threads from - // executing this logic. But it should actually be impossible to trigger loading here. - Klass* k2 = _constants->klass_at(cp_index, THREAD); -+ k2 = k2->newest_version(); - assert(!HAS_PENDING_EXCEPTION || PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass()), - "Exceptions should not be possible here"); - if (k2 == k) { -@@ -1307,6 +1308,15 @@ void InstanceKlass::init_implementor() { - } - } - -+// (DCEVM) - init_implementor() for dcevm -+void InstanceKlass::init_implementor_from_redefine() { -+ assert(is_interface(), "not interface"); -+ Klass** addr = adr_implementor(); -+ assert(addr != NULL, "null addr"); -+ if (addr != NULL) { -+ *addr = NULL; -+ } -+} - - void InstanceKlass::process_interfaces(Thread *thread) { - // link this class into the implementors list of every interface it implements -@@ -1364,6 +1374,8 @@ bool InstanceKlass::implements_interface(Klass* k) const { - return false; - } - -+ -+// (DCEVM) - bool InstanceKlass::implements_interface_any_version(Klass* k) const { - k = k->newest_version(); - if (this->newest_version() == k) return true; -@@ -1642,10 +1654,8 @@ void InstanceKlass::methods_do(void f(Method* method)) { - } - } - --/** -- Update information contains mapping of fields from old class to the new class. -- Info is stored on HEAP, you need to call clear_update_information to free the space. --*/ -+// (DCEVM) Update information contains mapping of fields from old class to the new class. -+// Info is stored on HEAP, you need to call clear_update_information to free the space. - void InstanceKlass::store_update_information(GrowableArray &values) { - int *arr = NEW_C_HEAP_ARRAY(int, values.length(), mtClass); - for (int i = 0; i < values.length(); i++) { -@@ -2341,7 +2351,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { - - void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { - dependencies().remove_dependent_nmethod(nm); -- // (DCEVM) Hack as dependencies get wrong version of Klass* -+ // FIXME: (DCEVM) Hack as dependencies get wrong version of Klass* - // if (this->old_version() != NULL) { - // InstanceKlass::cast(this->old_version())->remove_dependent_nmethod(nm, true); - // return; -@@ -2352,6 +2362,7 @@ void InstanceKlass::clean_dependency_context() { - dependencies().clean_unloading_dependents(); - } - -+// DCEVM - update jmethod ids - bool InstanceKlass::update_jmethod_id(Method* method, jmethodID newMethodID) { - size_t idnum = (size_t)method->method_idnum(); - jmethodID* jmeths = methods_jmethod_ids_acquire(); -@@ -3767,6 +3778,7 @@ void InstanceKlass::verify_on(outputStream* st) { - } - - guarantee(sib->is_klass(), "should be klass"); -+ // TODO: (DCEVM) explain - guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); - } - -diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp -index aa3d38d95e0..6ead9426728 100644 ---- a/src/hotspot/share/oops/instanceKlass.hpp -+++ b/src/hotspot/share/oops/instanceKlass.hpp -@@ -1045,6 +1045,7 @@ public: - int nof_implementors() const; - void add_implementor(Klass* k); // k is a new class that implements this interface - void init_implementor(); // initialize -+ void init_implementor_from_redefine(); // initialize - - // link this class into the implementors list of every interface it implements - void process_interfaces(Thread *thread); -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 83c0952de37..92ce6c27b8a 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -1,4 +1,4 @@ --/* -+ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * -@@ -28,6 +28,7 @@ - #include "classfile/metadataOnStackMark.hpp" - #include "classfile/systemDictionary.hpp" - #include "classfile/verifier.hpp" -+#include "classfile/dictionary.hpp" - #include "interpreter/oopMapCache.hpp" - #include "interpreter/rewriter.hpp" - #include "logging/logStream.hpp" -@@ -35,7 +36,7 @@ - #include "memory/metaspaceShared.hpp" - #include "memory/resourceArea.hpp" - #include "memory/iterator.inline.hpp" --#include "gc/serial/markSweep.hpp" // FIXME: other GC? -+#include "gc/serial/markSweep.hpp" - #include "oops/fieldStreams.hpp" - #include "oops/klassVtable.hpp" - #include "oops/oop.inline.hpp" -@@ -48,6 +49,7 @@ - #include "runtime/deoptimization.hpp" - #include "runtime/jniHandles.inline.hpp" - #include "runtime/relocator.hpp" -+#include "runtime/fieldDescriptor.inline.hpp" - #include "utilities/bitMap.inline.hpp" - #include "prims/jvmtiThreadState.inline.hpp" - #include "utilities/events.hpp" -@@ -64,21 +66,19 @@ int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; - int VM_EnhancedRedefineClasses::_added_methods_length = 0; - Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; - --/** -- * Create new instance of enhanced class redefiner. -- * -- * This class implements VM_GC_Operation - the usual usage should be: -- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -- * VMThread::execute(&op); -- * Which -- * -- * @param class_count size of class_defs -- * @param class_defs class definition - either new class or redefined class -- * note that this is not the final array of classes to be redefined -- * we need to scan for all affected classes (e.g. subclasses) and -- * caculcate redefinition for them as well. -- * @param class_load_kind always jvmti_class_load_kind_redefine -- */ -+// -+// Create new instance of enhanced class redefiner. -+// -+// This class implements VM_GC_Operation - the usual usage should be: -+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+// VMThread::execute(&op); -+// Which -+// - class_count size of class_defs -+// - class_defs class definition - either new class or redefined class -+// note that this is not the final array of classes to be redefined -+// we need to scan for all affected classes (e.g. subclasses) and -+// caculcate redefinition for them as well. -+// @param class_load_kind always jvmti_class_load_kind_redefine - VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : - VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { - _affected_klasses = NULL; -@@ -94,12 +94,10 @@ static inline InstanceKlass* get_ik(jclass def) { - return InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); - } - --/** -- * Start the redefinition: -- * - Load new class definitions - @see load_new_class_versions -- * - Start mark&sweep GC. -- * @return true if success, otherwise all chnages are rollbacked. -- */ -+// Start the redefinition: -+// - Load new class definitions - @see load_new_class_versions -+// - Start mark&sweep GC. -+// - true if success, otherwise all chnages are rollbacked. - bool VM_EnhancedRedefineClasses::doit_prologue() { - - if (_class_count == 0) { -@@ -172,9 +170,7 @@ bool VM_EnhancedRedefineClasses::doit_prologue() { - return true; - } - --/** -- * Closer for static fields - copy value from old class to the new class. -- */ -+// Closer for static fields - copy value from old class to the new class. - class FieldCopier : public FieldClosure { - public: - void do_field(fieldDescriptor* fd) { -@@ -222,18 +218,18 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { - // TODO comment - struct StoreBarrier { - // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store -- template static void oop_store(T* p, oop v) { HeapAccess<>::oop_store(p, v); } -+ template static void oop_store_not_null(T* p, oop v) { HeapAccess::oop_store(p, v); } -+ template static void oop_store(T* p) { HeapAccess<>::oop_store(p, oop(NULL)); } - }; - - - // TODO comment - struct StoreNoBarrier { -- template static void oop_store(T* p, oop v) { RawAccess::oop_store(p, v); } -+ template static void oop_store_not_null(T* p, oop v) { RawAccess::oop_store(p, v); } -+ template static void oop_store(T* p) { RawAccess<>::oop_store(p, oop(NULL)); } - }; - --/** -- Closure to scan all heap objects and update method handles --*/ -+// Closure to scan all heap objects and update method handles - template - class ChangePointersOopClosure : public BasicOopIterateClosure { - // import java_lang_invoke_MemberName.* -@@ -242,13 +238,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK, - }; - -- - bool update_member_name(oop obj) { - int flags = java_lang_invoke_MemberName::flags(obj); - int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; - if (MethodHandles::ref_kind_is_method(ref_kind)) { - Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj); -- if (m != NULL && m->method_holder()->new_version() != NULL) { -+ if (m != NULL && m->method_holder()->is_redefining()) { - // Let's try to re-resolve method - InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version()); - Method* new_method = newest->find_method(m->name(), m->signature()); -@@ -257,29 +252,34 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - // Note: we might set NULL at this point, which should force AbstractMethodError at runtime - Thread *thread = Thread::current(); - CallInfo info(new_method, newest, thread); -- Handle objHandle(thread, obj); // TODO : review thread -+ Handle objHandle(thread, obj); - MethodHandles::init_method_MemberName(objHandle, info); - } else { - java_lang_invoke_MemberName::set_method(obj, NULL); - } - } - } else if (MethodHandles::ref_kind_is_field(ref_kind)) { -- Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj); -+ oop clazz = java_lang_invoke_MemberName::clazz(obj); -+ if (clazz == NULL) { -+ return false; -+ } -+ Klass* k = java_lang_Class::as_Klass(clazz); - if (k == NULL) { - return false; // Was cleared before, this MemberName is invalid. - } - -- if (k != NULL && k->new_version() != NULL) { -+ if (k->is_redefining()) { - // Let's try to re-resolve field -+ InstanceKlass* old = InstanceKlass::cast(k->old_version()); - fieldDescriptor fd; - int offset = java_lang_invoke_MemberName::vmindex(obj); - bool is_static = MethodHandles::ref_kind_is_static(ref_kind); -- InstanceKlass* ik = InstanceKlass::cast(k); -- if (ik->find_local_field_from_offset(offset, is_static, &fd)) { -- InstanceKlass* newest = InstanceKlass::cast(k->newest_version()); -+ InstanceKlass* ik_old = InstanceKlass::cast(old); -+ if (ik_old->find_local_field_from_offset(offset, is_static, &fd)) { -+ InstanceKlass* ik_new = InstanceKlass::cast(k->newest_version()); - fieldDescriptor fd_new; -- if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) { -- Handle objHandle(Thread::current(), obj); // TODO : review thread -+ if (ik_new->find_local_field(fd.name(), fd.signature(), &fd_new)) { -+ Handle objHandle(Thread::current(), obj); - MethodHandles::init_field_MemberName(objHandle, fd_new, MethodHandles::ref_kind_is_setter(ref_kind)); - } else { - // Matching field is not found in new version, not much we can do here. -@@ -288,7 +288,7 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - // Eventually, we probably want to replace them with something more meaningful, - // like instance throwing NoSuchFieldError or DMH that will resort to dynamic - // field resolution (with possibility of type conversion) -- java_lang_invoke_MemberName::set_method(obj, NULL); -+ java_lang_invoke_MemberName::set_clazz(obj, NULL); - java_lang_invoke_MemberName::set_vmindex(obj, 0); - return false; - } -@@ -301,6 +301,9 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - bool update_direct_method_handle(oop obj) { - // Always update member name first. - oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj); -+ if (mem_name == NULL) { -+ return true; -+ } - if (!update_member_name(mem_name)) { - return false; - } -@@ -332,25 +335,30 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - if (obj == NULL) { - return; - } -+ bool oop_updated = false; - if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) { - Klass* klass = java_lang_Class::as_Klass(obj); - if (klass != NULL && klass->is_instance_klass()) { - assert(obj == InstanceKlass::cast(klass)->java_mirror(), "just checking"); - if (klass->new_version() != NULL) { - obj = InstanceKlass::cast(klass->new_version())->java_mirror(); -- S::oop_store(p, obj); -+ S::oop_store_not_null(p, obj); -+ oop_updated = true; - } - } - } - -+ - // JSR 292 support, uptade java.lang.invoke.MemberName instances - if (java_lang_invoke_MemberName::is_instance(obj)) { -- update_member_name(obj); -+ if (oop_updated) { -+ update_member_name(obj); -+ } - } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) { - if (!update_direct_method_handle(obj)) { - // DMH is no longer valid, replace it with null reference. - // See note above. We probably want to replace this with something more meaningful. -- S::oop_store(p, NULL); -+ S::oop_store(p); - } - } - } -@@ -364,14 +372,12 @@ class ChangePointersOopClosure : public BasicOopIterateClosure { - } - }; - --/** -- * Closure to scan all objects on heap for objects of changed classes -- * - if the fields are compatible, only update class definition reference -- * - otherwise if the new object size is smaller then old size, reshufle -- * the fields and fill the gap with "dead_space" -- * - otherwise set the _needs_instance_update flag, we need to do full GC -- * and reshuffle object positions durring mark&sweep -- */ -+// Closure to scan all objects on heap for objects of changed classes -+// - if the fields are compatible, only update class definition reference -+// - otherwise if the new object size is smaller then old size, reshufle -+// the fields and fill the gap with "dead_space" -+// - otherwise set the _needs_instance_update flag, we need to do full GC -+// and reshuffle object positions durring mark&sweep - class ChangePointersObjectClosure : public ObjectClosure { - private: - -@@ -440,22 +446,19 @@ public: - }; - - --/** -- Main transformation method - runs in VM thread. -- -- - UseSharedSpaces - TODO what does it mean? -- - for each sratch class call redefine_single_class -- - clear code cache (flush_dependent_code) -- - iterate the heap and update object defintions, check it old/new class fields -- are compatible. If new class size is smaller then old, it can be solved directly here. -- - iterate the heap and update method handles to new version -- - Swap marks to have same hashcodes -- - copy static fields -- - notify JVM of the modification --*/ -+// Main transformation method - runs in VM thread. -+// - for each scratch class call redefine_single_class -+// - clear code cache (flush_dependent_code) -+// - iterate the heap and update object definitions, check it old/new class fields -+// are compatible. If new class size is smaller then old, it can be solved directly here. -+// - iterate the heap and update method handles to new version -+// - Swap marks to have same hashcodes -+// - copy static fields -+// - notify JVM of the modification - void VM_EnhancedRedefineClasses::doit() { - Thread *thread = Thread::current(); - -+#if INCLUDE_CDS - if (UseSharedSpaces) { - // Sharing is enabled so we remap the shared readonly space to - // shared readwrite, private just in case we need to redefine -@@ -467,10 +470,13 @@ void VM_EnhancedRedefineClasses::doit() { - return; - } - } -+#endif - - // Mark methods seen on stack and everywhere else so old methods are not - // cleaned up if they're on the stack. -- MetadataOnStackMark md_on_stack(true); -+ -+ // FIXME: fails in enhanced redefinition -+ // MetadataOnStackMark md_on_stack(true); - HandleMark hm(thread); // make sure any handles created are deleted - // before the stack walk again. - -@@ -479,12 +485,19 @@ void VM_EnhancedRedefineClasses::doit() { - } - - // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) -- flush_dependent_code(NULL, thread); -+ // if (_max_redefinition_flags > Klass::ModifyClass) { -+ flush_dependent_code(NULL, thread); -+ // } -+ -+ // Adjust constantpool caches for all classes that reference methods of the evolved class. -+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); -+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); -+ - - // JSR-292 support - if (_any_class_has_resolved_methods) { - bool trace_name_printed = false; -- ResolvedMethodTable::adjust_method_entries(&trace_name_printed); -+ ResolvedMethodTable::adjust_method_entries_dcevm(&trace_name_printed); - } - - ChangePointersOopClosure oopClosureNoBarrier; -@@ -554,14 +567,14 @@ void VM_EnhancedRedefineClasses::doit() { - } - } - --// if (objectClosure.needs_instance_update()) { -+ if (objectClosure.needs_instance_update()) { - // Do a full garbage collection to update the instance sizes accordingly - Universe::set_redefining_gc_run(true); - notify_gc_begin(true); - Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); - notify_gc_end(); - Universe::set_redefining_gc_run(false); --// } -+ } - - // Unmark Klass*s as "redefining" - for (int i = 0; i < _new_classes->length(); i++) { -@@ -587,24 +600,32 @@ void VM_EnhancedRedefineClasses::doit() { - // See jvmtiExport.hpp for detailed explanation. - JvmtiExport::set_has_redefined_a_class(); - -- // check_class() is optionally called for product bits, but is -- // always called for non-product bits. - #ifdef PRODUCT - if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { - #endif -- log_trace(redefine, class, obsolete, metadata)("calling check_class"); -- CheckClass check_class(thread); -- ClassLoaderDataGraph::classes_do(&check_class); -+ for (int i=0; i<_affected_klasses->length(); i++) { -+ Klass* the_class = _affected_klasses->at(i); -+ assert(the_class->new_version() != NULL, "Must have been redefined"); -+ Klass* new_version = the_class->new_version(); -+ assert(new_version->new_version() == NULL, "Must be newest version"); -+ -+ if (!(new_version->super() == NULL || new_version->super()->new_version() == NULL)) { -+ new_version->print(); -+ new_version->super()->print(); -+ } -+ assert(new_version->super() == NULL || new_version->super()->new_version() == NULL, "Super class must be newest version"); -+ } -+ log_trace(redefine, class, obsolete, metadata)("calling check_class"); -+ ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do(check_class, thread); - #ifdef PRODUCT - } - #endif -+ - } - --/** -- * Cleanup - runs in JVM thread -- * - free used memory -- * - end GC -- */ -+// Cleanup - runs in JVM thread -+// - free used memory -+// - end GC - void VM_EnhancedRedefineClasses::doit_epilogue() { - VM_GC_Operation::doit_epilogue(); - -@@ -636,11 +657,9 @@ void VM_EnhancedRedefineClasses::doit_epilogue() { - } - } - --/** -- * Exclude java primitives and arrays from redefinition -- * @param klass_mirror pointer to the klass -- * @return true if is modifiable -- */ -+// Exclude java primitives and arrays from redefinition -+// - klass_mirror pointer to the klass -+// - true if is modifiable - bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { - // classes for primitives cannot be redefined - if (java_lang_Class::is_primitive(klass_mirror)) { -@@ -659,17 +678,12 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { - return true; - } - --/** -- Load and link new classes (either redefined or affected by redefinition - subclass, ...) -- -- - find sorted affected classes -- - resolve new class -- - calculate redefine flags (field change, method change, supertype change, ...) -- - calculate modified fields and mapping to old fields -- - link new classes -- -- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. --*/ -+// Load and link new classes (either redefined or affected by redefinition - subclass, ...) -+// - find sorted affected classes -+// - resolve new class -+// - calculate redefine flags (field change, method change, supertype change, ...) -+// - calculate modified fields and mapping to old fields -+// - link new classes - jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - - _affected_klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_class_count, true); -@@ -842,9 +856,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - return JVMTI_ERROR_NONE; - } - --/** -- Calculated the difference between new and old class (field change, method change, supertype change, ...). --*/ -+ // Calculated the difference between new and old class (field change, method change, supertype change, ...). - int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { - int result = Klass::NoRedefinition; - log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); -@@ -1127,14 +1139,11 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ - } - - --/** -- Searches for the class bytecode of the given class and returns it as a byte array. -- -- @param the_class definition of a class, either existing class or new_class -- @param class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. -- @param class_byte_count - size of class_bytes -- @param not_changed - new_class not available or same as current class --*/ -+// Searches for the class bytecode of the given class and returns it as a byte array. -+// - the_class definition of a class, either existing class or new_class -+// - class_bytes - if the class is redefined, it contains new class definition, otherwise just original class bytecode. -+// - class_byte_count - size of class_bytes -+// - not_changed - new_class not available or same as current class - jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed) { - - *not_changed = false; -@@ -1177,11 +1186,9 @@ jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class - return JVMTI_ERROR_NONE; - } - --/** -- Calculate difference between non static fields of old and new class and store the info into new class: -- instanceKlass->store_update_information -- instanceKlass->copy_backwards --*/ -+// Calculate difference between non static fields of old and new class and store the info into new class: -+// instanceKlass->store_update_information -+// instanceKlass->copy_backwards - void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) { - - class CalculateFieldUpdates : public FieldClosure { -@@ -1273,29 +1280,26 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne - GrowableArray result = cl.finish(); - ik->store_update_information(result); - ik->set_copying_backwards(cl.does_copy_backwards()); --/* TODO logging -- if (RC_TRACE_ENABLED(0x00000001)) { -- RC_TRACE(0x00000001, ("Instance update information for %s:", new_version->name()->as_C_string())); -+ if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -+ log_trace(redefine, class, obsolete, metadata)("Instance update information for %s:", new_version->name()->as_C_string()); - if (cl.does_copy_backwards()) { -- RC_TRACE(0x00000001, ("\tDoes copy backwards!")); -+ log_trace(redefine, class, obsolete, metadata)("\tDoes copy backwards!"); - } - for (int i=0; i 0) { -- RC_TRACE(0x00000001, ("\t%d COPY from %d", curNum, result.at(i + 1))); -+ log_trace(redefine, class, obsolete, metadata)("\t%d COPY from %d", curNum, result.at(i + 1)); - i++; - } else { -- RC_TRACE(0x00000001, ("\tEND")); -+ log_trace(redefine, class, obsolete, metadata)("\tEND"); - } - } -- }*/ -+ } - } - --/** -- Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. --*/ -+// Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. - void VM_EnhancedRedefineClasses::rollback() { - log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); - ClassLoaderDataGraph::rollback_redefinition(); -@@ -1364,92 +1368,41 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { - } - } - --// Unevolving classes may point to methods of the_class directly -+// Unevolving classes may point to old methods directly - // from their constant pool caches, itables, and/or vtables. We --// use the ClassLoaderDataGraph::classes_do() facility and this helper --// to fix up these pointers. --// Adjust cpools and vtables closure -+// use the SystemDictionary::classes_do() facility and this helper -+// to fix up these pointers. Additional field offsets and vtable indices -+// in the constant pool cache entries are fixed. -+// -+// Note: We currently don't support updating the vtable in -+// arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. - void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { -- // This is a very busy routine. We don't want too much tracing -- // printed out. -- bool trace_name_printed = false; -- InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop); -- -- // If the class being redefined is java.lang.Object, we need to fix all -- // array class vtables also -- if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { -- k->vtable().adjust_method_entries(the_class, &trace_name_printed); -- } else if (k->is_instance_klass()) { -- HandleMark hm(_thread); -- InstanceKlass *ik = InstanceKlass::cast(k); -+ if (!k->is_instance_klass()) { -+ return; -+ } - -- // HotSpot specific optimization! HotSpot does not currently -- // support delegation from the bootstrap class loader to a -- // user-defined class loader. This means that if the bootstrap -- // class loader is the initiating class loader, then it will also -- // be the defining class loader. This also means that classes -- // loaded by the bootstrap class loader cannot refer to classes -- // loaded by a user-defined class loader. Note: a user-defined -- // class loader can delegate to the bootstrap class loader. -- // -- // If the current class being redefined has a user-defined class -- // loader as its defining class loader, then we can skip all -- // classes loaded by the bootstrap class loader. -- bool is_user_defined = -- InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; -- if (is_user_defined && ik->class_loader() == NULL) { -- return; -- } -- -- // Fix the vtable embedded in the_class and subclasses of the_class, -- // if one exists. We discard scratch_class and we don't keep an -- // InstanceKlass around to hold obsolete methods so we don't have -- // any other InstanceKlass embedded vtables to update. The vtable -- // holds the Method*s for virtual (but not final) methods. -- // Default methods, or concrete methods in interfaces are stored -- // in the vtable, so if an interface changes we need to check -- // adjust_method_entries() for every InstanceKlass, which will also -- // adjust the default method vtable indices. -- // We also need to adjust any default method entries that are -- // not yet in the vtable, because the vtable setup is in progress. -- // This must be done after we adjust the default_methods and -- // default_vtable_indices for methods already in the vtable. -- // If redefining Unsafe, walk all the vtables looking for entries. --// FIXME - code from standard redefine - if needed, it should switch to new_class --// if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() --// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() --// || ik->is_subtype_of(_the_class_oop))) { --// // ik->vtable() creates a wrapper object; rm cleans it up --// ResourceMark rm(_thread); --// --// ik->vtable()->adjust_method_entries(the_class, &trace_name_printed); --// ik->adjust_default_methods(the_class, &trace_name_printed); --// } -- -- // If the current class has an itable and we are either redefining an -- // interface or if the current class is a subclass of the_class, then -- // we potentially have to fix the itable. If we are redefining an -- // interface, then we have to call adjust_method_entries() for -- // every InstanceKlass that has an itable since there isn't a -- // subclass relationship between an interface and an InstanceKlass. -- // If redefining Unsafe, walk all the itables looking for entries. --// FIXME - code from standard redefine - if needed, it should switch to new_class --// if (ik->itable_length() > 0 && (_the_class_oop->is_interface() --// || _the_class_oop == SystemDictionary::internal_Unsafe_klass() --// || ik->is_subclass_of(_the_class_oop))) { --// // ik->itable() creates a wrapper object; rm cleans it up --// ResourceMark rm(_thread); --// --// ik->itable()->adjust_method_entries(the_class, &trace_name_printed); --// } -- -- constantPoolHandle other_cp = constantPoolHandle(ik->constants()); -+ HandleMark hm(_thread); -+ InstanceKlass *ik = InstanceKlass::cast(k); -+ -+ constantPoolHandle other_cp = constantPoolHandle(ik->constants()); - - // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. - if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { - ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); - } - -+ // Update implementor if there is only one, in this case implementor() can reference old class -+ if (ik->is_interface()) { -+ Klass* implKlass = ik->implementor(); -+ if (implKlass != NULL && implKlass != ik && implKlass->new_version() != NULL) { -+ InstanceKlass* newest_impl = InstanceKlass::cast(implKlass->newest_version()); -+ ik->init_implementor_from_redefine(); -+ if (newest_impl->implements_interface(ik)) { -+ ik->add_implementor(newest_impl); -+ } -+ } -+ } -+ - for (int i = 0; i < other_cp->length(); i++) { - if (other_cp->tag_at(i).is_klass()) { - Klass* klass = other_cp->resolved_klass_at(i); -@@ -1457,8 +1410,7 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - // Constant pool entry points to redefined class -- update to the new version - other_cp->klass_at_put(i, klass->newest_version()); - } -- klass = other_cp->resolved_klass_at(i); -- assert(klass->new_version() == NULL, "Must be new klass!"); -+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); - } - } - -@@ -1472,7 +1424,6 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - if (RewriteBytecodes) { - ik->methods_do(unpatch_bytecode); - } -- } - } - - // Clean method data for this class -@@ -1519,9 +1470,7 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() { - } - } - --/** -- Set method as obsolete / old / deleted. --*/ -+// Set method as obsolete / old / deleted. - void VM_EnhancedRedefineClasses::check_methods_and_mark_as_obsolete() { - for (int j = 0; j < _matching_methods_length; ++j/*, ++old_index*/) { - Method* old_method = _matching_old_methods[j]; -@@ -1718,8 +1667,14 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) - // All dependencies have been recorded from startup or this is a second or - // subsequent use of RedefineClasses - // FIXME: for now, deoptimize all! -- if (0 && JvmtiExport::all_dependencies_are_recorded()) { -+ if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) { - CodeCache::flush_evol_dependents_on(k_h); -+ Klass* superCl = k_h->super(); -+ // Deoptimize super classes since redefined class can has a new method override -+ while (superCl != NULL && !superCl->is_redefining()) { -+ CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl)); -+ superCl = superCl->super(); -+ } - } else { - CodeCache::mark_all_nmethods_for_deoptimization(); - -@@ -1737,12 +1692,9 @@ void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) - } - } - --/** -- Compare _old_methods and _new_methods arrays and store the result into -- _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods -- -- Setup _old_methods and _new_methods before the call - it should be called for one class only! --*/ -+// Compare _old_methods and _new_methods arrays and store the result into -+// _matching_old_methods, _matching_new_methods, _added_methods, _deleted_methods -+// Setup _old_methods and _new_methods before the call - it should be called for one class only! - void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { - Method* old_method; - Method* new_method; -@@ -1804,19 +1756,6 @@ void VM_EnhancedRedefineClasses::compute_added_deleted_matching_methods() { - assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity"); - } - --/** -- FIXME - swap_annotations is never called, check that annotations work --*/ --void VM_EnhancedRedefineClasses::swap_annotations(InstanceKlass* the_class, -- InstanceKlass* new_class) { -- // FIXME - probably original implementation only -- // Swap annotation fields values -- Annotations* old_annotations = the_class->annotations(); -- the_class->set_annotations(new_class->annotations()); -- new_class->set_annotations(old_annotations); --} -- -- - // Install the redefinition of a class: - // - house keeping (flushing breakpoints and caches, deoptimizing - // dependent compiled code) -@@ -1847,7 +1786,9 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - - // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined - // Deoptimize all compiled code that depends on this class -- // flush_dependent_code(the_class, THREAD); -+// if (_max_redefinition_flags <= Klass::ModifyClass) { -+// flush_dependent_code(the_class, THREAD); -+// } - - _old_methods = the_class->methods(); - _new_methods = new_class->methods(); -@@ -1877,22 +1818,17 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - } - */ - -- // Adjust constantpool caches for all classes that reference methods of the evolved class. -- ClearCpoolCacheAndUnpatch clear_cpool_cache(THREAD); -- ClassLoaderDataGraph::classes_do(&clear_cpool_cache); -- - { - ResourceMark rm(THREAD); - // increment the classRedefinedCount field in the_class and in any - // direct and indirect subclasses of the_class -- increment_class_counter(the_class, THREAD); -+ increment_class_counter(new_class, THREAD); - log_info(redefine, class, load) - ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", -- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10); -+ new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), os::available_memory() >> 10); - Events::log_redefinition(THREAD, "redefined class name=%s, count=%d", -- the_class->external_name(), -- java_lang_Class::classRedefinedCount(the_class->java_mirror())); -- -+ new_class->external_name(), -+ java_lang_Class::classRedefinedCount(new_class->java_mirror())); - } - _timer_rsc_phase2.stop(); - } // end redefine_single_class() -@@ -1901,91 +1837,27 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - // Increment the classRedefinedCount field in the specific InstanceKlass - // and in all direct and indirect subclasses. - void VM_EnhancedRedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { -- oop class_mirror = ik->java_mirror(); -+ oop class_mirror = ik->old_version()->java_mirror(); - Klass* class_oop = java_lang_Class::as_Klass(class_mirror); - int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; -- java_lang_Class::set_classRedefinedCount(class_mirror, new_count); -- -- if (class_oop != _the_class_oop) { -- // _the_class_oop count is printed at end of redefine_single_class() -- log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count); -- } -- -- for (Klass *subk = ik->subklass(); subk != NULL; -- subk = subk->next_sibling()) { -- if (subk->is_instance_klass()) { -- // Only update instanceKlasses -- InstanceKlass *subik = InstanceKlass::cast(subk); -- // recursively do subclasses of the current subclass -- increment_class_counter(subik, THREAD); -- } -- } -+ java_lang_Class::set_classRedefinedCount(ik->java_mirror(), new_count); - } - --// FIXME - class check is currently disabled --void VM_EnhancedRedefineClasses::CheckClass::do_klass(Klass* k) { -- return; -- bool no_old_methods = true; // be optimistic -- -- // Both array and instance classes have vtables. -- // a vtable should never contain old or obsolete methods -- ResourceMark rm(_thread); -- if (k->vtable_length() > 0 && -- !k->vtable().check_no_old_or_obsolete_entries()) { -- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -- log_trace(redefine, class, obsolete, metadata) -- ("klassVtable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -- k->signature_name()); -- k->vtable().dump_vtable(); -- } -- no_old_methods = false; -- } -- -- if (k->is_instance_klass()) { -- HandleMark hm(_thread); -- InstanceKlass *ik = InstanceKlass::cast(k); -+void VM_EnhancedRedefineClasses::check_class(InstanceKlass* ik, TRAPS) { -+ if (ik->is_instance_klass() && ik->old_version() != NULL) { -+ HandleMark hm(THREAD); - -- // an itable should never contain old or obsolete methods -- if (ik->itable_length() > 0 && -- !ik->itable().check_no_old_or_obsolete_entries()) { -- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -- log_trace(redefine, class, obsolete, metadata) -- ("klassItable::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -- ik->signature_name()); -- ik->itable().dump_itable(); -- } -- no_old_methods = false; -- } -- -- // the constant pool cache should never contain non-deleted old or obsolete methods -- if (ik->constants() != NULL && -- ik->constants()->cache() != NULL && -- !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { -- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -- log_trace(redefine, class, obsolete, metadata) -- ("cp-cache::check_no_old_or_obsolete_entries failure -- OLD or OBSOLETE method found -- class: %s", -- ik->signature_name()); -- ik->constants()->cache()->dump_cache(); -- } -- no_old_methods = false; -- } -- } -+ assert(ik->new_version() == NULL, "must be latest version in system dictionary"); - -- // print and fail guarantee if old methods are found. -- if (!no_old_methods) { -- if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -- dump_methods(); -- } else { -- log_trace(redefine, class)("Use the '-Xlog:redefine+class*:' option " -- "to see more info about the following guarantee() failure."); -+ if (ik->vtable_length() > 0) { -+ ResourceMark rm(THREAD); -+ assert(ik->vtable().check_no_old_or_obsolete_entries(), "old method found"); -+ ik->vtable().verify(tty, true); - } -- guarantee(false, "OLD and/or OBSOLETE method(s) found"); - } - } - --/** -- * Logging of all methods (old, new, changed, ...) -- */ -+// Logging of all methods (old, new, changed, ...) - void VM_EnhancedRedefineClasses::dump_methods() { - int j; - log_trace(redefine, class, dump)("_old_methods --"); -@@ -2045,18 +1917,7 @@ void VM_EnhancedRedefineClasses::dump_methods() { - } - } - --// TODO - is it called anywhere? --void VM_EnhancedRedefineClasses::print_on_error(outputStream* st) const { -- VM_Operation::print_on_error(st); -- if (_the_class_oop != NULL) { -- ResourceMark rm; -- st->print_cr(", redefining class %s", _the_class_oop->external_name()); -- } --} -- --/** -- Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. --*/ -+// Helper class to traverse all loaded classes and figure out if the class is affected by redefinition. - class AffectedKlassClosure : public KlassClosure { - private: - GrowableArray* _affected_klasses; -@@ -2087,7 +1948,7 @@ class AffectedKlassClosure : public KlassClosure { - log_trace(redefine, class, load)("found affected class: %s", klass->name()->as_C_string()); - klass->set_redefinition_flag(Klass::MarkedAsAffected); - _affected_klasses->append(klass); -- return; -+ return; - } - } - -@@ -2104,10 +1965,8 @@ class AffectedKlassClosure : public KlassClosure { - } - }; - --/** -- Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). -- Affected classes are stored in _affected_klasses and parent classes always precedes child class. --*/ -+// Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change). -+// Affected classes are stored in _affected_klasses and parent classes always precedes child class. - jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { - for (int i = 0; i < _class_count; i++) { - InstanceKlass* klass_handle = get_ik(_class_defs[i].klass); -@@ -2119,7 +1978,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { - - // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) - AffectedKlassClosure closure(_affected_klasses); -- // TODO: j10 - review chancge from SystemDictionary::classes_do(&closure); -+ // Updated in j10, from original SystemDictionary::classes_do - ClassLoaderDataGraph::dictionary_classes_do(&closure); - log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); - -@@ -2135,9 +1994,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { - return JVMTI_ERROR_NONE; - } - --/** -- Pairs of class dependencies (for topological sort) --*/ -+// Pairs of class dependencies (for topological sort) - struct KlassPair { - const Klass* _left; - const Klass* _right; -@@ -2150,15 +2007,11 @@ static bool match_second(void* value, KlassPair elem) { - return elem._right == value; - } - --/** -- For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. -- First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). -- Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) -- -- For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. -- -- TODO - the class file is potentionally parsed multiple times - introduce a cache? --*/ -+// For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. -+// First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). -+// Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) -+// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. -+// TODO - the class file is potentionally parsed multiple times - introduce a cache? - jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { - ResourceMark mark(THREAD); - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index b712d69a193..60b62c3170a 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -16,6 +16,8 @@ - * 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. -@@ -30,21 +32,19 @@ - #include "memory/resourceArea.hpp" - #include "oops/objArrayKlass.hpp" - #include "oops/objArrayOop.hpp" --#include "runtime/vm_operations.hpp" - #include "gc/shared/vmGCOperations.hpp" - #include "../../../java.base/unix/native/include/jni_md.h" - --/** -- * Enhanced class redefiner. -- * -- * This class implements VM_GC_Operation - the usual usage should be: -- * VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -- * VMThread::execute(&op); -- * Which in turn runs: -- * - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions -- * - doit() - main redefition, adjust existing objects on the heap, clear caches -- * - doit_epilogue() - cleanup --*/ -+// -+// Enhanced class redefiner. -+// -+// This class implements VM_GC_Operation - the usual usage should be: -+// VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); -+// VMThread::execute(&op); -+// Which in turn runs: -+// - doit_prologue() - calculate all affected classes (add subclasses etc) and load new class versions -+// - doit() - main redefition, adjust existing objects on the heap, clear caches -+// - doit_epilogue() - cleanup - class VM_EnhancedRedefineClasses: public VM_GC_Operation { - private: - // These static fields are needed by ClassLoaderDataGraph::classes_do() -@@ -69,17 +69,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // RetransformClasses. Indicate which. - JvmtiClassLoadKind _class_load_kind; - -- // _index_map_count is just an optimization for knowing if -- // _index_map_p contains any entries. -- int _index_map_count; -- intArray * _index_map_p; -- -- // _operands_index_map_count is just an optimization for knowing if -- // _operands_index_map_p contains any entries. -- int _operands_cur_length; -- int _operands_index_map_count; -- intArray * _operands_index_map_p; -- - GrowableArray* _new_classes; - jvmtiError _res; - -@@ -103,17 +92,15 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - - // These routines are roughly in call order unless otherwise noted. - -- /** -- Load and link new classes (either redefined or affected by redefinition - subclass, ...) -- -- - find sorted affected classes -- - resolve new class -- - calculate redefine flags (field change, method change, supertype change, ...) -- - calculate modified fields and mapping to old fields -- - link new classes -- -- The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. -- */ -+ // Load and link new classes (either redefined or affected by redefinition - subclass, ...) -+ // -+ // - find sorted affected classes -+ // - resolve new class -+ // - calculate redefine flags (field change, method change, supertype change, ...) -+ // - calculate modified fields and mapping to old fields -+ // - link new classes -+ // -+ // The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays. - jvmtiError load_new_class_versions(TRAPS); - - // Searches for all affected classes and performs a sorting such tha -@@ -144,15 +131,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // Install the redefinition of a class - void redefine_single_class(InstanceKlass* new_class_oop, TRAPS); - -- void swap_annotations(InstanceKlass* new_class, -- InstanceKlass* scratch_class); -- - // Increment the classRedefinedCount field in the specific InstanceKlass - // and in all direct and indirect subclasses. - void increment_class_counter(InstanceKlass *ik, TRAPS); - - void flush_dependent_code(InstanceKlass* k_h, TRAPS); - -+ static void check_class(InstanceKlass* k_oop, TRAPS); -+ - static void dump_methods(); - - // Check that there are no old or obsolete methods -@@ -195,8 +181,5 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // Modifiable test must be shared between IsModifiableClass query - // and redefine implementation - static bool is_modifiable_class(oop klass_mirror); -- -- // Error printing -- void print_on_error(outputStream* st) const; - }; - #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES2_HPP -diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp -index a1ea25de1ea..6ea6f2fa902 100644 ---- a/src/hotspot/share/prims/jvmtiImpl.cpp -+++ b/src/hotspot/share/prims/jvmtiImpl.cpp -@@ -248,8 +248,10 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { - Symbol* m_signature = _method->signature(); - - // (DCEVM) Go through old versions of method -- for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { -- (m->*meth_act)(_bci); -+ if (AllowEnhancedClassRedefinition) { -+ for (Method* m = _method->old_version(); m != NULL; m = m->old_version()) { -+ (m->*meth_act)(_bci); -+ } - } - - // search previous versions if they exist -diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp -index 91d6d80e75b..122bb8c186b 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.cpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp -@@ -384,6 +384,69 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { - } - #endif // INCLUDE_JVMTI - -+// (DCEVM) It is called at safepoint only for RedefineClasses -+void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) { -+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); -+ // For each entry in RMT, change to new method -+ GrowableArray* oops_to_add = new GrowableArray(); -+ -+ for (int i = 0; i < _the_table->table_size(); ++i) { -+ for (ResolvedMethodEntry* entry = _the_table->bucket(i); -+ entry != NULL; -+ entry = entry->next()) { -+ -+ oop mem_name = entry->object_no_keepalive(); -+ // except ones removed -+ if (mem_name == NULL) { -+ continue; -+ } -+ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); -+ -+ if (old_method->is_old()) { -+ -+ // Method* new_method; -+ if (old_method->is_deleted()) { -+ // FIXME:(DCEVM) - check if exception can be thrown -+ // new_method = Universe::throw_no_such_method_error(); -+ continue; -+ } -+ -+ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); -+ Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); -+ -+ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); -+ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -+ assert(old_method != newer_method, "sanity check"); -+ -+ if (_the_table->lookup(newer_method) != NULL) { -+ // old method was already adjusted if new method exists in _the_table -+ continue; -+ } -+ -+ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); -+ java_lang_invoke_ResolvedMethodName::set_vmholder_offset(mem_name, newer_method); -+ -+ newer_klass->set_has_resolved_methods(); -+ oops_to_add->append(mem_name); -+ -+ ResourceMark rm; -+ if (!(*trace_name_printed)) { -+ log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); -+ *trace_name_printed = true; -+ } -+ log_debug(redefine, class, update, constantpool) -+ ("ResolvedMethod method update: %s(%s)", -+ newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); -+ } -+ } -+ for (int i = 0; i < oops_to_add->length(); i++) { -+ oop mem_name = oops_to_add->at(i); -+ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); -+ _the_table->basic_add(method, Handle(Thread::current(), mem_name)); -+ } -+ } -+} -+ - // Verification - class VerifyResolvedMethod : StackObj { - public: -diff --git a/src/hotspot/share/prims/resolvedMethodTable.hpp b/src/hotspot/share/prims/resolvedMethodTable.hpp -index 794a8651804..143922b50b8 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.hpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp -@@ -77,6 +77,7 @@ public: - - // JVMTI Support - It is called at safepoint only for RedefineClasses - JVMTI_ONLY(static void adjust_method_entries(bool * trace_name_printed);) -+ JVMTI_ONLY(static void adjust_method_entries_dcevm(bool * trace_name_printed);) - - // Debugging - static size_t items_count(); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch b/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch deleted file mode 100644 index 4fd2678b21df..000000000000 --- a/jb/project/tools/patches/dcevm/0003-Fix-class-cast-exception-on-redefinition-of-class-A-.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 960dafbeeba190911955c208b611fecc15d66738 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Wed, 11 Mar 2020 14:19:34 +0100 -Subject: [PATCH 03/34] Fix class cast exception on redefinition of class A, - that is superclass of B that has anonymous class C - ---- - src/hotspot/share/oops/instanceKlass.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index 994fc8a3bc8..3be3a09ef8f 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -953,7 +953,10 @@ bool InstanceKlass::link_class_impl(TRAPS) { - - if (!is_linked()) { - if (!is_rewritten()) { -- { -+ // (DCEVM): If class A is being redefined and class B->A (B is extended from A) and B is host class of anonymous class C -+ // then second redefinition fails with cannot cast klass exception. So we currently turn off bytecode verification -+ // on redefinition. -+ if (!AllowEnhancedClassRedefinition || !newest_version()->is_redefining()) { - bool verify_ok = verify_code(THREAD); - if (!verify_ok) { - return false; --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch b/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch deleted file mode 100644 index cafc41d1babc..000000000000 --- a/jb/project/tools/patches/dcevm/0004-HotswapAgent-integration.patch +++ /dev/null @@ -1,1086 +0,0 @@ -From 68dcf3c0d26d717ee9d2d2404848dffb69fee8d4 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Wed, 14 Nov 2018 21:20:08 +0100 -Subject: [PATCH 04/34] HotswapAgent integration - -It include: - -- option to compile DCEVM only version with -DDCEVM_ONLY added -to CFLAGS (bash configure --with-extra-cflags="-DDCEVM_ONLY"), by -default compilation goes with HotswapAgent - -Allow ha class initializer calls - -Add --add-opens for necessary modules/packages -- java.base/java.lang - for reflection access to Proxy.proxyCache -- java.base/jdk.internal.loader - for access proxyCache class -- java.desktop/java.beans - for reflection access to Introspector -- java.desktop/com.sun.beans -- java.base/java.io -- com.sun.beans.util - -Open jdk module to access ClassInfo.CACHE - -- be quiet if HotswapAgent is not found in lib/, it is compatible with -old DCEVM -- disable HotswapAgent for -Xshare:dump -- disable HotswapAgent in jvm tools -- disable HotswapAgent in keytool ---- - make/launcher/Launcher-java.base.gmk | 93 ++++++++++++++++ - make/launcher/Launcher-java.security.jgss.gmk | 43 ++++++++ - make/launcher/Launcher-jdk.aot.gmk | 58 ++++++++++ - make/launcher/Launcher-jdk.compiler.gmk | 50 +++++++++ - make/launcher/Launcher-jdk.jcmd.gmk | 74 +++++++++++++ - make/launcher/Launcher-jdk.jconsole.gmk | 35 ++++++ - make/launcher/Launcher-jdk.jstatd.gmk | 34 ++++++ - make/launcher/Launcher-jdk.pack.gmk | 101 ++++++++++++++++++ - make/launcher/Launcher-jdk.rmic.gmk | 32 ++++++ - .../Launcher-jdk.scripting.nashorn.shell.gmk | 33 ++++++ - make/modules/java.rmi/Launcher.gmk | 2 + - make/modules/java.scripting/Launcher.gmk | 3 +- - make/modules/jdk.hotspot.agent/Launcher.gmk | 1 + - make/modules/jdk.jartool/Launcher.gmk | 2 + - make/modules/jdk.javadoc/Launcher.gmk | 3 +- - make/modules/jdk.jdeps/Launcher.gmk | 3 + - make/modules/jdk.jdi/Launcher.gmk | 1 + - make/modules/jdk.jlink/Launcher.gmk | 5 +- - make/modules/jdk.jshell/Launcher.gmk | 1 + - src/hotspot/share/classfile/vmSymbols.hpp | 1 + - .../share/interpreter/linkResolver.cpp | 2 +- - src/hotspot/share/runtime/arguments.cpp | 67 ++++++++++++ - src/hotspot/share/runtime/arguments.hpp | 3 + - src/hotspot/share/runtime/globals.hpp | 12 ++- - .../sun/beans/introspect/package-info.java | 26 +++++ - .../classes/com/sun/beans/package-info.java | 26 +++++ - .../com/sun/beans/util/package-info.java | 26 +++++ - .../share/classes/module-info.java | 3 + - 28 files changed, 735 insertions(+), 5 deletions(-) - create mode 100644 make/launcher/Launcher-java.base.gmk - create mode 100644 make/launcher/Launcher-java.security.jgss.gmk - create mode 100644 make/launcher/Launcher-jdk.aot.gmk - create mode 100644 make/launcher/Launcher-jdk.compiler.gmk - create mode 100644 make/launcher/Launcher-jdk.jcmd.gmk - create mode 100644 make/launcher/Launcher-jdk.jconsole.gmk - create mode 100644 make/launcher/Launcher-jdk.jstatd.gmk - create mode 100644 make/launcher/Launcher-jdk.pack.gmk - create mode 100644 make/launcher/Launcher-jdk.rmic.gmk - create mode 100644 make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk - create mode 100644 src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java - create mode 100644 src/java.desktop/share/classes/com/sun/beans/package-info.java - create mode 100644 src/java.desktop/share/classes/com/sun/beans/util/package-info.java - -diff --git a/make/launcher/Launcher-java.base.gmk b/make/launcher/Launcher-java.base.gmk -new file mode 100644 -index 00000000000..38ba29530d8 ---- /dev/null -+++ b/make/launcher/Launcher-java.base.gmk -@@ -0,0 +1,93 @@ -+# -+# Copyright (c) 2011, 2020, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call IncludeCustomExtension, launcher/Launcher-java.base.gmk)) -+ -+JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/common -+JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/launcher/icons -+ -+################################################################################ -+ -+$(eval $(call SetupBuildLauncher, java, \ -+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ -+ LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \ -+ LIBS_windows := user32.lib comctl32.lib, \ -+ EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ -+ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ -+ OPTIMIZATION := HIGH, \ -+)) -+ -+ifeq ($(OPENJDK_TARGET_OS), windows) -+ $(eval $(call SetupBuildLauncher, javaw, \ -+ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ -+ LIBS_windows := user32.lib comctl32.lib, \ -+ EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ -+ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ -+ )) -+endif -+ -+$(eval $(call SetupBuildLauncher, keytool, \ -+ MAIN_CLASS := sun.security.tools.keytool.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+)) -+ -+################################################################################ -+ -+ifeq ($(OPENJDK_TARGET_OS), linux) -+ $(eval $(call SetupJdkExecutable, BUILD_JEXEC, \ -+ NAME := jexec, \ -+ SRC := $(TOPDIR)/src/$(MODULE)/unix/native/launcher, \ -+ INCLUDE_FILES := jexec.c, \ -+ OPTIMIZATION := LOW, \ -+ CFLAGS := $(CFLAGS_JDKEXE) \ -+ -I$(TOPDIR)/src/$(MODULE)/share/native/libjli, \ -+ CFLAGS_linux := -fPIC, \ -+ CFLAGS_solaris := -KPIC, \ -+ LDFLAGS := $(LDFLAGS_JDKEXE), \ -+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \ -+ )) -+ -+ TARGETS += $(BUILD_JEXEC) -+endif -+ -+################################################################################ -+ -+ifneq ($(findstring $(OPENJDK_TARGET_OS), macosx solaris aix linux), ) -+ $(eval $(call SetupJdkExecutable, BUILD_JSPAWNHELPER, \ -+ NAME := jspawnhelper, \ -+ SRC := $(TOPDIR)/src/$(MODULE)/unix/native/jspawnhelper, \ -+ OPTIMIZATION := LOW, \ -+ CFLAGS := $(CFLAGS_JDKEXE) -I$(TOPDIR)/src/$(MODULE)/unix/native/libjava, \ -+ EXTRA_OBJECT_FILES := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc.o, \ -+ LDFLAGS := $(LDFLAGS_JDKEXE), \ -+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE), \ -+ )) -+ -+ TARGETS += $(BUILD_JSPAWNHELPER) -+endif -+ -+################################################################################ -diff --git a/make/launcher/Launcher-java.security.jgss.gmk b/make/launcher/Launcher-java.security.jgss.gmk -new file mode 100644 -index 00000000000..2b856bfccb4 ---- /dev/null -+++ b/make/launcher/Launcher-java.security.jgss.gmk -@@ -0,0 +1,43 @@ -+# -+# Copyright (c) 2011, 2015, 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. -+# -+ -+include LauncherCommon.gmk -+ -+ifeq ($(OPENJDK_TARGET_OS), windows) -+ $(eval $(call SetupBuildLauncher, kinit, \ -+ MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ )) -+ -+ $(eval $(call SetupBuildLauncher, klist, \ -+ MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ )) -+ -+ $(eval $(call SetupBuildLauncher, ktab, \ -+ MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ )) -+endif -diff --git a/make/launcher/Launcher-jdk.aot.gmk b/make/launcher/Launcher-jdk.aot.gmk -new file mode 100644 -index 00000000000..2c52c31a555 ---- /dev/null -+++ b/make/launcher/Launcher-jdk.aot.gmk -@@ -0,0 +1,58 @@ -+# -+# Copyright (c) 2016, 2019, 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. -+# -+ -+include LauncherCommon.gmk -+ -+# The JVMCI exports are needed since JVMCI is normally dynamically exported -+# (see jdk.vm.ci.services.internal.ReflectionAccessJDK::openJVMCITo). -+ -+$(eval $(call SetupBuildLauncher, jaotc, \ -+ MAIN_CLASS := jdk.tools.jaotc.Main, \ -+ EXTRA_JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \ -+ -XX:+DisableHotswapAgent \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.site=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.stack=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.common=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ , \ -+ JAVA_ARGS := --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ -XX:+DisableHotswapAgent \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ -+ -XX:+UnlockExperimentalVMOptions -XX:+UseAOT \ -+ -XX:+CalculateClassFingerprint \ -+ -Djvmci.UseProfilingInformation=false \ -+ -Dgraal.UseExceptionProbability=false \ -+ -Djvmci.Compiler=graal \ -+ --add-modules ALL-DEFAULT \ -+ , \ -+)) -diff --git a/make/launcher/Launcher-jdk.compiler.gmk b/make/launcher/Launcher-jdk.compiler.gmk -new file mode 100644 -index 00000000000..744969546de ---- /dev/null -+++ b/make/launcher/Launcher-jdk.compiler.gmk -@@ -0,0 +1,50 @@ -+# -+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. -+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+# -+# This code is free software; you can redistribute it and/or modify it -+# 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, javac, \ -+ MAIN_CLASS := com.sun.tools.javac.Main, \ -+ JAVA_ARGS := --add-modules ALL-DEFAULT \ -+ -XX:+DisableHotswapAgent, \ -+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, serialver, \ -+ MAIN_CLASS := sun.tools.serialver.SerialVer, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ -+)) -+ -+ifeq ($(ENABLE_SJAVAC), yes) -+ # Build sjavac directly to the exploded image so that it does not get included -+ # into any real images -+ $(eval $(call SetupBuildLauncher, sjavac, \ -+ MAIN_CLASS := com.sun.tools.sjavac.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ -+ OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \ -+ )) -+endif -diff --git a/make/launcher/Launcher-jdk.jcmd.gmk b/make/launcher/Launcher-jdk.jcmd.gmk -new file mode 100644 -index 00000000000..761a52d8466 ---- /dev/null -+++ b/make/launcher/Launcher-jdk.jcmd.gmk -@@ -0,0 +1,74 @@ -+# -+# Copyright (c) 2011, 2019, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, jinfo, \ -+ MAIN_CLASS := sun.tools.jinfo.JInfo, \ -+ JAVA_ARGS := \ -+ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ -+ -XX:+DisableHotswapAgent, \ -+ MACOSX_PRIVILEGED := true, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, jmap, \ -+ MAIN_CLASS := sun.tools.jmap.JMap, \ -+ JAVA_ARGS := \ -+ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \ -+ -XX:+DisableHotswapAgent, \ -+ MACOSX_PRIVILEGED := true, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, jps, \ -+ MAIN_CLASS := sun.tools.jps.Jps, \ -+ JAVA_ARGS := \ -+ -XX:+DisableHotswapAgent, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, jstack, \ -+ MAIN_CLASS := sun.tools.jstack.JStack, \ -+ JAVA_ARGS := \ -+ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -+ -Dsun.jvm.hotspot.debugger.useWindbgDebugger \ -+ -XX:+DisableHotswapAgent, \ -+ MACOSX_PRIVILEGED := true, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, jstat, \ -+ MAIN_CLASS := sun.tools.jstat.Jstat, \ -+ JAVA_ARGS := \ -+ -XX:+DisableHotswapAgent, \ -+)) -+ -+$(eval $(call SetupBuildLauncher, jcmd, \ -+ MAIN_CLASS := sun.tools.jcmd.JCmd, \ -+ JAVA_ARGS := \ -+ -XX:+DisableHotswapAgent, \ -+)) -+ -+# Hook to include the corresponding custom file, if present. -+$(eval $(call IncludeCustomExtension, launcher/Launcher-jdk.jcmd-post.gmk)) -diff --git a/make/launcher/Launcher-jdk.jconsole.gmk b/make/launcher/Launcher-jdk.jconsole.gmk -new file mode 100644 -index 00000000000..5ca6a0c123b ---- /dev/null -+++ b/make/launcher/Launcher-jdk.jconsole.gmk -@@ -0,0 +1,35 @@ -+# -+# Copyright (c) 2011, 2015, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, jconsole, \ -+ MAIN_CLASS := sun.tools.jconsole.JConsole, \ -+ JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \ -+ -Djconsole.showOutputViewer \ -+ -XX:+DisableHotswapAgent, \ -+ CFLAGS_windows := -DJAVAW, \ -+ LIBS_windows := user32.lib, \ -+)) -diff --git a/make/launcher/Launcher-jdk.jstatd.gmk b/make/launcher/Launcher-jdk.jstatd.gmk -new file mode 100644 -index 00000000000..e1657910c67 ---- /dev/null -+++ b/make/launcher/Launcher-jdk.jstatd.gmk -@@ -0,0 +1,34 @@ -+# -+# Copyright (c) 2011, 2018, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, jstatd, \ -+ MAIN_CLASS := sun.tools.jstatd.Jstatd, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+)) -+ -+# Hook to include the corresponding custom file, if present. -+$(eval $(call IncludeCustomExtension, launcher/Launcher-jdk.jstatd-post.gmk)) -diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk -new file mode 100644 -index 00000000000..64bbbb7c949 ---- /dev/null -+++ b/make/launcher/Launcher-jdk.pack.gmk -@@ -0,0 +1,101 @@ -+# -+# Copyright (c) 2011, 2018, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, pack200, \ -+ MAIN_MODULE := java.base, \ -+ MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+)) -+ -+################################################################################ -+# The order of the object files on the link command line affects the size of the resulting -+# binary (at least on linux) which causes the size to differ between old and new build. -+ -+# Tell the compiler not to export any functions unless declared so in -+# the source code. On Windows, this is the default and cannot be changed. -+# On Mac, we have always exported all symbols, probably due to oversight -+# and/or misunderstanding. To emulate this, don't hide any symbols -+# by default. -+# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063) -+# Also provide an override for non-conformant libraries. -+ifeq ($(TOOLCHAIN_TYPE), gcc) -+ CXXFLAGS_JDKEXE += -fvisibility=hidden -+ LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL -+else ifeq ($(TOOLCHAIN_TYPE), clang) -+ ifneq ($(OPENJDK_TARGET_OS), macosx) -+ CXXFLAGS_JDKEXE += -fvisibility=hidden -+ endif -+else ifeq ($(TOOLCHAIN_TYPE), solstudio) -+ CXXFLAGS_JDKEXE += -xldscope=hidden -+endif -+ -+UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \ -+ $(TOPDIR)/src/jdk.pack/share/native/unpack200 -+UNPACKEXE_CFLAGS := -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \ -+ -I$(TOPDIR)/src/java.base/share/native/libjava \ -+ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava -+ -+ifeq ($(USE_EXTERNAL_LIBZ), true) -+ UNPACKEXE_CFLAGS += -DSYSTEM_ZLIB -+ UNPACKEXE_LIBS := -lz -+else -+ UNPACKEXE_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/libzip/zlib -+ UNPACKEXE_ZIPOBJS := $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zcrc32$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/deflate$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/trees$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zadler32$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/compress$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zutil$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inflate$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/infback$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inftrees$(OBJ_SUFFIX) \ -+ $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inffast$(OBJ_SUFFIX) -+ -+endif -+ -+$(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \ -+ NAME := unpack200, \ -+ SRC := $(UNPACKEXE_SRC), \ -+ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ -+ OPTIMIZATION := LOW, \ -+ CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \ -+ CFLAGS_release := -DPRODUCT, \ -+ CFLAGS_linux := -fPIC, \ -+ CFLAGS_solaris := -KPIC, \ -+ CFLAGS_macosx := -fPIC, \ -+ LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ -+ $(call SET_SHARED_LIBRARY_ORIGIN), \ -+ LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \ -+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \ -+ MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \ -+ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ -+ EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \ -+)) -+ -+TARGETS += $(BUILD_UNPACKEXE) -+ -+################################################################################ -diff --git a/make/launcher/Launcher-jdk.rmic.gmk b/make/launcher/Launcher-jdk.rmic.gmk -new file mode 100644 -index 00000000000..b8a55900b0e ---- /dev/null -+++ b/make/launcher/Launcher-jdk.rmic.gmk -@@ -0,0 +1,32 @@ -+# -+# Copyright (c) 2011, 2015, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, rmic, \ -+ MAIN_CLASS := sun.rmi.rmic.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ -+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ -+)) -diff --git a/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk -new file mode 100644 -index 00000000000..bd39f8595b2 ---- /dev/null -+++ b/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk -@@ -0,0 +1,33 @@ -+# -+# Copyright (c) 2011, 2016, 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. -+# -+ -+include LauncherCommon.gmk -+ -+$(eval $(call SetupBuildLauncher, jjs, \ -+ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ -+ JAVA_ARGS := --add-modules ALL-DEFAULT \ -+ -XX:+DisableHotswapAgent, \ -+ CFLAGS := -DENABLE_ARG_FILES, \ -+)) -diff --git a/make/modules/java.rmi/Launcher.gmk b/make/modules/java.rmi/Launcher.gmk -index a69a90bcc81..07046232275 100644 ---- a/make/modules/java.rmi/Launcher.gmk -+++ b/make/modules/java.rmi/Launcher.gmk -@@ -27,8 +27,10 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, rmid, \ - MAIN_CLASS := sun.rmi.server.Activation, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - )) - - $(eval $(call SetupBuildLauncher, rmiregistry, \ - MAIN_CLASS := sun.rmi.registry.RegistryImpl, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - )) -diff --git a/make/modules/java.scripting/Launcher.gmk b/make/modules/java.scripting/Launcher.gmk -index 057d2bf3aca..cf100e20789 100644 ---- a/make/modules/java.scripting/Launcher.gmk -+++ b/make/modules/java.scripting/Launcher.gmk -@@ -27,5 +27,6 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jrunscript, \ - MAIN_CLASS := com.sun.tools.script.shell.Main, \ -- JAVA_ARGS := --add-modules ALL-DEFAULT, \ -+ JAVA_ARGS := --add-modules ALL-DEFAULT \ -+ -XX:+DisableHotswapAgent, \ - )) -diff --git a/make/modules/jdk.hotspot.agent/Launcher.gmk b/make/modules/jdk.hotspot.agent/Launcher.gmk -index 76da3600368..9f12b05b172 100644 ---- a/make/modules/jdk.hotspot.agent/Launcher.gmk -+++ b/make/modules/jdk.hotspot.agent/Launcher.gmk -@@ -27,5 +27,6 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jhsdb, \ - MAIN_CLASS := sun.jvm.hotspot.SALauncher, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - MACOSX_PRIVILEGED := true, \ - )) -diff --git a/make/modules/jdk.jartool/Launcher.gmk b/make/modules/jdk.jartool/Launcher.gmk -index f74e82bfdae..647d82b65b1 100644 ---- a/make/modules/jdk.jartool/Launcher.gmk -+++ b/make/modules/jdk.jartool/Launcher.gmk -@@ -27,8 +27,10 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jar, \ - MAIN_CLASS := sun.tools.jar.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - )) - - $(eval $(call SetupBuildLauncher, jarsigner, \ - MAIN_CLASS := sun.security.tools.jarsigner.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - )) -diff --git a/make/modules/jdk.javadoc/Launcher.gmk b/make/modules/jdk.javadoc/Launcher.gmk -index 889028a2b17..c3d2093be04 100644 ---- a/make/modules/jdk.javadoc/Launcher.gmk -+++ b/make/modules/jdk.javadoc/Launcher.gmk -@@ -27,6 +27,7 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, javadoc, \ - MAIN_CLASS := jdk.javadoc.internal.tool.Main, \ -- JAVA_ARGS := --add-modules ALL-DEFAULT, \ -+ JAVA_ARGS := --add-modules ALL-DEFAULT \ -+ -XX:+DisableHotswapAgent, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ - )) -diff --git a/make/modules/jdk.jdeps/Launcher.gmk b/make/modules/jdk.jdeps/Launcher.gmk -index 217523c48cc..5448278dae7 100644 ---- a/make/modules/jdk.jdeps/Launcher.gmk -+++ b/make/modules/jdk.jdeps/Launcher.gmk -@@ -27,15 +27,18 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, javap, \ - MAIN_CLASS := com.sun.tools.javap.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ - )) - - $(eval $(call SetupBuildLauncher, jdeps, \ - MAIN_CLASS := com.sun.tools.jdeps.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ - )) - - $(eval $(call SetupBuildLauncher, jdeprscan, \ - MAIN_CLASS := com.sun.tools.jdeprscan.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ - )) -diff --git a/make/modules/jdk.jdi/Launcher.gmk b/make/modules/jdk.jdi/Launcher.gmk -index fcce98cf430..27bd448e3ae 100644 ---- a/make/modules/jdk.jdi/Launcher.gmk -+++ b/make/modules/jdk.jdi/Launcher.gmk -@@ -27,4 +27,5 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jdb, \ - MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - )) -diff --git a/make/modules/jdk.jlink/Launcher.gmk b/make/modules/jdk.jlink/Launcher.gmk -index df2173996d7..9e61edeb2c8 100644 ---- a/make/modules/jdk.jlink/Launcher.gmk -+++ b/make/modules/jdk.jlink/Launcher.gmk -@@ -27,18 +27,21 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jimage,\ - MAIN_CLASS := jdk.tools.jimage.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DENABLE_ARG_FILES, \ - )) - - $(eval $(call SetupBuildLauncher, jlink,\ - MAIN_CLASS := jdk.tools.jlink.internal.Main, \ -- JAVA_ARGS := --add-modules ALL-DEFAULT, \ -+ JAVA_ARGS := --add-modules ALL-DEFAULT \ -+ -XX:+DisableHotswapAgent, \ - CFLAGS := -DENABLE_ARG_FILES \ - -DEXPAND_CLASSPATH_WILDCARDS, \ - )) - - $(eval $(call SetupBuildLauncher, jmod,\ - MAIN_CLASS := jdk.tools.jmod.Main, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DENABLE_ARG_FILES \ - -DEXPAND_CLASSPATH_WILDCARDS, \ - )) -diff --git a/make/modules/jdk.jshell/Launcher.gmk b/make/modules/jdk.jshell/Launcher.gmk -index 349eb88e9eb..7287f8f998a 100644 ---- a/make/modules/jdk.jshell/Launcher.gmk -+++ b/make/modules/jdk.jshell/Launcher.gmk -@@ -27,5 +27,6 @@ include LauncherCommon.gmk - - $(eval $(call SetupBuildLauncher, jshell, \ - MAIN_CLASS := jdk.internal.jshell.tool.JShellToolProvider, \ -+ JAVA_ARGS := -XX:+DisableHotswapAgent, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ - )) -diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp -index 99c5ac98995..6a3b234b222 100644 ---- a/src/hotspot/share/classfile/vmSymbols.hpp -+++ b/src/hotspot/share/classfile/vmSymbols.hpp -@@ -347,6 +347,7 @@ - /* common method and field names */ \ - template(object_initializer_name, "") \ - template(class_initializer_name, "") \ -+ template(ha_class_initializer_name, "$$ha$clinit") \ - template(println_name, "println") \ - template(printStackTrace_name, "printStackTrace") \ - template(main_name, "main") \ -diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp -index 3425e3f893d..b6e9e0a308d 100644 ---- a/src/hotspot/share/interpreter/linkResolver.cpp -+++ b/src/hotspot/share/interpreter/linkResolver.cpp -@@ -1025,7 +1025,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, - assert(m != NULL, "information about the current method must be available for 'put' bytecodes"); - bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic && - fd.is_static() && -- !m->is_static_initializer()); -+ !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name())); - bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) && - !fd.is_static() && - !m->is_object_initializer()); -diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index 6148bce5b9b..2803a3c46eb 100644 ---- a/src/hotspot/share/runtime/arguments.cpp -+++ b/src/hotspot/share/runtime/arguments.cpp -@@ -4116,6 +4116,8 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { - // Set object alignment values. - set_object_alignment(); - -+ setup_hotswap_agent(); -+ - #if !INCLUDE_CDS - if (DumpSharedSpaces || RequireSharedSpaces) { - jio_fprintf(defaultStream::error_stream(), -@@ -4442,3 +4444,68 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen, - *b = '\0'; - return (p == src_end); // return false if not all of the source was copied - } -+ -+void Arguments::setup_hotswap_agent() { -+ -+ if (DumpSharedSpaces) -+ return; -+ -+ if (!AllowEnhancedClassRedefinition) -+ return; -+ -+ // Set HotswapAgent -+ if (!DisableHotswapAgent) { -+ -+ char ext_path_str[JVM_MAXPATHLEN]; -+ -+ os::jvm_path(ext_path_str, sizeof(ext_path_str)); -+ for (int i = 0; i < 3; i++) { -+ char *end = strrchr(ext_path_str, *os::file_separator()); -+ if (end != NULL) *end = '\0'; -+ } -+ size_t ext_path_length = strlen(ext_path_str); -+ if (ext_path_length >= 3) { -+ if (strcmp(ext_path_str + ext_path_length - 3, "lib") != 0) { -+ if (ext_path_length < JVM_MAXPATHLEN - 4) { -+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, "%slib", os::file_separator()); -+ ext_path_length += 4; -+ } -+ } -+ } -+ if (ext_path_length < JVM_MAXPATHLEN - 10) { -+ jio_snprintf(ext_path_str + ext_path_length, sizeof(ext_path_str) - ext_path_length, -+ "%shotswap%shotswap-agent.jar", os::file_separator(), os::file_separator()); -+ } -+ -+ int fd = ::open(ext_path_str, O_RDONLY); -+ if (fd >= 0) { -+ os::close(fd); -+ size_t length = strlen(ext_path_str) + 1; -+ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments); -+ jio_snprintf(options, length, "%s", ext_path_str); -+ add_init_agent("instrument", ext_path_str, false); -+ jio_fprintf(defaultStream::output_stream(), "Starting HotswapAgent '%s'\n", ext_path_str); -+ } -+// else -+// { -+// jio_fprintf(defaultStream::error_stream(), "HotswapAgent not found on path:'%s'\n", ext_path_str); -+// } -+ } -+ -+ // TODO: open it only for org.hotswap.agent module -+ // Use to access java.lang.reflect.Proxy/proxyCache -+ create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); -+ // Class of field java.lang.reflect.Proxy/proxyCache -+ create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); -+ // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream -+ create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); -+ // java.beans.Introspector access -+ create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); -+ // java.beans.Introspector access -+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); -+ // com.sun.beans.introspect.ClassInfo access -+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); -+ // com.sun.beans.introspect.util.Cache access -+ create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); -+ -+} -diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp -index 9c656124d5b..e5fed6345f7 100644 ---- a/src/hotspot/share/runtime/arguments.hpp -+++ b/src/hotspot/share/runtime/arguments.hpp -@@ -512,6 +512,9 @@ class Arguments : AllStatic { - - static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; } - -+ // Initialize HotswapAgent -+ static void setup_hotswap_agent(); -+ - // Return the maximum size a heap with compressed oops can take - static size_t max_heap_for_compressed_oops(); - -diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp -index de9193ca447..5b367704800 100644 ---- a/src/hotspot/share/runtime/globals.hpp -+++ b/src/hotspot/share/runtime/globals.hpp -@@ -31,6 +31,13 @@ - #include "utilities/align.hpp" - #include "utilities/globalDefinitions.hpp" - #include "utilities/macros.hpp" -+ -+#ifdef DCEVM_ONLY -+#define DISABLED_HOTSWAP_AGENT true -+#else -+#define DISABLED_HOTSWAP_AGENT false -+#endif -+ - #include CPU_HEADER(globals) - #include OS_HEADER(globals) - #include OS_CPU_HEADER(globals) -@@ -2461,7 +2468,10 @@ const size_t minimumSymbolTableSize = 1024; - \ - product(bool, AllowEnhancedClassRedefinition, true, \ - "Allow enhanced class redefinition beyond swapping method " \ -- "bodies") -+ "bodies") \ -+ \ -+ product(bool, DisableHotswapAgent, DISABLED_HOTSWAP_AGENT, \ -+ "Disable integrated Hotswap Agent (HotswapVM only)") - - - // Interface macros -diff --git a/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java -new file mode 100644 -index 00000000000..6636e4dd62a ---- /dev/null -+++ b/src/java.desktop/share/classes/com/sun/beans/introspect/package-info.java -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * 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. -+ */ -+ -+package com.sun.beans.introspect; -diff --git a/src/java.desktop/share/classes/com/sun/beans/package-info.java b/src/java.desktop/share/classes/com/sun/beans/package-info.java -new file mode 100644 -index 00000000000..5c097eeaa53 ---- /dev/null -+++ b/src/java.desktop/share/classes/com/sun/beans/package-info.java -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * 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. -+ */ -+ -+package com.sun.beans; -diff --git a/src/java.desktop/share/classes/com/sun/beans/util/package-info.java b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java -new file mode 100644 -index 00000000000..2d5d735ffa8 ---- /dev/null -+++ b/src/java.desktop/share/classes/com/sun/beans/util/package-info.java -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * 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. -+ */ -+ -+package com.sun.beans.util; -diff --git a/src/java.desktop/share/classes/module-info.java b/src/java.desktop/share/classes/module-info.java -index 897647ee368..286304c775c 100644 ---- a/src/java.desktop/share/classes/module-info.java -+++ b/src/java.desktop/share/classes/module-info.java -@@ -111,6 +111,9 @@ module java.desktop { - exports javax.swing.text.rtf; - exports javax.swing.tree; - exports javax.swing.undo; -+ exports com.sun.beans; -+ exports com.sun.beans.introspect; -+ exports com.sun.beans.util; - - // qualified exports may be inserted at build time - // see make/GensrcModuleInfo.gmk --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch b/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch deleted file mode 100644 index 054fe81657a1..000000000000 --- a/jb/project/tools/patches/dcevm/0005-Support-for-Lambda-class-redefinition.patch +++ /dev/null @@ -1,240 +0,0 @@ -From 39df5f163d4a0f1fd6b92313a5570808f19d5e20 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 4 Oct 2020 21:12:12 +0200 -Subject: [PATCH 05/34] Support for Lambda class redefinition - ---- - .../share/classfile/classLoaderData.cpp | 9 +++ - .../share/classfile/classLoaderData.hpp | 2 +- - .../share/classfile/systemDictionary.cpp | 12 +++- - .../share/classfile/systemDictionary.hpp | 1 + - .../prims/jvmtiEnhancedRedefineClasses.cpp | 65 +++++++++++++++++-- - .../prims/jvmtiEnhancedRedefineClasses.hpp | 1 + - .../share/prims/resolvedMethodTable.cpp | 2 + - src/hotspot/share/prims/unsafe.cpp | 1 + - 8 files changed, 83 insertions(+), 10 deletions(-) - -diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp -index 0cd90bb8c27..4d64c6b454a 100644 ---- a/src/hotspot/share/classfile/classLoaderData.cpp -+++ b/src/hotspot/share/classfile/classLoaderData.cpp -@@ -593,6 +593,15 @@ Dictionary* ClassLoaderData::create_dictionary() { - return new Dictionary(this, size, resizable); - } - -+void ClassLoaderData::exchange_holders(ClassLoaderData* cld) { -+ oop holder_oop = _holder.peek(); -+ _holder.replace(cld->_holder.peek()); -+ cld->_holder.replace(holder_oop); -+ WeakHandle exchange = _holder; -+ _holder = cld->_holder; -+ cld->_holder = exchange; -+} -+ - // Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph - oop ClassLoaderData::holder_phantom() const { - // A klass that was previously considered dead can be looked up in the -diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp -index ba2393f8dd0..e2ae0a77351 100644 ---- a/src/hotspot/share/classfile/classLoaderData.hpp -+++ b/src/hotspot/share/classfile/classLoaderData.hpp -@@ -181,7 +181,7 @@ class ClassLoaderData : public CHeapObj { - bool has_accumulated_modified_oops() { return _accumulated_modified_oops; } - oop holder_no_keepalive() const; - oop holder_phantom() const; -- -+ void exchange_holders(ClassLoaderData* cld); - private: - void unload(); - bool keep_alive() const { return _keep_alive > 0; } -diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp -index bd0cae7cb9b..8f2b46add4d 100644 ---- a/src/hotspot/share/classfile/systemDictionary.cpp -+++ b/src/hotspot/share/classfile/systemDictionary.cpp -@@ -1062,10 +1062,14 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, - Handle class_loader, - ClassFileStream* st, - const ClassLoadInfo& cl_info, -+ InstanceKlass* old_klass, - TRAPS) { - - EventClassLoad class_load_start_event; - ClassLoaderData* loader_data; -+ -+ bool is_redefining = (old_klass != NULL); -+ - bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL; - - // - for unsafe anonymous class: create a new CLD whith a class holder that uses -@@ -1094,8 +1098,12 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name, - class_name, - loader_data, - cl_info, -- false, // pick_newest -+ is_redefining, // pick_newest - CHECK_NULL); -+ if (is_redefining && k != NULL) { -+ k->set_redefining(true); -+ k->set_old_version(old_klass); -+ } - - if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) { - // Hidden classes that are not strong and unsafe anonymous classes must update -@@ -1998,7 +2006,7 @@ void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) { - k->remove_from_sibling_list(); - } - --// (DCEVM) -+// (DCEVM) - void SystemDictionary::update_constraints_after_redefinition() { - constraints()->update_after_redefinition(); - } -diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp -index 4547449dbec..931e655d631 100644 ---- a/src/hotspot/share/classfile/systemDictionary.hpp -+++ b/src/hotspot/share/classfile/systemDictionary.hpp -@@ -329,6 +329,7 @@ public: - Handle class_loader, - ClassFileStream* st, - const ClassLoadInfo& cl_info, -+ InstanceKlass* old_klass, - TRAPS); - - // Resolve from stream (called by jni_DefineClass and JVM_DefineClass) -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 92ce6c27b8a..8b765623dcd 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -494,6 +494,8 @@ void VM_EnhancedRedefineClasses::doit() { - ClassLoaderDataGraph::classes_do(&clear_cpool_cache); - - -+ // SystemDictionary::methods_do(fix_invoke_method); -+ - // JSR-292 support - if (_any_class_has_resolved_methods) { - bool trace_name_printed = false; -@@ -756,12 +758,34 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - // load hook event. - state->set_class_being_redefined(the_class, _class_load_kind); - -- InstanceKlass* k = SystemDictionary::resolve_from_stream(the_class_sym, -- the_class_loader, -- protection_domain, -- &st, -- the_class, -- THREAD); -+ InstanceKlass* k; -+ -+ if (InstanceKlass::cast(the_class)->is_anonymous()) { -+ const InstanceKlass* host_class = the_class->host_klass(); -+ -+ // Make sure it's the real host class, not another anonymous class. -+ while (host_class != NULL && host_class->is_anonymous()) { -+ host_class = host_class->host_klass(); -+ } -+ -+ k = SystemDictionary::parse_stream(the_class_sym, -+ the_class_loader, -+ protection_domain, -+ &st, -+ host_class, -+ the_class, -+ NULL, -+ THREAD); -+ k->class_loader_data()->exchange_holders(the_class->class_loader_data()); -+ the_class->class_loader_data()->inc_keep_alive(); -+ } else { -+ k = SystemDictionary::resolve_from_stream(the_class_sym, -+ the_class_loader, -+ protection_domain, -+ &st, -+ the_class, -+ THREAD); -+ } - // Clear class_being_redefined just to be sure. - state->clear_class_being_redefined(); - -@@ -1442,6 +1466,30 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { - } - } - -+void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) { -+ -+ constantPoolHandle other_cp = constantPoolHandle(method->constants()); -+ -+ for (int i = 0; i < other_cp->length(); i++) { -+ if (other_cp->tag_at(i).is_klass()) { -+ Klass* klass = other_cp->resolved_klass_at(i); -+ if (klass->new_version() != NULL) { -+ // Constant pool entry points to redefined class -- update to the new version -+ other_cp->klass_at_put(i, klass->newest_version()); -+ } -+ assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); -+ } -+ } -+ -+ ConstantPoolCache* cp_cache = other_cp->cache(); -+ if (cp_cache != NULL) { -+ cp_cache->clear_entries(); -+ } -+ -+} -+ -+ -+ - void VM_EnhancedRedefineClasses::update_jmethod_ids() { - for (int j = 0; j < _matching_methods_length; ++j) { - Method* old_method = _matching_old_methods[j]; -@@ -1979,7 +2027,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { - // Find classes not directly redefined, but affected by a redefinition (because one of its supertypes is redefined) - AffectedKlassClosure closure(_affected_klasses); - // Updated in j10, from original SystemDictionary::classes_do -- ClassLoaderDataGraph::dictionary_classes_do(&closure); -+ -+ ClassLoaderDataGraph::classes_do(&closure); -+ //ClassLoaderDataGraph::dictionary_classes_do(&closure); -+ - log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); - - // Sort the affected klasses such that a supertype is always on a smaller array index than its subtype. -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index 60b62c3170a..d8a11b51fe9 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -116,6 +116,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - void rollback(); - static void mark_as_scavengable(nmethod* nm); - static void unpatch_bytecode(Method* method); -+ static void fix_invoke_method(Method* method); - - // Figure out which new methods match old methods in name and signature, - // which methods have been added, and which are no longer present -diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp -index 122bb8c186b..81b3aa96564 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.cpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp -@@ -414,6 +414,8 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) - InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); - Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); - -+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); -+ - assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); - assert(newer_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != newer_method, "sanity check"); -diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp -index 72d81ec9d6c..027afa3fabd 100644 ---- a/src/hotspot/share/prims/unsafe.cpp -+++ b/src/hotspot/share/prims/unsafe.cpp -@@ -865,6 +865,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, - host_loader, - &st, - cl_info, -+ NULL, - CHECK_NULL); - if (anonk == NULL) { - return NULL; --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch b/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch deleted file mode 100644 index 418c656a3461..000000000000 --- a/jb/project/tools/patches/dcevm/0006-Fix-no-original-bytecode-found-error-if-method-with-.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 5af1daedc86b5fec0f222cbdda3afbdf518985ea Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sat, 23 May 2020 10:02:15 +0200 -Subject: [PATCH 06/34] Fix "no original bytecode found" error if method with - bkp is missing - -Sometimes IDE can deploy class with erroneous method, such method has -n bytecode, but breakpoint position can still exist. ---- - src/hotspot/share/interpreter/bytecodes.cpp | 2 +- - .../share/interpreter/interpreterRuntime.cpp | 2 +- - src/hotspot/share/oops/method.cpp | 8 ++++---- - src/hotspot/share/oops/method.hpp | 4 ++-- - .../prims/jvmtiEnhancedRedefineClasses.cpp | 18 ++++++++++-------- - 5 files changed, 18 insertions(+), 16 deletions(-) - -diff --git a/src/hotspot/share/interpreter/bytecodes.cpp b/src/hotspot/share/interpreter/bytecodes.cpp -index e377e36b88c..262ecc021b2 100644 ---- a/src/hotspot/share/interpreter/bytecodes.cpp -+++ b/src/hotspot/share/interpreter/bytecodes.cpp -@@ -84,7 +84,7 @@ Bytecodes::Code Bytecodes::code_at(Method* method, int bci) { - Bytecodes::Code Bytecodes::non_breakpoint_code_at(const Method* method, address bcp) { - assert(method != NULL, "must have the method for breakpoint conversion"); - assert(method->contains(bcp), "must be valid bcp in method"); -- return method->orig_bytecode_at(method->bci_from(bcp)); -+ return method->orig_bytecode_at(method->bci_from(bcp), false); - } - - int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) { -diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp -index ed3cc3eb6a2..504e59caf51 100644 ---- a/src/hotspot/share/interpreter/interpreterRuntime.cpp -+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp -@@ -814,7 +814,7 @@ JRT_END - // Invokes - - JRT_ENTRY(Bytecodes::Code, InterpreterRuntime::get_original_bytecode_at(JavaThread* thread, Method* method, address bcp)) -- return method->orig_bytecode_at(method->bci_from(bcp)); -+ return method->orig_bytecode_at(method->bci_from(bcp), false); - JRT_END - - JRT_ENTRY(void, InterpreterRuntime::set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code)) -diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp -index 516f2bb8f2f..1c88511a5fc 100644 ---- a/src/hotspot/share/oops/method.cpp -+++ b/src/hotspot/share/oops/method.cpp -@@ -1853,14 +1853,14 @@ bool CompressedLineNumberReadStream::read_pair() { - - #if INCLUDE_JVMTI - --Bytecodes::Code Method::orig_bytecode_at(int bci) const { -+Bytecodes::Code Method::orig_bytecode_at(int bci, bool no_fatal) const { - BreakpointInfo* bp = method_holder()->breakpoints(); - for (; bp != NULL; bp = bp->next()) { - if (bp->match(this, bci)) { - return bp->orig_bytecode(); - } - } -- { -+ if (!no_fatal) { - ResourceMark rm; - fatal("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci); - } -@@ -2006,7 +2006,7 @@ BreakpointInfo::BreakpointInfo(Method* m, int bci) { - _signature_index = m->signature_index(); - _orig_bytecode = (Bytecodes::Code) *m->bcp_from(_bci); - if (_orig_bytecode == Bytecodes::_breakpoint) -- _orig_bytecode = m->orig_bytecode_at(_bci); -+ _orig_bytecode = m->orig_bytecode_at(_bci, false); - _next = NULL; - } - -@@ -2015,7 +2015,7 @@ void BreakpointInfo::set(Method* method) { - { - Bytecodes::Code code = (Bytecodes::Code) *method->bcp_from(_bci); - if (code == Bytecodes::_breakpoint) -- code = method->orig_bytecode_at(_bci); -+ code = method->orig_bytecode_at(_bci, false); - assert(orig_bytecode() == code, "original bytecode must be the same"); - } - #endif -diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp -index 83ed2d9c3c1..4d4cc6dc012 100644 ---- a/src/hotspot/share/oops/method.hpp -+++ b/src/hotspot/share/oops/method.hpp -@@ -230,7 +230,7 @@ class Method : public Metadata { - - // JVMTI breakpoints - #if !INCLUDE_JVMTI -- Bytecodes::Code orig_bytecode_at(int bci) const { -+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const { - ShouldNotReachHere(); - return Bytecodes::_shouldnotreachhere; - } -@@ -239,7 +239,7 @@ class Method : public Metadata { - }; - u2 number_of_breakpoints() const {return 0;} - #else // !INCLUDE_JVMTI -- Bytecodes::Code orig_bytecode_at(int bci) const; -+ Bytecodes::Code orig_bytecode_at(int bci, bool no_fatal) const; - void set_orig_bytecode_at(int bci, Bytecodes::Code code); - void set_breakpoint(int bci); - void clear_breakpoint(int bci); -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 8b765623dcd..a859b8e1162 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -1362,14 +1362,16 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { - - if (code == Bytecodes::_breakpoint) { - int bci = method->bci_from(bcp); -- code = method->orig_bytecode_at(bci); -- java_code = Bytecodes::java_code(code); -- if (code != java_code && -- (java_code == Bytecodes::_getfield || -- java_code == Bytecodes::_putfield || -- java_code == Bytecodes::_aload_0)) { -- // Let breakpoint table handling unpatch bytecode -- method->set_orig_bytecode_at(bci, java_code); -+ code = method->orig_bytecode_at(bci, true); -+ if (code != Bytecodes::_shouldnotreachhere) { -+ java_code = Bytecodes::java_code(code); -+ if (code != java_code && -+ (java_code == Bytecodes::_getfield || -+ java_code == Bytecodes::_putfield || -+ java_code == Bytecodes::_aload_0)) { -+ // Let breakpoint table handling unpatch bytecode -+ method->set_orig_bytecode_at(bci, java_code); -+ } - } - } else { - java_code = Bytecodes::java_code(code); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch b/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch deleted file mode 100644 index a4c3f58b498e..000000000000 --- a/jb/project/tools/patches/dcevm/0007-Replace-deleted-method-with-Universe-throw_no_such_m.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 19d2274a5dff6e6b31474252b45e5e7484f0180b Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 24 May 2020 12:07:42 +0200 -Subject: [PATCH 07/34] Replace deleted method with - Universe::throw_no_such_method_error - ---- - .../share/prims/resolvedMethodTable.cpp | 28 +++++++++---------- - 1 file changed, 14 insertions(+), 14 deletions(-) - -diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp -index 81b3aa96564..caf03ffe56d 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.cpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp -@@ -404,25 +404,25 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) - - if (old_method->is_old()) { - -+ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); -+ Method* newer_method; -+ - // Method* new_method; - if (old_method->is_deleted()) { -- // FIXME:(DCEVM) - check if exception can be thrown -- // new_method = Universe::throw_no_such_method_error(); -- continue; -- } -- -- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); -- Method* newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); -+ newer_method = Universe::throw_no_such_method_error(); -+ } else { -+ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); - -- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); -+ log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); - -- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); -- assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -- assert(old_method != newer_method, "sanity check"); -+ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); -+ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -+ assert(old_method != newer_method, "sanity check"); - -- if (_the_table->lookup(newer_method) != NULL) { -- // old method was already adjusted if new method exists in _the_table -- continue; -+ if (_the_table->lookup(newer_method) != NULL) { -+ // old method was already adjusted if new method exists in _the_table -+ continue; -+ } - } - - java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch b/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch deleted file mode 100644 index d28e787ffdf8..000000000000 --- a/jb/project/tools/patches/dcevm/0008-Support-for-G1-gc.patch +++ /dev/null @@ -1,1310 +0,0 @@ -From a597c7248c92aad292e681564300dc98eb72e216 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Fri, 12 Jun 2020 17:43:52 +0200 -Subject: [PATCH 08/34] Support for G1 gc - ---- - src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 20 +++ - src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 3 + - src/hotspot/share/gc/g1/g1FullCollector.cpp | 16 +- - .../share/gc/g1/g1FullGCCompactTask.cpp | 92 +++++++++- - .../share/gc/g1/g1FullGCCompactTask.hpp | 19 +++ - .../share/gc/g1/g1FullGCCompactionPoint.cpp | 85 +++++++++- - .../share/gc/g1/g1FullGCCompactionPoint.hpp | 11 ++ - .../share/gc/g1/g1FullGCPrepareTask.cpp | 90 +++++++++- - .../share/gc/g1/g1FullGCPrepareTask.hpp | 13 ++ - src/hotspot/share/gc/g1/heapRegion.hpp | 10 ++ - src/hotspot/share/gc/serial/genMarkSweep.cpp | 4 +- - src/hotspot/share/gc/serial/markSweep.cpp | 97 ----------- - src/hotspot/share/gc/serial/markSweep.hpp | 3 - - src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 159 ++++++++++++++++++ - src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 49 ++++++ - src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- - src/hotspot/share/gc/shared/space.inline.hpp | 3 +- - src/hotspot/share/memory/universe.cpp | 5 + - .../prims/jvmtiEnhancedRedefineClasses.cpp | 80 ++++++--- - .../prims/jvmtiEnhancedRedefineClasses.hpp | 6 +- - src/hotspot/share/runtime/arguments.cpp | 4 +- - src/hotspot/share/utilities/growableArray.hpp | 4 + - 22 files changed, 628 insertions(+), 147 deletions(-) - create mode 100644 src/hotspot/share/gc/shared/dcevmSharedGC.cpp - create mode 100644 src/hotspot/share/gc/shared/dcevmSharedGC.hpp - -diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -index e8cdd861cbb..a29d2dddc2d 100644 ---- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -@@ -2352,6 +2352,21 @@ public: - } - }; - -+class G1IterateObjectClosureTask : public AbstractGangTask { -+ private: -+ ObjectClosure* _cl; -+ G1CollectedHeap* _g1h; -+ HeapRegionClaimer _hrclaimer; -+ public: -+ G1IterateObjectClosureTask(ObjectClosure* cl, G1CollectedHeap* g1h) : AbstractGangTask("IterateObject Closure"), -+ _cl(cl), _g1h(g1h), _hrclaimer(g1h->workers()->active_workers()) { } -+ -+ virtual void work(uint worker_id) { -+ IterateObjectClosureRegionClosure blk(_cl); -+ _g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id); -+ } -+}; -+ - void G1CollectedHeap::object_iterate(ObjectClosure* cl) { - IterateObjectClosureRegionClosure blk(cl); - heap_region_iterate(&blk); -@@ -2365,6 +2380,11 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { - _hrm->iterate(cl); - } - -+void G1CollectedHeap::object_par_iterate(ObjectClosure* cl) { -+ G1IterateObjectClosureTask iocl_task(cl, this); -+ workers()->run_task(&iocl_task); -+} -+ - void G1CollectedHeap::heap_region_par_iterate_from_worker_offset(HeapRegionClosure* cl, - HeapRegionClaimer *hrclaimer, - uint worker_id) const { -diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp -index 71f89d09184..adb97ee260a 100644 ---- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp -+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp -@@ -146,6 +146,7 @@ class G1CollectedHeap : public CollectedHeap { - friend class G1ParScanThreadStateSet; - friend class G1EvacuateRegionsTask; - friend class G1PLABAllocator; -+ friend class G1FullGCPrepareTask; - - // Other related classes. - friend class HeapRegionClaimer; -@@ -1168,6 +1169,8 @@ public: - - // Iteration functions. - -+ void object_par_iterate(ObjectClosure* cl); -+ - // Iterate over all objects, calling "cl.do_object" on each. - virtual void object_iterate(ObjectClosure* cl); - -diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp -index 0242e45eef5..707fe8844d0 100644 ---- a/src/hotspot/share/gc/g1/g1FullCollector.cpp -+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp -@@ -237,8 +237,12 @@ void G1FullCollector::phase2_prepare_compaction() { - run_task(&task); - - // To avoid OOM when there is memory left. -- if (!task.has_freed_regions()) { -- task.prepare_serial_compaction(); -+ if (!Universe::is_redefining_gc_run()) { -+ if (!task.has_freed_regions()) { -+ task.prepare_serial_compaction(); -+ } -+ } else { -+ task.prepare_serial_compaction_dcevm(); - } - } - -@@ -257,8 +261,12 @@ void G1FullCollector::phase4_do_compaction() { - run_task(&task); - - // Serial compact to avoid OOM when very few free regions. -- if (serial_compaction_point()->has_regions()) { -- task.serial_compaction(); -+ if (!Universe::is_redefining_gc_run()) { -+ if (serial_compaction_point()->has_regions()) { -+ task.serial_compaction(); -+ } -+ } else { -+ task.serial_compaction_dcevm(); - } - } - -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -index 97742d26ee9..f70f4606dc8 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -@@ -30,6 +30,7 @@ - #include "gc/g1/g1FullGCCompactTask.hpp" - #include "gc/g1/heapRegion.inline.hpp" - #include "gc/shared/gcTraceTime.inline.hpp" -+#include "gc/shared/dcevmSharedGC.hpp" - #include "logging/log.hpp" - #include "oops/oop.inline.hpp" - #include "utilities/ticks.hpp" -@@ -90,12 +91,30 @@ void G1FullGCCompactTask::compact_region(HeapRegion* hr) { - void G1FullGCCompactTask::work(uint worker_id) { - Ticks start = Ticks::now(); - GrowableArray* compaction_queue = collector()->compaction_point(worker_id)->regions(); -- for (GrowableArrayIterator it = compaction_queue->begin(); -- it != compaction_queue->end(); -- ++it) { -- compact_region(*it); -+ -+ if (!Universe::is_redefining_gc_run()) { -+ for (GrowableArrayIterator it = compaction_queue->begin(); -+ it != compaction_queue->end(); -+ ++it) { -+ compact_region(*it); -+ } -+ } else { -+ GrowableArrayIterator rescue_oops_it = collector()->compaction_point(worker_id)->rescued_oops()->begin(); -+ GrowableArray* rescued_oops_values = collector()->compaction_point(worker_id)->rescued_oops_values(); -+ -+ for (GrowableArrayIterator it = compaction_queue->begin(); -+ it != compaction_queue->end(); -+ ++it) { -+ compact_region_dcevm(*it, rescued_oops_values, &rescue_oops_it); -+ } -+ assert(rescue_oops_it.at_end(), "Must be at end"); -+ G1FullGCCompactionPoint* cp = collector()->compaction_point(worker_id); -+ if (cp->last_rescued_oop() > 0) { -+ DcevmSharedGC::copy_rescued_objects_back(rescued_oops_values, 0, cp->last_rescued_oop(), false); -+ } - } - -+ // TODO: (DCEV) check it - G1ResetHumongousClosure hc(collector()->mark_bitmap()); - G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&hc, &_claimer, worker_id); - log_task("Compaction task", worker_id, start); -@@ -110,3 +129,68 @@ void G1FullGCCompactTask::serial_compaction() { - compact_region(*it); - } - } -+ -+void G1FullGCCompactTask::compact_region_dcevm(HeapRegion* hr, GrowableArray* rescued_oops_values, -+ GrowableArrayIterator* rescue_oops_it) { -+ assert(!hr->is_humongous(), "Should be no humongous regions in compaction queue"); -+ ResourceMark rm; // -+ -+ G1CompactRegionClosureDcevm compact(collector()->mark_bitmap(), rescued_oops_values, rescue_oops_it); -+ hr->apply_to_marked_objects(collector()->mark_bitmap(), &compact); -+ // Once all objects have been moved the liveness information -+ // needs be cleared. -+ collector()->mark_bitmap()->clear_region(hr); -+ hr->complete_compaction(); -+} -+ -+void G1FullGCCompactTask::serial_compaction_dcevm() { -+ GCTraceTime(Debug, gc, phases) tm("Phase 4: Serial Compaction", collector()->scope()->timer()); -+ -+ // compact remaining, not parallel compacted rescued oops using serial compact point -+ -+ for (uint i = 0; i < collector()->workers(); i++) { -+ G1FullGCCompactionPoint* cp = collector()->compaction_point(i); -+ DcevmSharedGC::clear_rescued_objects_heap(cp->rescued_oops_values()); -+ } -+ -+} -+ -+size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) { -+ size_t size = obj->size(); -+ HeapWord* destination = (HeapWord*)obj->forwardee(); -+ if (destination == NULL) { -+ // Object not moving -+ return size; -+ } -+ -+ // copy object and reinit its mark -+ HeapWord* obj_addr = (HeapWord*) obj; -+ -+ if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) { -+ ++(*_rescue_oops_it); -+ HeapWord* rescued_obj = NEW_C_HEAP_ARRAY(HeapWord, size, mtInternal); -+ Copy::aligned_disjoint_words(obj_addr, rescued_obj, size); -+ _rescued_oops_values->append(rescued_obj); -+ debug_only(Copy::fill_to_words(obj_addr, size, 0)); -+ return size; -+ } -+ -+ if (obj->klass()->new_version() != NULL) { -+ Klass* new_version = obj->klass()->new_version(); -+ if (new_version->update_information() == NULL) { -+ Copy::aligned_conjoint_words(obj_addr, destination, size); -+ oop(destination)->set_klass(new_version); -+ } else { -+ DcevmSharedGC::update_fields(obj, oop(destination)); -+ } -+ oop(destination)->init_mark_raw(); -+ assert(oop(destination)->klass() != NULL, "should have a class"); -+ return size; -+ } -+ -+ Copy::aligned_conjoint_words(obj_addr, destination, size); -+ oop(destination)->init_mark_raw(); -+ assert(oop(destination)->klass() != NULL, "should have a class"); -+ -+ return size; -+} -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp -index 6c8eaf5967e..ea52a2db8cc 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp -@@ -41,6 +41,8 @@ protected: - - private: - void compact_region(HeapRegion* hr); -+ void compact_region_dcevm(HeapRegion* hr, GrowableArray* rescued_oops_values, -+ GrowableArrayIterator* rescue_oops_it); - - public: - G1FullGCCompactTask(G1FullCollector* collector) : -@@ -48,6 +50,7 @@ public: - _claimer(collector->workers()) { } - void work(uint worker_id); - void serial_compaction(); -+ void serial_compaction_dcevm(); - - class G1CompactRegionClosure : public StackObj { - G1CMBitMap* _bitmap; -@@ -56,6 +59,22 @@ public: - G1CompactRegionClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { } - size_t apply(oop object); - }; -+ -+ class G1CompactRegionClosureDcevm : public StackObj { -+ G1CMBitMap* _bitmap; -+ GrowableArray* _rescued_oops_values; -+ GrowableArrayIterator* _rescue_oops_it; -+ -+ public: -+ G1CompactRegionClosureDcevm(G1CMBitMap* bitmap, -+ GrowableArray* rescued_oops_values, -+ GrowableArrayIterator* rescue_oops_it) : -+ _bitmap(bitmap), -+ _rescued_oops_values(rescued_oops_values), -+ _rescue_oops_it(rescue_oops_it) -+ { } -+ size_t apply(oop object); -+ }; - }; - - #endif // SHARE_GC_G1_G1FULLGCCOMPACTTASK_HPP -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -index 269d14d8b73..1e49571c999 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -@@ -31,13 +31,19 @@ - G1FullGCCompactionPoint::G1FullGCCompactionPoint() : - _current_region(NULL), - _threshold(NULL), -- _compaction_top(NULL) { -+ _compaction_top(NULL), -+ _last_rescued_oop(0) -+{ - _compaction_regions = new (ResourceObj::C_HEAP, mtGC) GrowableArray(32, true, mtGC); - _compaction_region_iterator = _compaction_regions->begin(); -+ _rescued_oops = new (ResourceObj::C_HEAP, mtGC) GrowableArray(128, true, mtGC); -+ _rescued_oops_values = new (ResourceObj::C_HEAP, mtGC) GrowableArray(128, true, mtGC); - } - - G1FullGCCompactionPoint::~G1FullGCCompactionPoint() { - delete _compaction_regions; -+ delete _rescued_oops; -+ delete _rescued_oops_values; - } - - void G1FullGCCompactionPoint::update() { -@@ -80,6 +86,14 @@ GrowableArray* G1FullGCCompactionPoint::regions() { - return _compaction_regions; - } - -+GrowableArray* G1FullGCCompactionPoint::rescued_oops() { -+ return _rescued_oops; -+} -+ -+GrowableArray* G1FullGCCompactionPoint::rescued_oops_values() { -+ return _rescued_oops_values; -+} -+ - bool G1FullGCCompactionPoint::object_will_fit(size_t size) { - size_t space_left = pointer_delta(_current_region->end(), _compaction_top); - return size <= space_left; -@@ -143,3 +157,72 @@ void G1FullGCCompactionPoint::merge(G1FullGCCompactionPoint* other) { - HeapRegion* G1FullGCCompactionPoint::remove_last() { - return _compaction_regions->pop(); - } -+ -+HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) { -+ assert(_current_region != NULL, "Must have been initialized"); -+ // Ensure the object fit in the current region. -+ while (!object_will_fit(size)) { -+ if (!_compaction_region_iterator.has_next()) { -+ return NULL; -+ } -+ switch_region(); -+ } -+ return _compaction_top; -+} -+ -+void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_forward) { -+ assert(_current_region != NULL, "Must have been initialized"); -+ -+ // Store a forwarding pointer if the object should be moved. -+ if ((HeapWord*)object != _compaction_top || force_forward) { -+ object->forward_to(oop(_compaction_top)); -+ } else { -+ if (object->forwardee() != NULL) { -+ // Object should not move but mark-word is used so it looks like the -+ // object is forwarded. Need to clear the mark and it's no problem -+ // since it will be restored by preserved marks. There is an exception -+ // with BiasedLocking, in this case forwardee() will return NULL -+ // even if the mark-word is used. This is no problem since -+ // forwardee() will return NULL in the compaction phase as well. -+ object->init_mark_raw(); -+ } else { -+ // Make sure object has the correct mark-word set or that it will be -+ // fixed when restoring the preserved marks. -+ assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark -+ object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet -+ (UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking -+ "should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT, -+ p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object))); -+ } -+ assert(object->forwardee() == NULL, "should be forwarded to NULL"); -+ } -+ -+ // Update compaction values. -+ _compaction_top += size; -+ if (_compaction_top > _threshold) { -+ _threshold = _current_region->cross_threshold(_compaction_top - size, _compaction_top); -+ } -+} -+ -+void G1FullGCCompactionPoint::forward_rescued() { -+ int i; -+ -+ i = _last_rescued_oop; -+ -+ for (;ilength(); i++) { -+ HeapWord* q = rescued_oops()->at(i); -+ -+ size_t size = oop(q)->size(); -+ -+ // (DCEVM) There is a new version of the class of q => different size -+ if (oop(q)->klass()->new_version() != NULL) { -+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -+ size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); -+ } -+ if (forward_compact_top(size) == NULL) { -+ break; -+ } -+ forward_dcevm(oop(q), size, true); -+ } -+ _last_rescued_oop = i; -+} -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp -index 0ec0b324aab..a55a37f96c0 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp -@@ -37,6 +37,9 @@ class G1FullGCCompactionPoint : public CHeapObj { - HeapWord* _compaction_top; - GrowableArray* _compaction_regions; - GrowableArrayIterator _compaction_region_iterator; -+ GrowableArray* _rescued_oops; -+ GrowableArray* _rescued_oops_values; -+ int _last_rescued_oop; - - bool object_will_fit(size_t size); - void initialize_values(bool init_threshold); -@@ -52,6 +55,8 @@ public: - void initialize(HeapRegion* hr, bool init_threshold); - void update(); - void forward(oop object, size_t size); -+ HeapWord* forward_compact_top(size_t size); -+ void forward_dcevm(oop object, size_t size, bool force_forward); - void add(HeapRegion* hr); - void merge(G1FullGCCompactionPoint* other); - -@@ -59,6 +64,12 @@ public: - HeapRegion* current_region(); - - GrowableArray* regions(); -+ -+ GrowableArray* rescued_oops(); -+ GrowableArray* rescued_oops_values(); -+ -+ void forward_rescued(); -+ int last_rescued_oop() { return _last_rescued_oop; } - }; - - #endif // SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP -diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -index 3658ae200d9..a45681b60cf 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -@@ -40,6 +40,7 @@ - #include "utilities/ticks.hpp" - - bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) { -+ hr->set_processing_order(_region_processing_order++); - if (hr->is_humongous()) { - oop obj = oop(hr->humongous_start_region()->bottom()); - if (_bitmap->is_marked(obj)) { -@@ -49,7 +50,7 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* - } else { - free_humongous_region(hr); - } -- } else if (!hr->is_pinned()) { -+ } else if (!hr->is_pinned()) { // TODO: (DCEVM) review pinned - prepare_for_compaction(hr); - } - -@@ -81,6 +82,10 @@ void G1FullGCPrepareTask::work(uint worker_id) { - G1CalculatePointersClosure closure(collector()->mark_bitmap(), compaction_point); - G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer); - -+ if (Universe::is_redefining_gc_run()) { -+ compaction_point->forward_rescued(); -+ } -+ - // Update humongous region sets - closure.update_sets(); - compaction_point->update(); -@@ -97,7 +102,8 @@ G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1CM - _g1h(G1CollectedHeap::heap()), - _bitmap(bitmap), - _cp(cp), -- _humongous_regions_removed(0) { } -+ _humongous_regions_removed(0), -+ _region_processing_order(0) { } - - void G1FullGCPrepareTask::G1CalculatePointersClosure::free_humongous_region(HeapRegion* hr) { - FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); -@@ -146,9 +152,15 @@ size_t G1FullGCPrepareTask::G1RePrepareClosure::apply(oop obj) { - - void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction_work(G1FullGCCompactionPoint* cp, - HeapRegion* hr) { -- G1PrepareCompactLiveClosure prepare_compact(cp); -- hr->set_compaction_top(hr->bottom()); -- hr->apply_to_marked_objects(_bitmap, &prepare_compact); -+ if (!Universe::is_redefining_gc_run()) { -+ G1PrepareCompactLiveClosure prepare_compact(cp); -+ hr->set_compaction_top(hr->bottom()); -+ hr->apply_to_marked_objects(_bitmap, &prepare_compact); -+ } else { -+ G1PrepareCompactLiveClosureDcevm prepare_compact(cp, hr->processing_order()); -+ hr->set_compaction_top(hr->bottom()); -+ hr->apply_to_marked_objects(_bitmap, &prepare_compact); -+ } - } - - void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) { -@@ -219,3 +231,71 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::freed_regions() { - // No free regions in the queue. - return false; - } -+ -+void G1FullGCPrepareTask::prepare_serial_compaction_dcevm() { -+ GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare Serial Compaction", collector()->scope()->timer()); -+ -+ for (uint i = 0; i < collector()->workers(); i++) { -+ G1FullGCCompactionPoint* cp = collector()->compaction_point(i); -+ -+ // collect remaining, not forwarded rescued oops using serial compact point -+ while (cp->last_rescued_oop() < cp->rescued_oops()->length()) { -+ HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, false, true); -+ if (hr == NULL) { -+ vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "G1 - not enough of free regions after redefinition."); -+ } -+ hr->set_compaction_top(hr->bottom()); -+ cp->add(hr); -+ cp->forward_rescued(); -+ cp->update(); -+ } -+ } -+} -+ -+G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::G1PrepareCompactLiveClosureDcevm(G1FullGCCompactionPoint* cp, -+ uint region_processing_order) : -+ _cp(cp), -+ _region_processing_order(region_processing_order) { } -+ -+size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object) { -+ size_t size = object->size(); -+ size_t forward_size = size; -+ -+ // (DCEVM) There is a new version of the class of q => different size -+ if (object->klass()->new_version() != NULL) { -+ forward_size = object->size_given_klass(object->klass()->new_version()); -+ } -+ -+ HeapWord* compact_top = _cp->forward_compact_top(forward_size); -+ -+ if (compact_top == NULL || must_rescue(object, oop(compact_top))) { -+ _cp->rescued_oops()->append((HeapWord*)object); -+ } else { -+ _cp->forward_dcevm(object, forward_size, (size != forward_size)); -+ } -+ -+ return size; -+} -+ -+bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_obj, oop new_obj) { -+ // Only redefined objects can have the need to be rescued. -+ if (oop(old_obj)->klass()->new_version() == NULL) { -+ return false; -+ } -+ -+ if (_region_processing_order > _cp->current_region()->processing_order()) { -+ return false; -+ } -+ -+ if (_region_processing_order < _cp->current_region()->processing_order()) { -+ return true; -+ } -+ -+ // old obj and new obj are within same region -+ int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); -+ int original_size = old_obj->size(); -+ -+ bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); -+ -+ return overlap; -+} -diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp -index fcaf797a12f..98a8fa58bbc 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp -+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp -@@ -46,6 +46,7 @@ public: - G1FullGCPrepareTask(G1FullCollector* collector); - void work(uint worker_id); - void prepare_serial_compaction(); -+ void prepare_serial_compaction_dcevm(); - bool has_freed_regions(); - - protected: -@@ -55,6 +56,7 @@ protected: - G1CMBitMap* _bitmap; - G1FullGCCompactionPoint* _cp; - uint _humongous_regions_removed; -+ uint _region_processing_order; - - virtual void prepare_for_compaction(HeapRegion* hr); - void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr); -@@ -78,6 +80,16 @@ protected: - size_t apply(oop object); - }; - -+ class G1PrepareCompactLiveClosureDcevm : public StackObj { -+ G1FullGCCompactionPoint* _cp; -+ uint _region_processing_order; -+ -+ bool must_rescue(oop old_obj, oop new_obj); -+ public: -+ G1PrepareCompactLiveClosureDcevm(G1FullGCCompactionPoint* cp, uint region_processing_order); -+ size_t apply(oop object); -+ }; -+ - class G1RePrepareClosure : public StackObj { - G1FullGCCompactionPoint* _cp; - HeapRegion* _current; -@@ -90,6 +102,7 @@ protected: - - size_t apply(oop object); - }; -+ - }; - - #endif // SHARE_GC_G1_G1FULLGCPREPARETASK_HPP -diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp -index 5bf94460540..ec6c5cf8751 100644 ---- a/src/hotspot/share/gc/g1/heapRegion.hpp -+++ b/src/hotspot/share/gc/g1/heapRegion.hpp -@@ -199,6 +199,8 @@ private: - // The remembered set for this region. - HeapRegionRemSet* _rem_set; - -+ uint _processing_order; -+ - // Cached index of this region in the heap region sequence. - const uint _hrm_index; - -@@ -452,6 +454,14 @@ public: - return _rem_set; - } - -+ uint processing_order() { -+ return _processing_order; -+ } -+ -+ void set_processing_order(uint processing_order) { -+ _processing_order = processing_order; -+ } -+ - inline bool in_collection_set() const; - - // Methods used by the HeapRegionSetBase class and subclasses. -diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp -index 72f571645a5..1d13c647452 100644 ---- a/src/hotspot/share/gc/serial/genMarkSweep.cpp -+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp -@@ -334,5 +334,7 @@ void GenMarkSweep::mark_sweep_phase4() { - - GenCompactClosure blk; - gch->generation_iterate(&blk, true); -- MarkSweep::copy_rescued_objects_back(); -+ DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); -+ DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); -+ MarkSweep::_rescued_oops = NULL; - } -diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp -index c7befd2f63d..c0108bad092 100644 ---- a/src/hotspot/share/gc/serial/markSweep.cpp -+++ b/src/hotspot/share/gc/serial/markSweep.cpp -@@ -224,100 +224,3 @@ void MarkSweep::initialize() { - MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); - MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer(); - } -- --// (DCEVM) Copy the rescued objects to their destination address after compaction. --void MarkSweep::copy_rescued_objects_back() { -- -- if (_rescued_oops != NULL) { -- -- for (int i=0; i<_rescued_oops->length(); i++) { -- HeapWord* rescued_ptr = _rescued_oops->at(i); -- oop rescued_obj = (oop) rescued_ptr; -- -- int size = rescued_obj->size(); -- oop new_obj = rescued_obj->forwardee(); -- -- assert(rescued_obj->klass()->new_version() != NULL, "just checking"); -- -- if (rescued_obj->klass()->new_version()->update_information() != NULL) { -- MarkSweep::update_fields(rescued_obj, new_obj); -- } else { -- rescued_obj->set_klass(rescued_obj->klass()->new_version()); -- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -- } -- -- FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); -- -- new_obj->init_mark(); -- assert(oopDesc::is_oop(new_obj), "must be a valid oop"); -- } -- _rescued_oops->clear(); -- _rescued_oops = NULL; -- } --} -- --// (DCEVM) Update instances of a class whose fields changed. --void MarkSweep::update_fields(oop q, oop new_location) { -- -- assert(q->klass()->new_version() != NULL, "class of old object must have new version"); -- -- Klass* old_klass_oop = q->klass(); -- Klass* new_klass_oop = q->klass()->new_version(); -- -- InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); -- InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); -- -- int size = q->size_given_klass(old_klass); -- int new_size = q->size_given_klass(new_klass); -- -- HeapWord* tmp = NULL; -- oop tmp_obj = q; -- -- // Save object somewhere, there is an overlap in fields -- if (new_klass_oop->is_copying_backwards()) { -- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || -- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { -- tmp = NEW_RESOURCE_ARRAY(HeapWord, size); -- q = (oop) tmp; -- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); -- } -- } -- -- q->set_klass(new_klass_oop); -- int *cur = new_klass_oop->update_information(); -- assert(cur != NULL, "just checking"); -- MarkSweep::update_fields(new_location, q, cur); -- -- if (tmp != NULL) { -- FREE_RESOURCE_ARRAY(HeapWord, tmp, size); -- } --} -- --void MarkSweep::update_fields(oop new_location, oop tmp_obj, int *cur) { -- assert(cur != NULL, "just checking"); -- char* to = (char*)(HeapWord*)new_location; -- while (*cur != 0) { -- int size = *cur; -- if (size > 0) { -- cur++; -- int offset = *cur; -- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); -- if (size == HeapWordSize) { -- *((HeapWord*)to) = *from; -- } else if (size == HeapWordSize * 2) { -- *((HeapWord*)to) = *from; -- *(((HeapWord*)to) + 1) = *(from + 1); -- } else { -- Copy::conjoint_jbytes(from, to, size); -- } -- to += size; -- cur++; -- } else { -- assert(size < 0, ""); -- int skip = -*cur; -- Copy::fill_to_bytes(to, skip, 0); -- to += skip; -- cur++; -- } -- } --} -diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp -index e12ac327d90..92af0e36a1c 100644 ---- a/src/hotspot/share/gc/serial/markSweep.hpp -+++ b/src/hotspot/share/gc/serial/markSweep.hpp -@@ -148,9 +148,6 @@ class MarkSweep : AllStatic { - - static int adjust_pointers(oop obj); - -- static void copy_rescued_objects_back(); -- static void update_fields(oop q, oop new_location); -- static void update_fields(oop new_location, oop tmp_obj, int *cur); - static void follow_stack(); // Empty marking stack. - - static void follow_klass(Klass* klass); -diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp -new file mode 100644 -index 00000000000..803e645f843 ---- /dev/null -+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp -@@ -0,0 +1,159 @@ -+/* -+ * Copyright (c) 1997, 2018, 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/shared/dcevmSharedGC.hpp" -+#include "memory/iterator.inline.hpp" -+#include "oops/access.inline.hpp" -+#include "oops/compressedOops.inline.hpp" -+#include "oops/instanceClassLoaderKlass.inline.hpp" -+#include "oops/instanceKlass.inline.hpp" -+#include "oops/instanceMirrorKlass.inline.hpp" -+#include "oops/instanceRefKlass.inline.hpp" -+#include "oops/oop.inline.hpp" -+#include "utilities/macros.hpp" -+ -+void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_oops, bool must_be_new) { -+ if (rescued_oops != NULL) { -+ copy_rescued_objects_back(rescued_oops, 0, rescued_oops->length(), must_be_new); -+ } -+} -+ -+// (DCEVM) Copy the rescued objects to their destination address after compaction. -+void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_oops, int from, int to, bool must_be_new) { -+ -+ if (rescued_oops != NULL) { -+ for (int i=from; i < to; i++) { -+ HeapWord* rescued_ptr = rescued_oops->at(i); -+ oop rescued_obj = (oop) rescued_ptr; -+ -+ int size = rescued_obj->size(); -+ oop new_obj = rescued_obj->forwardee(); -+ -+ assert(!must_be_new || rescued_obj->klass()->new_version() != NULL, "Just checking"); -+ Klass* new_klass = rescued_obj->klass()->new_version(); -+ if (new_klass!= NULL) { -+ if (new_klass->update_information() != NULL) { -+ DcevmSharedGC::update_fields(rescued_obj, new_obj); -+ } else { -+ rescued_obj->set_klass(new_klass); -+ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -+ } -+ } else { -+ Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -+ } -+ -+ new_obj->init_mark_raw(); -+ assert(oopDesc::is_oop(new_obj), "must be a valid oop"); -+ } -+ } -+ -+} -+ -+void DcevmSharedGC::clear_rescued_objects_resource(GrowableArray* rescued_oops) { -+ if (rescued_oops != NULL) { -+ for (int i=0; i < rescued_oops->length(); i++) { -+ HeapWord* rescued_ptr = rescued_oops->at(i); -+ int size = ((oop) rescued_ptr)->size(); -+ FREE_RESOURCE_ARRAY(HeapWord, rescued_ptr, size); -+ } -+ rescued_oops->clear(); -+ } -+} -+ -+void DcevmSharedGC::clear_rescued_objects_heap(GrowableArray* rescued_oops) { -+ if (rescued_oops != NULL) { -+ for (int i=0; i < rescued_oops->length(); i++) { -+ HeapWord* rescued_ptr = rescued_oops->at(i); -+ FREE_C_HEAP_ARRAY(HeapWord, rescued_ptr); -+ } -+ rescued_oops->clear(); -+ } -+} -+ -+// (DCEVM) Update instances of a class whose fields changed. -+void DcevmSharedGC::update_fields(oop q, oop new_location) { -+ -+ assert(q->klass()->new_version() != NULL, "class of old object must have new version"); -+ -+ Klass* old_klass_oop = q->klass(); -+ Klass* new_klass_oop = q->klass()->new_version(); -+ -+ InstanceKlass *old_klass = InstanceKlass::cast(old_klass_oop); -+ InstanceKlass *new_klass = InstanceKlass::cast(new_klass_oop); -+ -+ int size = q->size_given_klass(old_klass); -+ int new_size = q->size_given_klass(new_klass); -+ -+ HeapWord* tmp = NULL; -+ oop tmp_obj = q; -+ -+ // Save object somewhere, there is an overlap in fields -+ if (new_klass_oop->is_copying_backwards()) { -+ if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || -+ ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { -+ tmp = NEW_RESOURCE_ARRAY(HeapWord, size); -+ q = (oop) tmp; -+ Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); -+ } -+ } -+ -+ q->set_klass(new_klass_oop); -+ int *cur = new_klass_oop->update_information(); -+ assert(cur != NULL, "just checking"); -+ DcevmSharedGC::update_fields(new_location, q, cur); -+ -+ if (tmp != NULL) { -+ FREE_RESOURCE_ARRAY(HeapWord, tmp, size); -+ } -+} -+ -+void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) { -+ assert(cur != NULL, "just checking"); -+ char* to = (char*)(HeapWord*)new_location; -+ while (*cur != 0) { -+ int size = *cur; -+ if (size > 0) { -+ cur++; -+ int offset = *cur; -+ HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); -+ if (size == HeapWordSize) { -+ *((HeapWord*)to) = *from; -+ } else if (size == HeapWordSize * 2) { -+ *((HeapWord*)to) = *from; -+ *(((HeapWord*)to) + 1) = *(from + 1); -+ } else { -+ Copy::conjoint_jbytes(from, to, size); -+ } -+ to += size; -+ cur++; -+ } else { -+ assert(size < 0, ""); -+ int skip = -*cur; -+ Copy::fill_to_bytes(to, skip, 0); -+ to += skip; -+ cur++; -+ } -+ } -+} -diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp -new file mode 100644 -index 00000000000..e2ef0171fb2 ---- /dev/null -+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) 1997, 2018, 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_GC_DCEVM_SHARED_GC_HPP -+#define SHARE_GC_DCEVM_SHARED_GC_HPP -+ -+#include "gc/shared/collectedHeap.hpp" -+#include "gc/shared/genOopClosures.hpp" -+#include "gc/shared/taskqueue.hpp" -+#include "memory/iterator.hpp" -+#include "oops/markOop.hpp" -+#include "oops/oop.hpp" -+#include "runtime/timer.hpp" -+#include "utilities/growableArray.hpp" -+#include "utilities/stack.hpp" -+ -+// Shared GC code used from different GC (Serial, CMS, G1) on enhanced redefinition -+class DcevmSharedGC : AllStatic { -+ public: -+ static void copy_rescued_objects_back(GrowableArray* rescued_oops, bool must_be_new); -+ static void copy_rescued_objects_back(GrowableArray* rescued_oops, int from, int to, bool must_be_new); -+ static void clear_rescued_objects_resource(GrowableArray* rescued_oops); -+ static void clear_rescued_objects_heap(GrowableArray* rescued_oops); -+ static void update_fields(oop q, oop new_location); -+ static void update_fields(oop new_location, oop tmp_obj, int *cur); -+}; -+ -+#endif -diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp -index fdb1c806559..f01d64d1434 100644 ---- a/src/hotspot/share/gc/shared/gcConfig.cpp -+++ b/src/hotspot/share/gc/shared/gcConfig.cpp -@@ -98,7 +98,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { - } - - void GCConfig::select_gc_ergonomically() { -- if (AllowEnhancedClassRedefinition) { -+ if (AllowEnhancedClassRedefinition && !UseG1GC) { - // Enhanced class redefinition only supports serial GC at the moment - FLAG_SET_ERGO(bool, UseSerialGC, true); - } else if (os::is_server_class_machine()) { -diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp -index 875c3fdf319..5a93e93471b 100644 ---- a/src/hotspot/share/gc/shared/space.inline.hpp -+++ b/src/hotspot/share/gc/shared/space.inline.hpp -@@ -37,6 +37,7 @@ - #if INCLUDE_SERIALGC - #include "gc/serial/markSweep.inline.hpp" - #endif -+#include "gc/shared/dcevmSharedGC.hpp" - - inline HeapWord* Space::block_start(const void* p) { - return block_start_const(p); -@@ -369,7 +370,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti - Copy::aligned_conjoint_words(cur_obj, compaction_top, size); - oop(compaction_top)->set_klass(new_version); - } else { -- MarkSweep::update_fields(oop(cur_obj), oop(compaction_top)); -+ DcevmSharedGC::update_fields(oop(cur_obj), oop(compaction_top)); - } - oop(compaction_top)->init_mark_raw(); - assert(oop(compaction_top)->klass() != NULL, "should have a class"); -diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp -index d38cd348e1b..f6e4253b5a5 100644 ---- a/src/hotspot/share/memory/universe.cpp -+++ b/src/hotspot/share/memory/universe.cpp -@@ -212,6 +212,11 @@ void Universe::root_oops_do(OopClosure *oopClosure) { - //ref_processor()->weak_oops_do(&oopClosure); - //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); - -+#if INCLUDE_AOT -+ if (UseAOT) { -+ AOTLoader::oops_do(oopClosure); -+ } -+#endif - // SO_AllClasses - SystemDictionary::oops_do(oopClosure); - } -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index a859b8e1162..6c9eb40ecf5 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -36,7 +36,6 @@ - #include "memory/metaspaceShared.hpp" - #include "memory/resourceArea.hpp" - #include "memory/iterator.inline.hpp" --#include "gc/serial/markSweep.hpp" - #include "oops/fieldStreams.hpp" - #include "oops/klassVtable.hpp" - #include "oops/oop.inline.hpp" -@@ -54,6 +53,8 @@ - #include "prims/jvmtiThreadState.inline.hpp" - #include "utilities/events.hpp" - #include "oops/constantPool.inline.hpp" -+#include "gc/g1/g1CollectedHeap.hpp" -+#include "gc/shared/dcevmSharedGC.hpp" - - Array* VM_EnhancedRedefineClasses::_old_methods = NULL; - Array* VM_EnhancedRedefineClasses::_new_methods = NULL; -@@ -77,7 +78,7 @@ Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; - // - class_defs class definition - either new class or redefined class - // note that this is not the final array of classes to be redefined - // we need to scan for all affected classes (e.g. subclasses) and --// caculcate redefinition for them as well. -+// calculate redefinition for them as well. - // @param class_load_kind always jvmti_class_load_kind_redefine - VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, JvmtiClassLoadKind class_load_kind) : - VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) { -@@ -215,6 +216,13 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { - } - } - -+void VM_EnhancedRedefineClasses::mark_as_scavengable_g1(nmethod* nm) { -+ // It should work not only for G1 but also for another GCs, but this way is safer now -+ if (!nm->is_zombie() && !nm->is_unloaded()) { -+ Universe::heap()->register_nmethod(nm); -+ } -+} -+ - // TODO comment - struct StoreBarrier { - // TODO: j10 review change ::oop_store -> HeapAccess<>::oop_store -@@ -431,12 +439,7 @@ public: - src->set_klass(obj->klass()->new_version()); - // FIXME: instance updates... - //guarantee(false, "instance updates!"); -- MarkSweep::update_fields(obj, src, new_klass->update_information()); -- -- if (size_diff > 0) { -- HeapWord* dead_space = ((HeapWord *)obj) + obj->size(); -- CollectedHeap::fill_with_object(dead_space, size_diff); -- } -+ DcevmSharedGC::update_fields(obj, src, new_klass->update_information()); - } - } else { - obj->set_klass(obj->klass()->new_version()); -@@ -458,6 +461,10 @@ public: - void VM_EnhancedRedefineClasses::doit() { - Thread *thread = Thread::current(); - -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_vm_op_doit.start(); -+ } -+ - #if INCLUDE_CDS - if (UseSharedSpaces) { - // Sharing is enabled so we remap the shared readonly space to -@@ -513,12 +520,31 @@ void VM_EnhancedRedefineClasses::doit() { - // mark such nmethod's as "scavengable". - // For now, mark all nmethod's as scavengable that are not scavengable already - if (ScavengeRootsInCode) { -- CodeCache::nmethods_do(mark_as_scavengable); -+ if (UseG1GC) { -+ // this should work also for other GCs -+ CodeCache::nmethods_do(mark_as_scavengable_g1); -+ } else { -+ CodeCache::nmethods_do(mark_as_scavengable); -+ } - } - - Universe::heap()->ensure_parsability(false); -- Universe::heap()->object_iterate(&objectClosure); -+ if (UseG1GC) { -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_heap_iterate.start(); -+ } -+ G1CollectedHeap::heap()->object_par_iterate(&objectClosure); -+ _timer_heap_iterate.stop(); -+ } else { -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_heap_iterate.start(); -+ } -+ Universe::heap()->object_iterate(&objectClosure); -+ _timer_heap_iterate.stop(); -+ } -+ - Universe::root_oops_do(&oopClosureNoBarrier); -+ - } - log_trace(redefine, class, obsolete, metadata)("After updating instances"); - -@@ -571,11 +597,19 @@ void VM_EnhancedRedefineClasses::doit() { - - if (objectClosure.needs_instance_update()) { - // Do a full garbage collection to update the instance sizes accordingly -+ -+ if (log_is_enabled(Info, redefine, class, timer)) { -+ _timer_heap_full_gc.start(); -+ } -+ - Universe::set_redefining_gc_run(true); - notify_gc_begin(true); -+ // TODO: check _metadata_GC_clear_soft_refs with ScavengeRootsInCode - Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); - notify_gc_end(); - Universe::set_redefining_gc_run(false); -+ -+ _timer_heap_full_gc.stop(); - } - - // Unmark Klass*s as "redefining" -@@ -623,6 +657,7 @@ void VM_EnhancedRedefineClasses::doit() { - } - #endif - -+ _timer_vm_op_doit.stop(); - } - - // Cleanup - runs in JVM thread -@@ -646,16 +681,14 @@ void VM_EnhancedRedefineClasses::doit_epilogue() { - if (log_is_enabled(Info, redefine, class, timer)) { - // Used to have separate timers for "doit" and "all", but the timer - // overhead skewed the measurements. -- jlong doit_time = _timer_rsc_phase1.milliseconds() + -- _timer_rsc_phase2.milliseconds(); -- jlong all_time = _timer_vm_op_prologue.milliseconds() + doit_time; -+ jlong all_time = _timer_vm_op_prologue.milliseconds() + _timer_vm_op_doit.milliseconds(); - - log_info(redefine, class, timer) - ("vm_op: all=" JLONG_FORMAT " prologue=" JLONG_FORMAT " doit=" JLONG_FORMAT, -- all_time, _timer_vm_op_prologue.milliseconds(), doit_time); -+ all_time, _timer_vm_op_prologue.milliseconds(), _timer_vm_op_doit.milliseconds()); - log_info(redefine, class, timer) -- ("redefine_single_class: phase1=" JLONG_FORMAT " phase2=" JLONG_FORMAT, -- _timer_rsc_phase1.milliseconds(), _timer_rsc_phase2.milliseconds()); -+ ("doit: heap iterate=" JLONG_FORMAT " fullgc=" JLONG_FORMAT, -+ _timer_heap_iterate.milliseconds(), _timer_heap_full_gc.milliseconds()); - } - } - -@@ -1404,7 +1437,7 @@ void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { - // arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. - void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - if (!k->is_instance_klass()) { -- return; -+ return; - } - - HandleMark hm(_thread); -@@ -1590,7 +1623,7 @@ class TransferNativeFunctionRegistration { - - // Recursively search the binary tree of possibly prefixed method names. - // Iteration could be used if all agents were well behaved. Full tree walk is -- // more resilent to agents not cleaning up intermediate methods. -+ // more resilient to agents not cleaning up intermediate methods. - // Branch at each depth in the binary tree is: - // (1) without the prefix. - // (2) with the prefix. -@@ -1695,7 +1728,7 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst - transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); - } - --// DCEVM - it always deoptimases everything! (because it is very difficult to find only correct dependencies) -+// DCEVM - it always deoptimizes everything! (because it is very difficult to find only correct dependencies) - // Deoptimize all compiled code that depends on this class. - // - // If the can_redefine_classes capability is obtained in the onload -@@ -1822,10 +1855,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - - HandleMark hm(THREAD); // make sure handles from this call are freed - -- if (log_is_enabled(Info, redefine, class, timer)) { -- _timer_rsc_phase1.start(); -- } -- - InstanceKlass* new_class = new_class_oop; - InstanceKlass* the_class = InstanceKlass::cast(new_class_oop->old_version()); - assert(the_class != NULL, "must have old version"); -@@ -1880,7 +1909,6 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - new_class->external_name(), - java_lang_Class::classRedefinedCount(new_class->java_mirror())); - } -- _timer_rsc_phase2.stop(); - } // end redefine_single_class() - - -@@ -2063,8 +2091,8 @@ static bool match_second(void* value, KlassPair elem) { - // For each class to be redefined parse the bytecode and figure out the superclass and all interfaces. - // First newly introduced classes (_class_defs) are scanned and then affected classed (_affected_klasses). - // Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected)) --// For each dependency create a KlassPair instance. Finnaly, affected classes (_affected_klasses) are sorted according to pairs. --// TODO - the class file is potentionally parsed multiple times - introduce a cache? -+// For each dependency create a KlassPair instance. Finally, affected classes (_affected_klasses) are sorted according to pairs. -+// TODO - the class file is potentially parsed multiple times - introduce a cache? - jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { - ResourceMark mark(THREAD); - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index d8a11b51fe9..9755944d70b 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -86,9 +86,10 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // Performance measurement support. These timers do not cover all - // the work done for JVM/TI RedefineClasses() but they do cover - // the heavy lifting. -- elapsedTimer _timer_rsc_phase1; -- elapsedTimer _timer_rsc_phase2; -+ elapsedTimer _timer_vm_op_doit; - elapsedTimer _timer_vm_op_prologue; -+ elapsedTimer _timer_heap_iterate; -+ elapsedTimer _timer_heap_full_gc; - - // These routines are roughly in call order unless otherwise noted. - -@@ -115,6 +116,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - - void rollback(); - static void mark_as_scavengable(nmethod* nm); -+ static void mark_as_scavengable_g1(nmethod* nm); - static void unpatch_bytecode(Method* method); - static void fix_invoke_method(Method* method); - -diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index 2803a3c46eb..d05a2893498 100644 ---- a/src/hotspot/share/runtime/arguments.cpp -+++ b/src/hotspot/share/runtime/arguments.cpp -@@ -2134,9 +2134,9 @@ bool Arguments::check_gc_consistency() { - if (AllowEnhancedClassRedefinition) { - // Must use serial GC. This limitation applies because the instance size changing GC modifications - // are only built into the mark and compact algorithm. -- if (!UseSerialGC && i >= 1) { -+ if ((!UseSerialGC && !UseG1GC) && i >= 1) { - jio_fprintf(defaultStream::error_stream(), -- "Must use the serial GC with enhanced class redefinition\n"); -+ "Must use the Serial or G1 GC with enhanced class redefinition.\n"); - return false; - } - } -diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp -index 972b702b4cb..548440e06b6 100644 ---- a/src/hotspot/share/utilities/growableArray.hpp -+++ b/src/hotspot/share/utilities/growableArray.hpp -@@ -560,6 +560,10 @@ template class GrowableArrayIterator : public StackObj { - assert(_array == rhs._array, "iterator belongs to different array"); - return _position != rhs._position; - } -+ -+ bool at_end() { return _position >= _array->length(); } -+ -+ bool has_next() { return _position < _array->length() - 1; } - }; - - // Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch b/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch deleted file mode 100644 index 1e8c4416e343..000000000000 --- a/jb/project/tools/patches/dcevm/0009-Change-log-level-in-advanced-redefinition.patch +++ /dev/null @@ -1,50 +0,0 @@ -From ca47ab5a0a6ce8e2644736f323a335a957311af9 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sat, 13 Jun 2020 18:50:59 +0200 -Subject: [PATCH 09/34] Change log level in advanced redefinition - -- Change log level for "Comparing different class ver.." to debug -- Fix adjust_method_entries_dcevm logging levels and severity ---- - src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 +- - src/hotspot/share/prims/resolvedMethodTable.cpp | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 6c9eb40ecf5..b09ba554e07 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -916,7 +916,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - // Calculated the difference between new and old class (field change, method change, supertype change, ...). - int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) { - int result = Klass::NoRedefinition; -- log_info(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); -+ log_debug(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string()); - - assert(new_class->old_version() != NULL, "must have old version"); - InstanceKlass* the_class = InstanceKlass::cast(new_class->old_version()); -diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp -index caf03ffe56d..eb9fcda44f3 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.cpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp -@@ -413,7 +413,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) - } else { - newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); - -- log_info(redefine, class, load, exceptions)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); -+ log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); - - assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); - assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -@@ -433,7 +433,7 @@ void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) - - ResourceMark rm; - if (!(*trace_name_printed)) { -- log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); -+ log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_debug(redefine, class, update, constantpool) --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch b/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch deleted file mode 100644 index a846a414e517..000000000000 --- a/jb/project/tools/patches/dcevm/0010-AllowEnhancedClassRedefinition-is-false-disabled-by-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 7e236beee0375656d1955fc1168143c1639fb7f1 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Tue, 6 Oct 2020 22:15:31 +0200 -Subject: [PATCH 10/34] AllowEnhancedClassRedefinition is false (disabled) by - default - ---- - src/hotspot/share/runtime/globals.hpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp -index 5b367704800..2710c6ea0e5 100644 ---- a/src/hotspot/share/runtime/globals.hpp -+++ b/src/hotspot/share/runtime/globals.hpp -@@ -2466,7 +2466,7 @@ const size_t minimumSymbolTableSize = 1024; - diagnostic(bool, DeoptimizeNMethodBarriersALot, false, \ - "Make nmethod barriers deoptimise a lot.") \ - \ -- product(bool, AllowEnhancedClassRedefinition, true, \ -+ product(bool, AllowEnhancedClassRedefinition, false, \ - "Allow enhanced class redefinition beyond swapping method " \ - "bodies") \ - \ --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch b/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch deleted file mode 100644 index d0853abe9db5..000000000000 --- a/jb/project/tools/patches/dcevm/0011-add-jvmtiEnhancedRedefineClasses.-to-CMakeLists.txt.patch +++ /dev/null @@ -1,2977 +0,0 @@ -From ab2cfbfa4f5758d26b9e32f5e779a7e56eba1a90 Mon Sep 17 00:00:00 2001 -From: Artem Khvastunov -Date: Tue, 14 Apr 2020 19:11:35 +0200 -Subject: [PATCH 11/34] add jvmtiEnhancedRedefineClasses.* to CMakeLists.txt - ---- - jb/project/hotspot-cmake/CMakeLists.txt | 2958 +++++++++++++++++++++++ - 1 file changed, 2958 insertions(+) - create mode 100644 jb/project/hotspot-cmake/CMakeLists.txt - -diff --git a/jb/project/hotspot-cmake/CMakeLists.txt b/jb/project/hotspot-cmake/CMakeLists.txt -new file mode 100644 -index 00000000000..6516e39058f ---- /dev/null -+++ b/jb/project/hotspot-cmake/CMakeLists.txt -@@ -0,0 +1,2958 @@ -+cmake_minimum_required(VERSION 3.9) -+project(hotspot) -+ -+include(../java-common.cmake) -+ -+include_directories( -+../../../src/hotspot/cpu/aarch64 -+../../../src/hotspot/cpu/aarch64/gc/g1 -+../../../src/hotspot/cpu/aarch64/gc/shared -+../../../src/hotspot/cpu/arm -+../../../src/hotspot/cpu/arm/gc/g1 -+../../../src/hotspot/cpu/arm/gc/shared -+../../../src/hotspot/cpu/ppc -+../../../src/hotspot/cpu/ppc/gc/g1 -+../../../src/hotspot/cpu/ppc/gc/shared -+../../../src/hotspot/cpu/s390 -+../../../src/hotspot/cpu/s390/gc/g1 -+../../../src/hotspot/cpu/s390/gc/shared -+../../../src/hotspot/cpu/sparc -+../../../src/hotspot/cpu/sparc/gc/g1 -+../../../src/hotspot/cpu/sparc/gc/shared -+../../../src/hotspot/cpu/x86 -+../../../src/hotspot/cpu/x86/gc/g1 -+../../../src/hotspot/cpu/x86/gc/shared -+../../../src/hotspot/cpu/x86/gc/z -+../../../src/hotspot/cpu/zero -+../../../src/hotspot/cpu/zero/gc/g1 -+../../../src/hotspot/cpu/zero/gc/shared -+../../../src/hotspot/os/aix -+../../../src/hotspot/os/bsd -+../../../src/hotspot/os/linux -+../../../src/hotspot/os/posix -+../../../src/hotspot/os/solaris -+../../../src/hotspot/os/windows -+../../../src/hotspot/os_cpu/aix_ppc -+../../../src/hotspot/os_cpu/bsd_x86 -+../../../src/hotspot/os_cpu/bsd_zero -+../../../src/hotspot/os_cpu/linux_aarch64 -+../../../src/hotspot/os_cpu/linux_arm -+../../../src/hotspot/os_cpu/linux_ppc -+../../../src/hotspot/os_cpu/linux_s390 -+../../../src/hotspot/os_cpu/linux_sparc -+../../../src/hotspot/os_cpu/linux_x86 -+../../../src/hotspot/os_cpu/linux_x86/gc/z -+../../../src/hotspot/os_cpu/linux_zero -+../../../src/hotspot/os_cpu/solaris_sparc -+../../../src/hotspot/os_cpu/solaris_x86 -+../../../src/hotspot/os_cpu/windows_x86 -+../../../src/hotspot/share -+) -+ -+set(SOURCE_FILES -+../../../src/hotspot/cpu/ppc/depChecker_ppc.hpp -+../../../src/hotspot/cpu/ppc/assembler_ppc.inline.hpp -+../../../src/hotspot/cpu/ppc/icache_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/vmreg_ppc.cpp -+../../../src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp -+../../../src/hotspot/cpu/ppc/compiledIC_ppc.cpp -+../../../src/hotspot/cpu/ppc/frame_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_globals_ppc.hpp -+../../../src/hotspot/cpu/ppc/relocInfo_ppc.hpp -+../../../src/hotspot/cpu/ppc/icBuffer_ppc.cpp -+../../../src/hotspot/cpu/ppc/register_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_LinearScan_ppc.cpp -+../../../src/hotspot/cpu/ppc/jvmciCodeInstaller_ppc.cpp -+../../../src/hotspot/cpu/ppc/assembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/methodHandles_ppc.hpp -+../../../src/hotspot/cpu/ppc/codeBuffer_ppc.hpp -+../../../src/hotspot/cpu/ppc/templateTable_ppc_64.cpp -+../../../src/hotspot/cpu/ppc/interpreterRT_ppc.cpp -+../../../src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp -+../../../src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp -+../../../src/hotspot/cpu/ppc/stubRoutines_ppc.hpp -+../../../src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp -+../../../src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/macroAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/globals_ppc.hpp -+../../../src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp -+../../../src/hotspot/cpu/ppc/frame_ppc.inline.hpp -+../../../src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp -+../../../src/hotspot/cpu/ppc/macroAssembler_ppc_sha.cpp -+../../../src/hotspot/cpu/ppc/jniTypes_ppc.hpp -+../../../src/hotspot/cpu/ppc/nativeInst_ppc.hpp -+../../../src/hotspot/cpu/ppc/bytes_ppc.hpp -+../../../src/hotspot/cpu/ppc/vm_version_ext_ppc.cpp -+../../../src/hotspot/cpu/ppc/copy_ppc.hpp -+../../../src/hotspot/cpu/ppc/vm_version_ppc.hpp -+../../../src/hotspot/cpu/ppc/runtime_ppc.cpp -+../../../src/hotspot/cpu/ppc/macroAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/register_definitions_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp -+../../../src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp -+../../../src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp -+../../../src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp -+../../../src/hotspot/cpu/ppc/nativeInst_ppc.cpp -+../../../src/hotspot/cpu/ppc/templateTable_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_LIR_ppc.cpp -+../../../src/hotspot/cpu/ppc/vm_version_ext_ppc.hpp -+../../../src/hotspot/cpu/ppc/c2_globals_ppc.hpp -+../../../src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/c2_init_ppc.cpp -+../../../src/hotspot/cpu/ppc/vm_version_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp -+../../../src/hotspot/cpu/ppc/icache_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_Defs_ppc.hpp -+../../../src/hotspot/cpu/ppc/vmreg_ppc.hpp -+../../../src/hotspot/cpu/ppc/vmStructs_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_FpuStackSim_ppc.hpp -+../../../src/hotspot/cpu/ppc/frame_ppc.hpp -+../../../src/hotspot/cpu/ppc/registerMap_ppc.hpp -+../../../src/hotspot/cpu/ppc/relocInfo_ppc.cpp -+../../../src/hotspot/cpu/ppc/register_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_FrameMap_ppc.hpp -+../../../src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp -+../../../src/hotspot/cpu/ppc/c1_LinearScan_ppc.hpp -+../../../src/hotspot/cpu/ppc/assembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/methodHandles_ppc.cpp -+../../../src/hotspot/cpu/ppc/disassembler_ppc.hpp -+../../../src/hotspot/cpu/ppc/interp_masm_ppc.hpp -+../../../src/hotspot/cpu/ppc/interpreterRT_ppc.hpp -+../../../src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp -+../../../src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp -+../../../src/hotspot/cpu/ppc/stubGenerator_ppc.cpp -+../../../src/hotspot/cpu/s390/stubRoutines_s390.hpp -+../../../src/hotspot/cpu/s390/frame_s390.hpp -+../../../src/hotspot/cpu/s390/compiledIC_s390.cpp -+../../../src/hotspot/cpu/s390/interp_masm_s390.cpp -+../../../src/hotspot/cpu/s390/nativeInst_s390.cpp -+../../../src/hotspot/cpu/s390/interpreterRT_s390.hpp -+../../../src/hotspot/cpu/s390/c1_LinearScan_s390.hpp -+../../../src/hotspot/cpu/s390/c1_LIR_s390.cpp -+../../../src/hotspot/cpu/s390/relocInfo_s390.cpp -+../../../src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp -+../../../src/hotspot/cpu/s390/stubGenerator_s390.cpp -+../../../src/hotspot/cpu/s390/vmreg_s390.cpp -+../../../src/hotspot/cpu/s390/macroAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/c2_init_s390.cpp -+../../../src/hotspot/cpu/s390/runtime_s390.cpp -+../../../src/hotspot/cpu/s390/c1_FpuStackSim_s390.hpp -+../../../src/hotspot/cpu/s390/icBuffer_s390.cpp -+../../../src/hotspot/cpu/s390/vmreg_s390.inline.hpp -+../../../src/hotspot/cpu/s390/vm_version_ext_s390.hpp -+../../../src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp -+../../../src/hotspot/cpu/s390/c1_globals_s390.hpp -+../../../src/hotspot/cpu/s390/assembler_s390.hpp -+../../../src/hotspot/cpu/s390/vmStructs_s390.hpp -+../../../src/hotspot/cpu/s390/sharedRuntime_s390.cpp -+../../../src/hotspot/cpu/s390/templateTable_s390.hpp -+../../../src/hotspot/cpu/s390/methodHandles_s390.hpp -+../../../src/hotspot/cpu/s390/globals_s390.hpp -+../../../src/hotspot/cpu/s390/c1_FrameMap_s390.hpp -+../../../src/hotspot/cpu/s390/register_s390.hpp -+../../../src/hotspot/cpu/s390/register_definitions_s390.cpp -+../../../src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp -+../../../src/hotspot/cpu/s390/icache_s390.cpp -+../../../src/hotspot/cpu/s390/registerSaver_s390.hpp -+../../../src/hotspot/cpu/s390/codeBuffer_s390.hpp -+../../../src/hotspot/cpu/s390/vm_version_s390.hpp -+../../../src/hotspot/cpu/s390/c1_Defs_s390.hpp -+../../../src/hotspot/cpu/s390/templateTable_s390.cpp -+../../../src/hotspot/cpu/s390/globalDefinitions_s390.hpp -+../../../src/hotspot/cpu/s390/methodHandles_s390.cpp -+../../../src/hotspot/cpu/s390/register_s390.cpp -+../../../src/hotspot/cpu/s390/c1_FrameMap_s390.cpp -+../../../src/hotspot/cpu/s390/copy_s390.hpp -+../../../src/hotspot/cpu/s390/frame_s390.inline.hpp -+../../../src/hotspot/cpu/s390/abstractInterpreter_s390.cpp -+../../../src/hotspot/cpu/s390/icache_s390.hpp -+../../../src/hotspot/cpu/s390/jvmciCodeInstaller_s390.cpp -+../../../src/hotspot/cpu/s390/bytes_s390.hpp -+../../../src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp -+../../../src/hotspot/cpu/s390/jniTypes_s390.hpp -+../../../src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp -+../../../src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/vm_version_s390.cpp -+../../../src/hotspot/cpu/s390/frame_s390.cpp -+../../../src/hotspot/cpu/s390/stubRoutines_s390.cpp -+../../../src/hotspot/cpu/s390/interp_masm_s390.hpp -+../../../src/hotspot/cpu/s390/disassembler_s390.hpp -+../../../src/hotspot/cpu/s390/c1_LinearScan_s390.cpp -+../../../src/hotspot/cpu/s390/interpreterRT_s390.cpp -+../../../src/hotspot/cpu/s390/macroAssembler_s390.inline.hpp -+../../../src/hotspot/cpu/s390/nativeInst_s390.hpp -+../../../src/hotspot/cpu/s390/vtableStubs_s390.cpp -+../../../src/hotspot/cpu/s390/relocInfo_s390.hpp -+../../../src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/vmreg_s390.hpp -+../../../src/hotspot/cpu/s390/depChecker_s390.hpp -+../../../src/hotspot/cpu/s390/macroAssembler_s390.hpp -+../../../src/hotspot/cpu/s390/jniFastGetField_s390.cpp -+../../../src/hotspot/cpu/s390/c2_globals_s390.hpp -+../../../src/hotspot/cpu/s390/c1_Runtime1_s390.cpp -+../../../src/hotspot/cpu/s390/registerMap_s390.hpp -+../../../src/hotspot/cpu/s390/vm_version_ext_s390.cpp -+../../../src/hotspot/cpu/s390/assembler_s390.inline.hpp -+../../../src/hotspot/cpu/s390/assembler_s390.cpp -+../../../src/hotspot/cpu/zero/disassembler_zero.cpp -+../../../src/hotspot/cpu/zero/frame_zero.hpp -+../../../src/hotspot/cpu/zero/compiledIC_zero.cpp -+../../../src/hotspot/cpu/zero/stubRoutines_zero.hpp -+../../../src/hotspot/cpu/zero/vmreg_zero.cpp -+../../../src/hotspot/cpu/zero/stubGenerator_zero.cpp -+../../../src/hotspot/cpu/zero/interpreterRT_zero.hpp -+../../../src/hotspot/cpu/zero/nativeInst_zero.cpp -+../../../src/hotspot/cpu/zero/relocInfo_zero.cpp -+../../../src/hotspot/cpu/zero/icBuffer_zero.cpp -+../../../src/hotspot/cpu/zero/depChecker_zero.cpp -+../../../src/hotspot/cpu/zero/vmStructs_zero.hpp -+../../../src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp -+../../../src/hotspot/cpu/zero/stack_zero.hpp -+../../../src/hotspot/cpu/zero/assembler_zero.hpp -+../../../src/hotspot/cpu/zero/vm_version_ext_zero.hpp -+../../../src/hotspot/cpu/zero/frame_zero.inline.hpp -+../../../src/hotspot/cpu/zero/sharedRuntime_zero.cpp -+../../../src/hotspot/cpu/zero/cppInterpreter_zero.cpp -+../../../src/hotspot/cpu/zero/macroAssembler_zero.inline.hpp -+../../../src/hotspot/cpu/zero/globals_zero.hpp -+../../../src/hotspot/cpu/zero/methodHandles_zero.hpp -+../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.hpp -+../../../src/hotspot/cpu/zero/register_zero.hpp -+../../../src/hotspot/cpu/zero/assembler_zero.inline.hpp -+../../../src/hotspot/cpu/zero/icache_zero.cpp -+../../../src/hotspot/cpu/zero/vm_version_zero.hpp -+../../../src/hotspot/cpu/zero/codeBuffer_zero.hpp -+../../../src/hotspot/cpu/zero/stack_zero.inline.hpp -+../../../src/hotspot/cpu/zero/globalDefinitions_zero.hpp -+../../../src/hotspot/cpu/zero/cppInterpreter_zero.hpp -+../../../src/hotspot/cpu/zero/fakeStubFrame_zero.hpp -+../../../src/hotspot/cpu/zero/entry_zero.hpp -+../../../src/hotspot/cpu/zero/copy_zero.hpp -+../../../src/hotspot/cpu/zero/methodHandles_zero.cpp -+../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.cpp -+../../../src/hotspot/cpu/zero/register_zero.cpp -+../../../src/hotspot/cpu/zero/interpreterFrame_zero.hpp -+../../../src/hotspot/cpu/zero/icache_zero.hpp -+../../../src/hotspot/cpu/zero/abstractInterpreter_zero.cpp -+../../../src/hotspot/cpu/zero/vmreg_zero.inline.hpp -+../../../src/hotspot/cpu/zero/bytecodeInterpreter_zero.inline.hpp -+../../../src/hotspot/cpu/zero/vm_version_zero.cpp -+../../../src/hotspot/cpu/zero/bytes_zero.hpp -+../../../src/hotspot/cpu/zero/gc/g1/g1BarrierSetAssembler_zero.hpp -+../../../src/hotspot/cpu/zero/gc/shared/barrierSetAssembler_zero.hpp -+../../../src/hotspot/cpu/zero/gc/shared/cardTableBarrierSetAssembler_zero.hpp -+../../../src/hotspot/cpu/zero/gc/shared/modRefBarrierSetAssembler_zero.hpp -+../../../src/hotspot/cpu/zero/jniTypes_zero.hpp -+../../../src/hotspot/cpu/zero/disassembler_zero.hpp -+../../../src/hotspot/cpu/zero/stubRoutines_zero.cpp -+../../../src/hotspot/cpu/zero/frame_zero.cpp -+../../../src/hotspot/cpu/zero/interp_masm_zero.hpp -+../../../src/hotspot/cpu/zero/vmreg_zero.hpp -+../../../src/hotspot/cpu/zero/nativeInst_zero.hpp -+../../../src/hotspot/cpu/zero/vtableStubs_zero.cpp -+../../../src/hotspot/cpu/zero/interpreterRT_zero.cpp -+../../../src/hotspot/cpu/zero/relocInfo_zero.hpp -+../../../src/hotspot/cpu/zero/cppInterpreterGenerator_zero.cpp -+../../../src/hotspot/cpu/zero/jniFastGetField_zero.cpp -+../../../src/hotspot/cpu/zero/entryFrame_zero.hpp -+../../../src/hotspot/cpu/zero/macroAssembler_zero.hpp -+../../../src/hotspot/cpu/zero/depChecker_zero.hpp -+../../../src/hotspot/cpu/zero/stack_zero.cpp -+../../../src/hotspot/cpu/zero/assembler_zero.cpp -+../../../src/hotspot/cpu/zero/vm_version_ext_zero.cpp -+../../../src/hotspot/cpu/zero/registerMap_zero.hpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86.inline.hpp -+../../../src/hotspot/cpu/x86/stubRoutines_x86_64.cpp -+../../../src/hotspot/cpu/x86/assembler_x86.inline.hpp -+../../../src/hotspot/cpu/x86/stubGenerator_x86_64.cpp -+../../../src/hotspot/cpu/x86/stubRoutines_x86.cpp -+../../../src/hotspot/cpu/x86/sharedRuntime_x86.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_log10.cpp -+../../../src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/register_definitions_x86.cpp -+../../../src/hotspot/cpu/x86/c1_Runtime1_x86.cpp -+../../../src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp -+../../../src/hotspot/cpu/x86/templateTable_x86.hpp -+../../../src/hotspot/cpu/x86/nativeInst_x86.cpp -+../../../src/hotspot/cpu/x86/c2_globals_x86.hpp -+../../../src/hotspot/cpu/x86/vm_version_x86.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_cos.cpp -+../../../src/hotspot/cpu/x86/rdtsc_x86.hpp -+../../../src/hotspot/cpu/x86/c2_init_x86.cpp -+../../../src/hotspot/cpu/x86/c1_LIR_x86.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_sin.cpp -+../../../src/hotspot/cpu/x86/vm_version_ext_x86.hpp -+../../../src/hotspot/cpu/x86/vmreg_x86.hpp -+../../../src/hotspot/cpu/x86/depChecker_x86.cpp -+../../../src/hotspot/cpu/x86/c1_Defs_x86.hpp -+../../../src/hotspot/cpu/x86/icache_x86.hpp -+../../../src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/frame_x86.inline.hpp -+../../../src/hotspot/cpu/x86/register_x86.hpp -+../../../src/hotspot/cpu/x86/vmreg_x86.inline.hpp -+../../../src/hotspot/cpu/x86/c1_FpuStackSim_x86.hpp -+../../../src/hotspot/cpu/x86/frame_x86.hpp -+../../../src/hotspot/cpu/x86/vmStructs_x86.hpp -+../../../src/hotspot/cpu/x86/registerMap_x86.hpp -+../../../src/hotspot/cpu/x86/relocInfo_x86.cpp -+../../../src/hotspot/cpu/x86/assembler_x86.hpp -+../../../src/hotspot/cpu/x86/vtableStubs_x86_32.cpp -+../../../src/hotspot/cpu/x86/methodHandles_x86.cpp -+../../../src/hotspot/cpu/x86/interpreterRT_x86_32.cpp -+../../../src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp -+../../../src/hotspot/cpu/x86/c1_FrameMap_x86.hpp -+../../../src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp -+../../../src/hotspot/cpu/x86/c1_LinearScan_x86.hpp -+../../../src/hotspot/cpu/x86/interpreterRT_x86.hpp -+../../../src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp -+../../../src/hotspot/cpu/x86/runtime_x86_32.cpp -+../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp -+../../../src/hotspot/cpu/x86/disassembler_x86.hpp -+../../../src/hotspot/cpu/x86/interp_masm_x86.hpp -+../../../src/hotspot/cpu/x86/vmreg_x86.cpp -+../../../src/hotspot/cpu/x86/stubRoutines_x86_32.cpp -+../../../src/hotspot/cpu/x86/compiledIC_x86.cpp -+../../../src/hotspot/cpu/x86/depChecker_x86.hpp -+../../../src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/icache_x86.cpp -+../../../src/hotspot/cpu/x86/stubGenerator_x86_32.cpp -+../../../src/hotspot/cpu/x86/register_x86.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_log.cpp -+../../../src/hotspot/cpu/x86/c1_FpuStackSim_x86.cpp -+../../../src/hotspot/cpu/x86/frame_x86.cpp -+../../../src/hotspot/cpu/x86/icBuffer_x86.cpp -+../../../src/hotspot/cpu/x86/c1_globals_x86.hpp -+../../../src/hotspot/cpu/x86/relocInfo_x86.hpp -+../../../src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp -+../../../src/hotspot/cpu/x86/registerMap_x86.cpp -+../../../src/hotspot/cpu/x86/assembler_x86.cpp -+../../../src/hotspot/cpu/x86/methodHandles_x86.hpp -+../../../src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp -+../../../src/hotspot/cpu/x86/codeBuffer_x86.hpp -+../../../src/hotspot/cpu/x86/c1_FrameMap_x86.cpp -+../../../src/hotspot/cpu/x86/c1_LinearScan_x86.cpp -+../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp -+../../../src/hotspot/cpu/x86/interp_masm_x86.cpp -+../../../src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp -+../../../src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/crc32c.h -+../../../src/hotspot/cpu/x86/macroAssembler_x86_exp.cpp -+../../../src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_tan.cpp -+../../../src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp -+../../../src/hotspot/cpu/x86/abstractInterpreter_x86.cpp -+../../../src/hotspot/cpu/x86/stubRoutines_x86.hpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_pow.cpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/globals_x86.hpp -+../../../src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp -+../../../src/hotspot/cpu/x86/vtableStubs_x86_64.cpp -+../../../src/hotspot/cpu/x86/interpreterRT_x86_64.cpp -+../../../src/hotspot/cpu/x86/nativeInst_x86.hpp -+../../../src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp -+../../../src/hotspot/cpu/x86/bytes_x86.hpp -+../../../src/hotspot/cpu/x86/templateTable_x86.cpp -+../../../src/hotspot/cpu/x86/jniTypes_x86.hpp -+../../../src/hotspot/cpu/x86/globalDefinitions_x86.hpp -+../../../src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp -+../../../src/hotspot/cpu/x86/rdtsc_x86.cpp -+../../../src/hotspot/cpu/x86/vm_version_x86.hpp -+../../../src/hotspot/cpu/x86/runtime_x86_64.cpp -+../../../src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp -+../../../src/hotspot/cpu/x86/vm_version_ext_x86.cpp -+../../../src/hotspot/cpu/x86/copy_x86.hpp -+../../../src/hotspot/cpu/arm/interpreterRT_arm.hpp -+../../../src/hotspot/cpu/arm/assembler_arm_32.cpp -+../../../src/hotspot/cpu/arm/jniFastGetField_arm.cpp -+../../../src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp -+../../../src/hotspot/cpu/arm/stubGenerator_arm.cpp -+../../../src/hotspot/cpu/arm/nativeInst_arm_64.hpp -+../../../src/hotspot/cpu/arm/disassembler_arm.hpp -+../../../src/hotspot/cpu/arm/interp_masm_arm.hpp -+../../../src/hotspot/cpu/arm/methodHandles_arm.cpp -+../../../src/hotspot/cpu/arm/assembler_arm.hpp -+../../../src/hotspot/cpu/arm/c1_FrameMap_arm.hpp -+../../../src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp -+../../../src/hotspot/cpu/arm/c1_LinearScan_arm.hpp -+../../../src/hotspot/cpu/arm/register_arm.hpp -+../../../src/hotspot/cpu/arm/vmStructs_arm.hpp -+../../../src/hotspot/cpu/arm/c1_FpuStackSim_arm.hpp -+../../../src/hotspot/cpu/arm/frame_arm.hpp -+../../../src/hotspot/cpu/arm/relocInfo_arm.cpp -+../../../src/hotspot/cpu/arm/registerMap_arm.hpp -+../../../src/hotspot/cpu/arm/vmreg_arm.hpp -+../../../src/hotspot/cpu/arm/vm_version_arm_32.cpp -+../../../src/hotspot/cpu/arm/depChecker_arm.cpp -+../../../src/hotspot/cpu/arm/icache_arm.hpp -+../../../src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/c1_Defs_arm.hpp -+../../../src/hotspot/cpu/arm/c2_globals_arm.hpp -+../../../src/hotspot/cpu/arm/assembler_arm_64.hpp -+../../../src/hotspot/cpu/arm/nativeInst_arm_32.cpp -+../../../src/hotspot/cpu/arm/vtableStubs_arm.cpp -+../../../src/hotspot/cpu/arm/c1_LIR_arm.cpp -+../../../src/hotspot/cpu/arm/vm_version_ext_arm.hpp -+../../../src/hotspot/cpu/arm/templateTable_arm.hpp -+../../../src/hotspot/cpu/arm/sharedRuntime_arm.cpp -+../../../src/hotspot/cpu/arm/register_definitions_arm.cpp -+../../../src/hotspot/cpu/arm/macroAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/c1_MacroAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/stubRoutinesCrypto_arm.cpp -+../../../src/hotspot/cpu/arm/c1_Runtime1_arm.cpp -+../../../src/hotspot/cpu/arm/c1_LIRGenerator_arm.hpp -+../../../src/hotspot/cpu/arm/stubRoutines_arm.cpp -+../../../src/hotspot/cpu/arm/runtime_arm.cpp -+../../../src/hotspot/cpu/arm/assembler_arm_64.cpp -+../../../src/hotspot/cpu/arm/vm_version_arm.hpp -+../../../src/hotspot/cpu/arm/nativeInst_arm_32.hpp -+../../../src/hotspot/cpu/arm/copy_arm.hpp -+../../../src/hotspot/cpu/arm/vm_version_ext_arm.cpp -+../../../src/hotspot/cpu/arm/macroAssembler_arm.inline.hpp -+../../../src/hotspot/cpu/arm/jniTypes_arm.hpp -+../../../src/hotspot/cpu/arm/templateTable_arm.cpp -+../../../src/hotspot/cpu/arm/bytes_arm.hpp -+../../../src/hotspot/cpu/arm/nativeInst_arm.hpp -+../../../src/hotspot/cpu/arm/globalDefinitions_arm.hpp -+../../../src/hotspot/cpu/arm/assembler_arm.inline.hpp -+../../../src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/globals_arm.hpp -+../../../src/hotspot/cpu/arm/macroAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/vm_version_arm_64.cpp -+../../../src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp -+../../../src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.cpp -+../../../src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/abstractInterpreter_arm.cpp -+../../../src/hotspot/cpu/arm/stubRoutines_arm.hpp -+../../../src/hotspot/cpu/arm/frame_arm.inline.hpp -+../../../src/hotspot/cpu/arm/interpreterRT_arm.cpp -+../../../src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp -+../../../src/hotspot/cpu/arm/assembler_arm_32.hpp -+../../../src/hotspot/cpu/arm/nativeInst_arm_64.cpp -+../../../src/hotspot/cpu/arm/vmreg_arm.inline.hpp -+../../../src/hotspot/cpu/arm/interp_masm_arm.cpp -+../../../src/hotspot/cpu/arm/jvmciCodeInstaller_arm.cpp -+../../../src/hotspot/cpu/arm/methodHandles_arm.hpp -+../../../src/hotspot/cpu/arm/assembler_arm.cpp -+../../../src/hotspot/cpu/arm/codeBuffer_arm.hpp -+../../../src/hotspot/cpu/arm/c1_FrameMap_arm.cpp -+../../../src/hotspot/cpu/arm/c1_LinearScan_arm.cpp -+../../../src/hotspot/cpu/arm/register_arm.cpp -+../../../src/hotspot/cpu/arm/c1_FpuStackSim_arm.cpp -+../../../src/hotspot/cpu/arm/frame_arm.cpp -+../../../src/hotspot/cpu/arm/c1_globals_arm.hpp -+../../../src/hotspot/cpu/arm/relocInfo_arm.hpp -+../../../src/hotspot/cpu/arm/icBuffer_arm.cpp -+../../../src/hotspot/cpu/arm/vmreg_arm.cpp -+../../../src/hotspot/cpu/arm/compiledIC_arm.cpp -+../../../src/hotspot/cpu/arm/depChecker_arm.hpp -+../../../src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp -+../../../src/hotspot/cpu/arm/icache_arm.cpp -+../../../src/hotspot/cpu/aarch64/copy_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp -+../../../src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/globals_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/bytes_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/icache_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/relocInfo_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/vm_version_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/immediate_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vmreg_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c2_init_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/register_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/assembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/depChecker_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/frame_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp -+../../../src/hotspot/cpu/aarch64/methodHandles_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_FpuStackSim_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/templateTable_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/codeBuffer_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_LinearScan_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vmreg_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/assembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/register_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/depChecker_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/frame_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp -+../../../src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/methodHandles_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/jniTypes_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp -+../../../src/hotspot/cpu/aarch64/c1_FpuStackSim_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/templateTable_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/runtime_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_LinearScan_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/disassembler_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/c1_Defs_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/icache_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64.inline.hpp -+../../../src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp -+../../../src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/registerMap_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/aarch64Test.cpp -+../../../src/hotspot/cpu/aarch64/immediate_aarch64.hpp -+../../../src/hotspot/cpu/aarch64/vm_version_aarch64.cpp -+../../../src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp -+../../../src/hotspot/cpu/sparc/vmStructs_sparc.hpp -+../../../src/hotspot/cpu/sparc/nativeInst_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_LinearScan_sparc.hpp -+../../../src/hotspot/cpu/sparc/copy_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_globals_sparc.hpp -+../../../src/hotspot/cpu/sparc/codeBuffer_sparc.hpp -+../../../src/hotspot/cpu/sparc/stubGenerator_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_FpuStackSim_sparc.cpp -+../../../src/hotspot/cpu/sparc/disassembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp -+../../../src/hotspot/cpu/sparc/c2_init_sparc.cpp -+../../../src/hotspot/cpu/sparc/assembler_sparc.inline.hpp -+../../../src/hotspot/cpu/sparc/vmreg_sparc.hpp -+../../../src/hotspot/cpu/sparc/vm_version_sparc.cpp -+../../../src/hotspot/cpu/sparc/templateTable_sparc.hpp -+../../../src/hotspot/cpu/sparc/macroAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_Defs_sparc.hpp -+../../../src/hotspot/cpu/sparc/interp_masm_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp -+../../../src/hotspot/cpu/sparc/vm_version_ext_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/macroAssembler_sparc.inline.hpp -+../../../src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp -+../../../src/hotspot/cpu/sparc/assembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/frame_sparc.inline.hpp -+../../../src/hotspot/cpu/sparc/frame_sparc.hpp -+../../../src/hotspot/cpu/sparc/stubRoutines_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_LIR_sparc.cpp -+../../../src/hotspot/cpu/sparc/abstractInterpreter_sparc.cpp -+../../../src/hotspot/cpu/sparc/methodHandles_sparc.hpp -+../../../src/hotspot/cpu/sparc/register_definitions_sparc.cpp -+../../../src/hotspot/cpu/sparc/relocInfo_sparc.cpp -+../../../src/hotspot/cpu/sparc/icache_sparc.hpp -+../../../src/hotspot/cpu/sparc/interpreterRT_sparc.cpp -+../../../src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp -+../../../src/hotspot/cpu/sparc/depChecker_sparc.cpp -+../../../src/hotspot/cpu/sparc/runtime_sparc.cpp -+../../../src/hotspot/cpu/sparc/register_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/c2_globals_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_FrameMap_sparc.cpp -+../../../src/hotspot/cpu/sparc/bytes_sparc.hpp -+../../../src/hotspot/cpu/sparc/interp_masm_sparc.hpp -+../../../src/hotspot/cpu/sparc/vm_version_ext_sparc.hpp -+../../../src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/globalDefinitions_sparc.hpp -+../../../src/hotspot/cpu/sparc/stubRoutines_sparc.cpp -+../../../src/hotspot/cpu/sparc/frame_sparc.cpp -+../../../src/hotspot/cpu/sparc/assembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_CodeStubs_sparc.cpp -+../../../src/hotspot/cpu/sparc/methodHandles_sparc.cpp -+../../../src/hotspot/cpu/sparc/relocInfo_sparc.hpp -+../../../src/hotspot/cpu/sparc/icache_sparc.cpp -+../../../src/hotspot/cpu/sparc/interpreterRT_sparc.hpp -+../../../src/hotspot/cpu/sparc/globals_sparc.hpp -+../../../src/hotspot/cpu/sparc/vmreg_sparc.inline.hpp -+../../../src/hotspot/cpu/sparc/depChecker_sparc.hpp -+../../../src/hotspot/cpu/sparc/registerMap_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/register_sparc.hpp -+../../../src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.cpp -+../../../src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp -+../../../src/hotspot/cpu/sparc/c1_FrameMap_sparc.hpp -+../../../src/hotspot/cpu/sparc/compiledIC_sparc.cpp -+../../../src/hotspot/cpu/sparc/icBuffer_sparc.cpp -+../../../src/hotspot/cpu/sparc/nativeInst_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_LinearScan_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp -+../../../src/hotspot/cpu/sparc/c1_FpuStackSim_sparc.hpp -+../../../src/hotspot/cpu/sparc/jniTypes_sparc.hpp -+../../../src/hotspot/cpu/sparc/vtableStubs_sparc.cpp -+../../../src/hotspot/cpu/sparc/javaFrameAnchor_sparc.hpp -+../../../src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp -+../../../src/hotspot/cpu/sparc/vmreg_sparc.cpp -+../../../src/hotspot/cpu/sparc/vm_version_sparc.hpp -+../../../src/hotspot/cpu/sparc/templateTable_sparc.cpp -+../../../src/hotspot/cpu/sparc/macroAssembler_sparc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/os_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/vmStructs_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp -+../../../src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp -+../../../src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp -+../../../src/hotspot/os_cpu/aix_ppc/bytes_aix_ppc.inline.hpp -+../../../src/hotspot/os_cpu/aix_ppc/prefetch_aix_ppc.inline.hpp -+../../../src/hotspot/os_cpu/linux_arm/copy_linux_arm.inline.hpp -+../../../src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp -+../../../src/hotspot/os_cpu/linux_arm/thread_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_arm/vmStructs_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_arm/orderAccess_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_arm/prefetch_linux_arm.inline.hpp -+../../../src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp -+../../../src/hotspot/os_cpu/linux_arm/vm_version_linux_arm_32.cpp -+../../../src/hotspot/os_cpu/linux_arm/bytes_linux_arm.inline.hpp -+../../../src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp -+../../../src/hotspot/os_cpu/linux_arm/os_linux_arm.hpp -+../../../src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp -+../../../src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp -+../../../src/hotspot/os_cpu/linux_zero/assembler_linux_zero.cpp -+../../../src/hotspot/os_cpu/linux_zero/vm_version_linux_zero.cpp -+../../../src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_zero/orderAccess_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_zero/prefetch_linux_zero.inline.hpp -+../../../src/hotspot/os_cpu/linux_zero/vmStructs_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_zero/bytes_linux_zero.inline.hpp -+../../../src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp -+../../../src/hotspot/os_cpu/linux_x86/orderAccess_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/thread_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/prefetch_linux_x86.inline.hpp -+../../../src/hotspot/os_cpu/linux_x86/vmStructs_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/bytes_linux_x86.inline.hpp -+../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/assembler_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.inline.hpp -+../../../src/hotspot/os_cpu/linux_x86/os_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/copy_linux_x86.inline.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zVirtualMemory_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zNUMA_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zAddress_linux_x86.inline.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingPath_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zLargePages_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/gc/z/zBackingFile_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_x86/vm_version_linux_x86.cpp -+../../../src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp -+../../../src/hotspot/os_cpu/linux_aarch64/bytes_linux_aarch64.inline.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/assembler_linux_aarch64.cpp -+../../../src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp -+../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.inline.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/vmStructs_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/prefetch_linux_aarch64.inline.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/orderAccess_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp -+../../../src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp -+../../../src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.inline.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/thread_solaris_sparc.cpp -+../../../src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/vm_version_solaris_sparc.cpp -+../../../src/hotspot/os_cpu/solaris_sparc/count_trailing_zeros_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/thread_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp -+../../../src/hotspot/os_cpu/solaris_sparc/globals_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/orderAccess_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/prefetch_solaris_sparc.inline.hpp -+../../../src/hotspot/os_cpu/solaris_sparc/vmStructs_solaris_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/globals_linux_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp -+../../../src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/thread_linux_sparc.cpp -+../../../src/hotspot/os_cpu/linux_sparc/prefetch_linux_sparc.inline.hpp -+../../../src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp -+../../../src/hotspot/os_cpu/linux_sparc/orderAccess_linux_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/thread_linux_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/os_linux_sparc.hpp -+../../../src/hotspot/os_cpu/linux_sparc/vmStructs_linux_sparc.hpp -+../../../src/hotspot/os_cpu/bsd_zero/bytes_bsd_zero.inline.hpp -+../../../src/hotspot/os_cpu/bsd_zero/prefetch_bsd_zero.inline.hpp -+../../../src/hotspot/os_cpu/bsd_zero/vm_version_bsd_zero.cpp -+../../../src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp -+../../../src/hotspot/os_cpu/bsd_zero/thread_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_zero/os_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_zero/thread_bsd_zero.cpp -+../../../src/hotspot/os_cpu/bsd_zero/assembler_bsd_zero.cpp -+../../../src/hotspot/os_cpu/bsd_zero/vmStructs_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_zero/orderAccess_bsd_zero.hpp -+../../../src/hotspot/os_cpu/bsd_x86/assembler_bsd_x86.cpp -+../../../src/hotspot/os_cpu/bsd_x86/orderAccess_bsd_x86.hpp -+../../../src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.inline.hpp -+../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp -+../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.inline.hpp -+../../../src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp -+../../../src/hotspot/os_cpu/bsd_x86/vm_version_bsd_x86.cpp -+../../../src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp -+../../../src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp -+../../../src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.hpp -+../../../src/hotspot/os_cpu/bsd_x86/prefetch_bsd_x86.inline.hpp -+../../../src/hotspot/os_cpu/bsd_x86/bytes_bsd_x86.inline.hpp -+../../../src/hotspot/os_cpu/bsd_x86/vmStructs_bsd_x86.hpp -+../../../src/hotspot/os_cpu/bsd_x86/os_bsd_x86.hpp -+../../../src/hotspot/os_cpu/linux_ppc/os_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_ppc/prefetch_linux_ppc.inline.hpp -+../../../src/hotspot/os_cpu/linux_ppc/bytes_linux_ppc.inline.hpp -+../../../src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp -+../../../src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_ppc/vmStructs_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp -+../../../src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp -+../../../src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp -+../../../src/hotspot/os_cpu/linux_s390/prefetch_linux_s390.inline.hpp -+../../../src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp -+../../../src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp -+../../../src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp -+../../../src/hotspot/os_cpu/linux_s390/bytes_linux_s390.inline.hpp -+../../../src/hotspot/os_cpu/linux_s390/thread_linux_s390.hpp -+../../../src/hotspot/os_cpu/linux_s390/orderAccess_linux_s390.hpp -+../../../src/hotspot/os_cpu/linux_s390/vmStructs_linux_s390.hpp -+../../../src/hotspot/os_cpu/linux_s390/os_linux_s390.hpp -+../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp -+../../../src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/bytes_windows_x86.inline.hpp -+../../../src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/copy_windows_x86.inline.hpp -+../../../src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp -+../../../src/hotspot/os_cpu/windows_x86/prefetch_windows_x86.inline.hpp -+../../../src/hotspot/os_cpu/windows_x86/unwind_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/vm_version_windows_x86.cpp -+../../../src/hotspot/os_cpu/windows_x86/thread_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/orderAccess_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/assembler_windows_x86.cpp -+../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp -+../../../src/hotspot/os_cpu/windows_x86/vmStructs_windows_x86.hpp -+../../../src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp -+../../../src/hotspot/os_cpu/solaris_x86/globals_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.cpp -+../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.inline.hpp -+../../../src/hotspot/os_cpu/solaris_x86/vm_version_solaris_x86.cpp -+../../../src/hotspot/os_cpu/solaris_x86/bytes_solaris_x86.inline.hpp -+../../../src/hotspot/os_cpu/solaris_x86/assembler_solaris_x86.cpp -+../../../src/hotspot/os_cpu/solaris_x86/orderAccess_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/thread_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/os_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/count_trailing_zeros_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/prefetch_solaris_x86.inline.hpp -+../../../src/hotspot/os_cpu/solaris_x86/vmStructs_solaris_x86.hpp -+../../../src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.inline.hpp -+../../../src/hotspot/os/posix/jvm_posix.cpp -+../../../src/hotspot/os/posix/include/jvm_md.h -+../../../src/hotspot/os/posix/os_posix.hpp -+../../../src/hotspot/os/posix/semaphore_posix.cpp -+../../../src/hotspot/os/posix/threadLocalStorage_posix.cpp -+../../../src/hotspot/os/posix/vmError_posix.cpp -+../../../src/hotspot/os/posix/os_posix.cpp -+../../../src/hotspot/os/posix/semaphore_posix.hpp -+../../../src/hotspot/os/bsd/semaphore_bsd.cpp -+../../../src/hotspot/os/bsd/osThread_bsd.hpp -+../../../src/hotspot/os/bsd/os_bsd.inline.hpp -+../../../src/hotspot/os/bsd/globals_bsd.hpp -+../../../src/hotspot/os/bsd/os_share_bsd.hpp -+../../../src/hotspot/os/bsd/os_bsd.hpp -+../../../src/hotspot/os/bsd/perfMemory_bsd.cpp -+../../../src/hotspot/os/bsd/decoder_machO.cpp -+../../../src/hotspot/os/bsd/c1_globals_bsd.hpp -+../../../src/hotspot/os/bsd/threadCritical_bsd.cpp -+../../../src/hotspot/os/bsd/os_bsd.cpp -+../../../src/hotspot/os/bsd/attachListener_bsd.cpp -+../../../src/hotspot/os/bsd/decoder_machO.hpp -+../../../src/hotspot/os/bsd/vmStructs_bsd.hpp -+../../../src/hotspot/os/bsd/os_perf_bsd.cpp -+../../../src/hotspot/os/bsd/semaphore_bsd.hpp -+../../../src/hotspot/os/bsd/osThread_bsd.cpp -+../../../src/hotspot/os/bsd/c2_globals_bsd.hpp -+../../../src/hotspot/os/linux/osContainer_linux.cpp -+../../../src/hotspot/os/linux/decoder_linux.cpp -+../../../src/hotspot/os/linux/perfMemory_linux.cpp -+../../../src/hotspot/os/linux/osThread_linux.cpp -+../../../src/hotspot/os/linux/os_linux.cpp -+../../../src/hotspot/os/linux/globals_linux.hpp -+../../../src/hotspot/os/linux/c2_globals_linux.hpp -+../../../src/hotspot/os/linux/os_linux.hpp -+../../../src/hotspot/os/linux/os_share_linux.hpp -+../../../src/hotspot/os/linux/threadCritical_linux.cpp -+../../../src/hotspot/os/linux/os_linux.inline.hpp -+../../../src/hotspot/os/linux/osContainer_linux.hpp -+../../../src/hotspot/os/linux/attachListener_linux.cpp -+../../../src/hotspot/os/linux/c1_globals_linux.hpp -+../../../src/hotspot/os/linux/os_perf_linux.cpp -+../../../src/hotspot/os/linux/vmStructs_linux.hpp -+../../../src/hotspot/os/linux/osThread_linux.hpp -+../../../src/hotspot/os/windows/globals_windows.hpp -+../../../src/hotspot/os/windows/semaphore_windows.cpp -+../../../src/hotspot/os/windows/decoder_windows.cpp -+../../../src/hotspot/os/windows/os_perf_windows.cpp -+../../../src/hotspot/os/windows/iphlp_interface.cpp -+../../../src/hotspot/os/windows/threadCritical_windows.cpp -+../../../src/hotspot/os/windows/threadLocalStorage_windows.cpp -+../../../src/hotspot/os/windows/include/jvm_md.h -+../../../src/hotspot/os/windows/pdh_interface.cpp -+../../../src/hotspot/os/windows/symbolengine.hpp -+../../../src/hotspot/os/windows/windbghelp.hpp -+../../../src/hotspot/os/windows/osThread_windows.hpp -+../../../src/hotspot/os/windows/os_windows.hpp -+../../../src/hotspot/os/windows/vmStructs_windows.hpp -+../../../src/hotspot/os/windows/perfMemory_windows.cpp -+../../../src/hotspot/os/windows/pdh_interface.hpp -+../../../src/hotspot/os/windows/symbolengine.cpp -+../../../src/hotspot/os/windows/windbghelp.cpp -+../../../src/hotspot/os/windows/os_windows.cpp -+../../../src/hotspot/os/windows/osThread_windows.cpp -+../../../src/hotspot/os/windows/semaphore_windows.hpp -+../../../src/hotspot/os/windows/jvm_windows.cpp -+../../../src/hotspot/os/windows/c1_globals_windows.hpp -+../../../src/hotspot/os/windows/os_windows.inline.hpp -+../../../src/hotspot/os/windows/sharedRuntimeRem.cpp -+../../../src/hotspot/os/windows/c2_globals_windows.hpp -+../../../src/hotspot/os/windows/iphlp_interface.hpp -+../../../src/hotspot/os/windows/attachListener_windows.cpp -+../../../src/hotspot/os/windows/vmError_windows.cpp -+../../../src/hotspot/os/windows/os_share_windows.hpp -+../../../src/hotspot/os/solaris/globals_solaris.hpp -+../../../src/hotspot/os/solaris/decoder_solaris.cpp -+../../../src/hotspot/os/solaris/os_perf_solaris.cpp -+../../../src/hotspot/os/solaris/os_solaris.inline.hpp -+../../../src/hotspot/os/solaris/threadCritical_solaris.cpp -+../../../src/hotspot/os/solaris/osThread_solaris.hpp -+../../../src/hotspot/os/solaris/os_solaris.hpp -+../../../src/hotspot/os/solaris/perfMemory_solaris.cpp -+../../../src/hotspot/os/solaris/vmStructs_solaris.hpp -+../../../src/hotspot/os/solaris/os_solaris.cpp -+../../../src/hotspot/os/solaris/osThread_solaris.cpp -+../../../src/hotspot/os/solaris/c1_globals_solaris.hpp -+../../../src/hotspot/os/solaris/c2_globals_solaris.hpp -+../../../src/hotspot/os/solaris/os_share_solaris.hpp -+../../../src/hotspot/os/solaris/attachListener_solaris.cpp -+../../../src/hotspot/os/aix/loadlib_aix.hpp -+../../../src/hotspot/os/aix/threadCritical_aix.cpp -+../../../src/hotspot/os/aix/c1_globals_aix.hpp -+../../../src/hotspot/os/aix/libperfstat_aix.hpp -+../../../src/hotspot/os/aix/perfMemory_aix.cpp -+../../../src/hotspot/os/aix/os_aix.hpp -+../../../src/hotspot/os/aix/porting_aix.cpp -+../../../src/hotspot/os/aix/os_share_aix.hpp -+../../../src/hotspot/os/aix/safepointMechanism_aix.cpp -+../../../src/hotspot/os/aix/libodm_aix.cpp -+../../../src/hotspot/os/aix/libo4.cpp -+../../../src/hotspot/os/aix/misc_aix.cpp -+../../../src/hotspot/os/aix/globals_aix.hpp -+../../../src/hotspot/os/aix/osThread_aix.hpp -+../../../src/hotspot/os/aix/c2_globals_aix.hpp -+../../../src/hotspot/os/aix/libodm_aix.hpp -+../../../src/hotspot/os/aix/libo4.hpp -+../../../src/hotspot/os/aix/misc_aix.hpp -+../../../src/hotspot/os/aix/decoder_aix.hpp -+../../../src/hotspot/os/aix/osThread_aix.cpp -+../../../src/hotspot/os/aix/os_aix.inline.hpp -+../../../src/hotspot/os/aix/os_perf_aix.cpp -+../../../src/hotspot/os/aix/loadlib_aix.cpp -+../../../src/hotspot/os/aix/vmStructs_aix.hpp -+../../../src/hotspot/os/aix/attachListener_aix.cpp -+../../../src/hotspot/os/aix/libperfstat_aix.cpp -+../../../src/hotspot/os/aix/os_aix.cpp -+../../../src/hotspot/os/aix/porting_aix.hpp -+../../../src/hotspot/share/interpreter/bytecodeTracer.cpp -+../../../src/hotspot/share/interpreter/bytecodeHistogram.cpp -+../../../src/hotspot/share/interpreter/bytecodeInterpreter.cpp -+../../../src/hotspot/share/interpreter/cppInterpreterGenerator.hpp -+../../../src/hotspot/share/interpreter/rewriter.hpp -+../../../src/hotspot/share/interpreter/bytecodes.hpp -+../../../src/hotspot/share/interpreter/bytecode.cpp -+../../../src/hotspot/share/interpreter/templateInterpreter.hpp -+../../../src/hotspot/share/interpreter/bytecodeInterpreterProfiling.hpp -+../../../src/hotspot/share/interpreter/interpreter.cpp -+../../../src/hotspot/share/interpreter/oopMapCache.cpp -+../../../src/hotspot/share/interpreter/linkResolver.cpp -+../../../src/hotspot/share/interpreter/templateTable.hpp -+../../../src/hotspot/share/interpreter/abstractInterpreter.hpp -+../../../src/hotspot/share/interpreter/invocationCounter.cpp -+../../../src/hotspot/share/interpreter/cppInterpreter.cpp -+../../../src/hotspot/share/interpreter/interp_masm.hpp -+../../../src/hotspot/share/interpreter/bytecodeStream.cpp -+../../../src/hotspot/share/interpreter/templateInterpreterGenerator.hpp -+../../../src/hotspot/share/interpreter/interpreterRuntime.hpp -+../../../src/hotspot/share/interpreter/linkResolver.hpp -+../../../src/hotspot/share/interpreter/templateTable.cpp -+../../../src/hotspot/share/interpreter/abstractInterpreter.cpp -+../../../src/hotspot/share/interpreter/bytecodeInterpreter.inline.hpp -+../../../src/hotspot/share/interpreter/invocationCounter.hpp -+../../../src/hotspot/share/interpreter/cppInterpreter.hpp -+../../../src/hotspot/share/interpreter/bytecodeStream.hpp -+../../../src/hotspot/share/interpreter/templateInterpreterGenerator.cpp -+../../../src/hotspot/share/interpreter/interpreterRuntime.cpp -+../../../src/hotspot/share/interpreter/bytecodeHistogram.hpp -+../../../src/hotspot/share/interpreter/bytecodeTracer.hpp -+../../../src/hotspot/share/interpreter/bytecodeInterpreter.hpp -+../../../src/hotspot/share/interpreter/cppInterpreterGenerator.cpp -+../../../src/hotspot/share/interpreter/bytecodes.cpp -+../../../src/hotspot/share/interpreter/rewriter.cpp -+../../../src/hotspot/share/interpreter/bytecode.hpp -+../../../src/hotspot/share/interpreter/templateInterpreter.cpp -+../../../src/hotspot/share/interpreter/interpreter.hpp -+../../../src/hotspot/share/interpreter/oopMapCache.hpp -+../../../src/hotspot/share/interpreter/bytecode.inline.hpp -+../../../src/hotspot/share/metaprogramming/isIntegral.hpp -+../../../src/hotspot/share/metaprogramming/isPointer.hpp -+../../../src/hotspot/share/metaprogramming/isFloatingPoint.hpp -+../../../src/hotspot/share/metaprogramming/isVolatile.hpp -+../../../src/hotspot/share/metaprogramming/isSame.hpp -+../../../src/hotspot/share/metaprogramming/removePointer.hpp -+../../../src/hotspot/share/metaprogramming/removeReference.hpp -+../../../src/hotspot/share/metaprogramming/removeCV.hpp -+../../../src/hotspot/share/metaprogramming/decay.hpp -+../../../src/hotspot/share/metaprogramming/isSigned.hpp -+../../../src/hotspot/share/metaprogramming/enableIf.hpp -+../../../src/hotspot/share/metaprogramming/conditional.hpp -+../../../src/hotspot/share/metaprogramming/integralConstant.hpp -+../../../src/hotspot/share/metaprogramming/isConst.hpp -+../../../src/hotspot/share/metaprogramming/primitiveConversions.hpp -+../../../src/hotspot/share/metaprogramming/isRegisteredEnum.hpp -+../../../src/hotspot/share/asm/codeBuffer.hpp -+../../../src/hotspot/share/asm/macroAssembler.hpp -+../../../src/hotspot/share/asm/register.hpp -+../../../src/hotspot/share/asm/assembler.cpp -+../../../src/hotspot/share/asm/register.cpp -+../../../src/hotspot/share/asm/assembler.hpp -+../../../src/hotspot/share/asm/codeBuffer.cpp -+../../../src/hotspot/share/asm/assembler.inline.hpp -+../../../src/hotspot/share/asm/macroAssembler.inline.hpp -+../../../src/hotspot/share/memory/resourceArea.hpp -+../../../src/hotspot/share/memory/freeList.inline.hpp -+../../../src/hotspot/share/memory/oopFactory.cpp -+../../../src/hotspot/share/memory/metaspaceShared.cpp -+../../../src/hotspot/share/memory/metaspaceTracer.cpp -+../../../src/hotspot/share/memory/metaspace.cpp -+../../../src/hotspot/share/memory/metaspaceClosure.cpp -+../../../src/hotspot/share/memory/iterator.cpp -+../../../src/hotspot/share/memory/allocation.inline.hpp -+../../../src/hotspot/share/memory/metaspaceGCThresholdUpdater.hpp -+../../../src/hotspot/share/memory/memRegion.hpp -+../../../src/hotspot/share/memory/allocation.cpp -+../../../src/hotspot/share/memory/guardedMemory.hpp -+../../../src/hotspot/share/memory/binaryTreeDictionary.hpp -+../../../src/hotspot/share/memory/heapInspection.cpp -+../../../src/hotspot/share/memory/heap.cpp -+../../../src/hotspot/share/memory/metaspaceCounters.cpp -+../../../src/hotspot/share/memory/filemap.hpp -+../../../src/hotspot/share/memory/universe.hpp -+../../../src/hotspot/share/memory/arena.cpp -+../../../src/hotspot/share/memory/virtualspace.cpp -+../../../src/hotspot/share/memory/operator_new.cpp -+../../../src/hotspot/share/memory/iterator.inline.hpp -+../../../src/hotspot/share/memory/allocation.hpp -+../../../src/hotspot/share/memory/guardedMemory.cpp -+../../../src/hotspot/share/memory/padded.inline.hpp -+../../../src/hotspot/share/memory/heapInspection.hpp -+../../../src/hotspot/share/memory/heap.hpp -+../../../src/hotspot/share/memory/filemap.cpp -+../../../src/hotspot/share/memory/metaspaceCounters.hpp -+../../../src/hotspot/share/memory/arena.hpp -+../../../src/hotspot/share/memory/universe.cpp -+../../../src/hotspot/share/memory/virtualspace.hpp -+../../../src/hotspot/share/memory/resourceArea.cpp -+../../../src/hotspot/share/memory/metaspaceShared.hpp -+../../../src/hotspot/share/memory/oopFactory.hpp -+../../../src/hotspot/share/memory/metaspaceTracer.hpp -+../../../src/hotspot/share/memory/metaspace/virtualSpaceList.hpp -+../../../src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp -+../../../src/hotspot/share/memory/metaspace/metaspaceCommon.hpp -+../../../src/hotspot/share/memory/metaspace/chunkManager.hpp -+../../../src/hotspot/share/memory/metaspace/occupancyMap.cpp -+../../../src/hotspot/share/memory/metaspace/smallBlocks.hpp -+../../../src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp -+../../../src/hotspot/share/memory/metaspace/spaceManager.cpp -+../../../src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp -+../../../src/hotspot/share/memory/metaspace/metaDebug.cpp -+../../../src/hotspot/share/memory/metaspace/metachunk.hpp -+../../../src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.hpp -+../../../src/hotspot/share/memory/metaspace/blockFreelist.hpp -+../../../src/hotspot/share/memory/metaspace/metaspaceStatistics.hpp -+../../../src/hotspot/share/memory/metaspace/metablock.hpp -+../../../src/hotspot/share/memory/metaspace/metabase.hpp -+../../../src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp -+../../../src/hotspot/share/memory/metaspace/metaDebug.hpp -+../../../src/hotspot/share/memory/metaspace/metachunk.cpp -+../../../src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp -+../../../src/hotspot/share/memory/metaspace/blockFreelist.cpp -+../../../src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp -+../../../src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp -+../../../src/hotspot/share/memory/metaspace/virtualSpaceList.cpp -+../../../src/hotspot/share/memory/metaspace/metaspaceCommon.cpp -+../../../src/hotspot/share/memory/metaspace/occupancyMap.hpp -+../../../src/hotspot/share/memory/metaspace/chunkManager.cpp -+../../../src/hotspot/share/memory/metaspace/smallBlocks.cpp -+../../../src/hotspot/share/memory/metaspace/virtualSpaceNode.hpp -+../../../src/hotspot/share/memory/metaspace/spaceManager.hpp -+../../../src/hotspot/share/memory/metaspace.hpp -+../../../src/hotspot/share/memory/referenceType.hpp -+../../../src/hotspot/share/memory/metadataFactory.hpp -+../../../src/hotspot/share/memory/freeList.hpp -+../../../src/hotspot/share/memory/metaspaceClosure.hpp -+../../../src/hotspot/share/memory/resourceArea.inline.hpp -+../../../src/hotspot/share/memory/padded.hpp -+../../../src/hotspot/share/memory/metaspaceChunkFreeListSummary.hpp -+../../../src/hotspot/share/memory/iterator.hpp -+../../../src/hotspot/share/memory/binaryTreeDictionary.inline.hpp -+../../../src/hotspot/share/memory/memRegion.cpp -+../../../src/hotspot/share/jfr/dcmd/jfrDcmds.cpp -+../../../src/hotspot/share/jfr/dcmd/jfrDcmds.hpp -+../../../src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp -+../../../src/hotspot/share/jfr/periodic/jfrOSInterface.cpp -+../../../src/hotspot/share/jfr/periodic/jfrModuleEvent.hpp -+../../../src/hotspot/share/jfr/periodic/jfrPeriodic.cpp -+../../../src/hotspot/share/jfr/periodic/jfrNetworkUtilization.cpp -+../../../src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp -+../../../src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp -+../../../src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp -+../../../src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.hpp -+../../../src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.cpp -+../../../src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp -+../../../src/hotspot/share/jfr/periodic/jfrNetworkUtilization.hpp -+../../../src/hotspot/share/jfr/periodic/jfrThreadDumpEvent.hpp -+../../../src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.hpp -+../../../src/hotspot/share/jfr/periodic/jfrOSInterface.hpp -+../../../src/hotspot/share/jfr/jfrEvents.hpp -+../../../src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp -+../../../src/hotspot/share/jfr/writers/jfrEventWriterHost.inline.hpp -+../../../src/hotspot/share/jfr/writers/jfrNativeEventWriter.hpp -+../../../src/hotspot/share/jfr/writers/jfrEncoding.hpp -+../../../src/hotspot/share/jfr/writers/jfrStorageHost.hpp -+../../../src/hotspot/share/jfr/writers/jfrStorageAdapter.hpp -+../../../src/hotspot/share/jfr/writers/jfrEncoders.hpp -+../../../src/hotspot/share/jfr/writers/jfrPosition.hpp -+../../../src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp -+../../../src/hotspot/share/jfr/writers/jfrPosition.inline.hpp -+../../../src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp -+../../../src/hotspot/share/jfr/writers/jfrStorageHost.inline.hpp -+../../../src/hotspot/share/jfr/writers/jfrStreamWriterHost.hpp -+../../../src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp -+../../../src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp -+../../../src/hotspot/share/jfr/writers/jfrBigEndianWriter.hpp -+../../../src/hotspot/share/jfr/writers/jfrWriterHost.hpp -+../../../src/hotspot/share/jfr/writers/jfrEventWriterHost.hpp -+../../../src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp -+../../../src/hotspot/share/jfr/jfr.hpp -+../../../src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.hpp -+../../../src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.hpp -+../../../src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp -+../../../src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -+../../../src/hotspot/share/jfr/utilities/jfrAllocation.cpp -+../../../src/hotspot/share/jfr/utilities/jfrTypes.hpp -+../../../src/hotspot/share/jfr/utilities/jfrTimeConverter.cpp -+../../../src/hotspot/share/jfr/utilities/jfrTryLock.hpp -+../../../src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp -+../../../src/hotspot/share/jfr/utilities/jfrResourceManager.hpp -+../../../src/hotspot/share/jfr/utilities/jfrTime.hpp -+../../../src/hotspot/share/jfr/utilities/jfrJavaLog.cpp -+../../../src/hotspot/share/jfr/utilities/jfrRefCountPointer.hpp -+../../../src/hotspot/share/jfr/utilities/jfrIterator.hpp -+../../../src/hotspot/share/jfr/utilities/jfrTime.cpp -+../../../src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp -+../../../src/hotspot/share/jfr/utilities/jfrJavaLog.hpp -+../../../src/hotspot/share/jfr/utilities/jfrHashtable.hpp -+../../../src/hotspot/share/jfr/utilities/jfrAllocation.hpp -+../../../src/hotspot/share/jfr/utilities/jfrLogTagSets.hpp -+../../../src/hotspot/share/jfr/utilities/jfrTimeConverter.hpp -+../../../src/hotspot/share/jfr/utilities/jfrBigEndian.hpp -+../../../src/hotspot/share/jfr/jfr.cpp -+../../../src/hotspot/share/jfr/support/jfrIntrinsics.hpp -+../../../src/hotspot/share/jfr/support/jfrAllocationTracer.cpp -+../../../src/hotspot/share/jfr/support/jfrKlassExtension.hpp -+../../../src/hotspot/share/jfr/support/jfrFlush.hpp -+../../../src/hotspot/share/jfr/support/jfrStackTraceMark.hpp -+../../../src/hotspot/share/jfr/support/jfrThreadLocal.cpp -+../../../src/hotspot/share/jfr/support/jfrEventClass.cpp -+../../../src/hotspot/share/jfr/support/jfrFlush.cpp -+../../../src/hotspot/share/jfr/support/jfrStackTraceMark.cpp -+../../../src/hotspot/share/jfr/support/jfrThreadLocal.hpp -+../../../src/hotspot/share/jfr/support/jfrEventClass.hpp -+../../../src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp -+../../../src/hotspot/share/jfr/support/jfrThreadExtension.hpp -+../../../src/hotspot/share/jfr/support/jfrAllocationTracer.hpp -+../../../src/hotspot/share/jfr/support/jfrThreadId.hpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolBuffer.cpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolWriter.hpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolWriter.cpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp -+../../../src/hotspot/share/jfr/recorder/stringpool/jfrStringPoolBuffer.hpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.hpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrRepository.hpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.hpp -+../../../src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointBlob.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadState.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrMetadataEvent.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointBlob.cpp -+../../../src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp -+../../../src/hotspot/share/jfr/recorder/jfrRecorder.hpp -+../../../src/hotspot/share/jfr/recorder/jfrEventSetting.cpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorageControl.cpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorage.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrStorageControl.hpp -+../../../src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp -+../../../src/hotspot/share/jfr/recorder/jfrRecorder.cpp -+../../../src/hotspot/share/jfr/recorder/jfrEventSetting.hpp -+../../../src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp -+../../../src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp -+../../../src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp -+../../../src/hotspot/share/jfr/recorder/service/jfrMemorySizer.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrEvent.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp -+../../../src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp -+../../../src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp -+../../../src/hotspot/share/jfr/recorder/service/jfrMemorySizer.hpp -+../../../src/hotspot/share/jfr/recorder/service/jfrEvent.hpp -+../../../src/hotspot/share/jfr/recorder/jfrEventSetting.inline.hpp -+../../../src/hotspot/share/jfr/leakprofiler/stopOperation.hpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.hpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.hpp -+../../../src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp -+../../../src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.hpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/sampleList.cpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/samplePriorityQueue.cpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/samplePriorityQueue.hpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp -+../../../src/hotspot/share/jfr/leakprofiler/sampling/sampleList.hpp -+../../../src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/saveRestore.hpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.cpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/granularTimer.hpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/saveRestore.cpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp -+../../../src/hotspot/share/jfr/leakprofiler/utilities/unifiedOop.hpp -+../../../src/hotspot/share/jfr/leakprofiler/startOperation.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edge.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/bitset.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/objectSampleMarker.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeQueue.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeQueue.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edge.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp -+../../../src/hotspot/share/jfr/leakprofiler/chains/bitset.cpp -+../../../src/hotspot/share/jfr/jni/jfrJniMethod.hpp -+../../../src/hotspot/share/jfr/jni/jfrUpcalls.cpp -+../../../src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp -+../../../src/hotspot/share/jfr/jni/jfrJavaSupport.cpp -+../../../src/hotspot/share/jfr/jni/jfrGetAllEventClasses.cpp -+../../../src/hotspot/share/jfr/jni/jfrJavaCall.hpp -+../../../src/hotspot/share/jfr/jni/jfrJavaSupport.hpp -+../../../src/hotspot/share/jfr/jni/jfrGetAllEventClasses.hpp -+../../../src/hotspot/share/jfr/jni/jfrJavaCall.cpp -+../../../src/hotspot/share/jfr/jni/jfrJniMethod.cpp -+../../../src/hotspot/share/jfr/jni/jfrUpcalls.hpp -+../../../src/hotspot/share/jfr/jni/jfrJniMethodRegistration.hpp -+../../../src/hotspot/share/jfr/metadata/jfrSerializer.hpp -+../../../src/hotspot/share/ci/ciConstantPoolCache.hpp -+../../../src/hotspot/share/ci/ciClassList.hpp -+../../../src/hotspot/share/ci/ciTypeArray.hpp -+../../../src/hotspot/share/ci/ciCallSite.hpp -+../../../src/hotspot/share/ci/ciType.cpp -+../../../src/hotspot/share/ci/ciTypeArrayKlass.cpp -+../../../src/hotspot/share/ci/ciMethodBlocks.hpp -+../../../src/hotspot/share/ci/ciArray.hpp -+../../../src/hotspot/share/ci/ciTypeFlow.hpp -+../../../src/hotspot/share/ci/bcEscapeAnalyzer.cpp -+../../../src/hotspot/share/ci/ciNullObject.hpp -+../../../src/hotspot/share/ci/ciField.hpp -+../../../src/hotspot/share/ci/ciConstant.cpp -+../../../src/hotspot/share/ci/ciArrayKlass.hpp -+../../../src/hotspot/share/ci/ciMethodType.hpp -+../../../src/hotspot/share/ci/ciReplay.hpp -+../../../src/hotspot/share/ci/ciInstanceKlass.hpp -+../../../src/hotspot/share/ci/ciSignature.hpp -+../../../src/hotspot/share/ci/ciInstance.cpp -+../../../src/hotspot/share/ci/ciSymbol.cpp -+../../../src/hotspot/share/ci/ciObjArray.cpp -+../../../src/hotspot/share/ci/ciMetadata.cpp -+../../../src/hotspot/share/ci/ciMemberName.cpp -+../../../src/hotspot/share/ci/ciObjArrayKlass.cpp -+../../../src/hotspot/share/ci/ciMethod.hpp -+../../../src/hotspot/share/ci/ciMethodHandle.hpp -+../../../src/hotspot/share/ci/ciFlags.cpp -+../../../src/hotspot/share/ci/ciObjectFactory.hpp -+../../../src/hotspot/share/ci/ciUtilities.hpp -+../../../src/hotspot/share/ci/ciEnv.hpp -+../../../src/hotspot/share/ci/ciStreams.cpp -+../../../src/hotspot/share/ci/ciKlass.hpp -+../../../src/hotspot/share/ci/ciMethodData.cpp -+../../../src/hotspot/share/ci/ciObject.cpp -+../../../src/hotspot/share/ci/ciExceptionHandler.cpp -+../../../src/hotspot/share/ci/ciBaseObject.cpp -+../../../src/hotspot/share/ci/ciObjArray.hpp -+../../../src/hotspot/share/ci/ciObjArrayKlass.hpp -+../../../src/hotspot/share/ci/ciMemberName.hpp -+../../../src/hotspot/share/ci/ciMetadata.hpp -+../../../src/hotspot/share/ci/ciUtilities.inline.hpp -+../../../src/hotspot/share/ci/ciMethodHandle.cpp -+../../../src/hotspot/share/ci/ciMethod.cpp -+../../../src/hotspot/share/ci/ciFlags.hpp -+../../../src/hotspot/share/ci/ciUtilities.cpp -+../../../src/hotspot/share/ci/ciObjectFactory.cpp -+../../../src/hotspot/share/ci/ciStreams.hpp -+../../../src/hotspot/share/ci/ciEnv.cpp -+../../../src/hotspot/share/ci/ciKlass.cpp -+../../../src/hotspot/share/ci/ciObject.hpp -+../../../src/hotspot/share/ci/ciMethodData.hpp -+../../../src/hotspot/share/ci/ciBaseObject.hpp -+../../../src/hotspot/share/ci/ciExceptionHandler.hpp -+../../../src/hotspot/share/ci/ciConstantPoolCache.cpp -+../../../src/hotspot/share/ci/ciTypeArray.cpp -+../../../src/hotspot/share/ci/ciTypeArrayKlass.hpp -+../../../src/hotspot/share/ci/ciType.hpp -+../../../src/hotspot/share/ci/ciCallSite.cpp -+../../../src/hotspot/share/ci/ciMethodBlocks.cpp -+../../../src/hotspot/share/ci/ciArray.cpp -+../../../src/hotspot/share/ci/compilerInterface.hpp -+../../../src/hotspot/share/ci/ciTypeFlow.cpp -+../../../src/hotspot/share/ci/bcEscapeAnalyzer.hpp -+../../../src/hotspot/share/ci/ciCallProfile.hpp -+../../../src/hotspot/share/ci/ciNullObject.cpp -+../../../src/hotspot/share/ci/ciField.cpp -+../../../src/hotspot/share/ci/ciConstant.hpp -+../../../src/hotspot/share/ci/ciArrayKlass.cpp -+../../../src/hotspot/share/ci/ciReplay.cpp -+../../../src/hotspot/share/ci/ciInstanceKlass.cpp -+../../../src/hotspot/share/ci/ciMethodType.cpp -+../../../src/hotspot/share/ci/ciSymbol.hpp -+../../../src/hotspot/share/ci/ciSignature.cpp -+../../../src/hotspot/share/ci/ciInstance.hpp -+../../../src/hotspot/share/include/jmm.h -+../../../src/hotspot/share/include/jvm.h -+../../../src/hotspot/share/c1/c1_FpuStackSim.hpp -+../../../src/hotspot/share/c1/c1_MacroAssembler.hpp -+../../../src/hotspot/share/c1/c1_ValueStack.hpp -+../../../src/hotspot/share/c1/c1_Compilation.cpp -+../../../src/hotspot/share/c1/c1_FrameMap.cpp -+../../../src/hotspot/share/c1/c1_RangeCheckElimination.hpp -+../../../src/hotspot/share/c1/c1_LIRGenerator.cpp -+../../../src/hotspot/share/c1/c1_CodeStubs.hpp -+../../../src/hotspot/share/c1/c1_InstructionPrinter.hpp -+../../../src/hotspot/share/c1/c1_IR.hpp -+../../../src/hotspot/share/c1/c1_LinearScan.hpp -+../../../src/hotspot/share/c1/c1_CFGPrinter.cpp -+../../../src/hotspot/share/c1/c1_Instruction.hpp -+../../../src/hotspot/share/c1/c1_Compiler.cpp -+../../../src/hotspot/share/c1/c1_Defs.cpp -+../../../src/hotspot/share/c1/c1_ValueSet.hpp -+../../../src/hotspot/share/c1/c1_LIR.cpp -+../../../src/hotspot/share/c1/c1_LIRAssembler.cpp -+../../../src/hotspot/share/c1/c1_Runtime1.hpp -+../../../src/hotspot/share/c1/c1_Optimizer.hpp -+../../../src/hotspot/share/c1/c1_ValueMap.cpp -+../../../src/hotspot/share/c1/c1_GraphBuilder.hpp -+../../../src/hotspot/share/c1/c1_Canonicalizer.cpp -+../../../src/hotspot/share/c1/c1_ValueType.hpp -+../../../src/hotspot/share/c1/c1_globals.hpp -+../../../src/hotspot/share/c1/c1_Instruction.cpp -+../../../src/hotspot/share/c1/c1_Defs.hpp -+../../../src/hotspot/share/c1/c1_Compiler.hpp -+../../../src/hotspot/share/c1/c1_ValueSet.cpp -+../../../src/hotspot/share/c1/c1_LIR.hpp -+../../../src/hotspot/share/c1/c1_LIRAssembler.hpp -+../../../src/hotspot/share/c1/c1_Runtime1.cpp -+../../../src/hotspot/share/c1/c1_ValueMap.hpp -+../../../src/hotspot/share/c1/c1_Optimizer.cpp -+../../../src/hotspot/share/c1/c1_GraphBuilder.cpp -+../../../src/hotspot/share/c1/c1_Canonicalizer.hpp -+../../../src/hotspot/share/c1/c1_Decorators.hpp -+../../../src/hotspot/share/c1/c1_globals.cpp -+../../../src/hotspot/share/c1/c1_ValueType.cpp -+../../../src/hotspot/share/c1/c1_ValueStack.cpp -+../../../src/hotspot/share/c1/c1_Compilation.hpp -+../../../src/hotspot/share/c1/c1_FrameMap.hpp -+../../../src/hotspot/share/c1/c1_RangeCheckElimination.cpp -+../../../src/hotspot/share/c1/c1_LIRGenerator.hpp -+../../../src/hotspot/share/c1/c1_ValueSet.inline.hpp -+../../../src/hotspot/share/c1/c1_InstructionPrinter.cpp -+../../../src/hotspot/share/c1/c1_IR.cpp -+../../../src/hotspot/share/c1/c1_LinearScan.cpp -+../../../src/hotspot/share/c1/c1_CFGPrinter.hpp -+../../../src/hotspot/share/runtime/stackValueCollection.cpp -+../../../src/hotspot/share/runtime/safepointMechanism.hpp -+../../../src/hotspot/share/runtime/prefetch.hpp -+../../../src/hotspot/share/runtime/synchronizer.cpp -+../../../src/hotspot/share/runtime/vframe.cpp -+../../../src/hotspot/share/runtime/init.hpp -+../../../src/hotspot/share/runtime/fieldDescriptor.hpp -+../../../src/hotspot/share/runtime/os.inline.hpp -+../../../src/hotspot/share/runtime/mutex.cpp -+../../../src/hotspot/share/runtime/safepoint.hpp -+../../../src/hotspot/share/runtime/thread.cpp -+../../../src/hotspot/share/runtime/jniHandles.cpp -+../../../src/hotspot/share/runtime/semaphore.hpp -+../../../src/hotspot/share/runtime/vframe.inline.hpp -+../../../src/hotspot/share/runtime/unhandledOops.hpp -+../../../src/hotspot/share/runtime/rframe.hpp -+../../../src/hotspot/share/runtime/sharedRuntimeTrig.cpp -+../../../src/hotspot/share/runtime/os.cpp -+../../../src/hotspot/share/runtime/frame.cpp -+../../../src/hotspot/share/runtime/osThread.cpp -+../../../src/hotspot/share/runtime/jniHandles.inline.hpp -+../../../src/hotspot/share/runtime/vmStructs.hpp -+../../../src/hotspot/share/runtime/vframeArray.cpp -+../../../src/hotspot/share/runtime/threadLocalStorage.hpp -+../../../src/hotspot/share/runtime/reflectionUtils.hpp -+../../../src/hotspot/share/runtime/signature.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlag.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlagRangeList.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagWriteableList.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintList.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintList.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp -+../../../src/hotspot/share/runtime/flags/jvmFlag.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp -+../../../src/hotspot/share/runtime/flags/flagSetting.hpp -+../../../src/hotspot/share/runtime/flags/jvmFlagWriteableList.hpp -+../../../src/hotspot/share/runtime/orderAccess.cpp -+../../../src/hotspot/share/runtime/handles.inline.hpp -+../../../src/hotspot/share/runtime/arguments.cpp -+../../../src/hotspot/share/runtime/handles.hpp -+../../../src/hotspot/share/runtime/objectMonitor.hpp -+../../../src/hotspot/share/runtime/threadCritical.hpp -+../../../src/hotspot/share/runtime/park.hpp -+../../../src/hotspot/share/runtime/sweeper.cpp -+../../../src/hotspot/share/runtime/relocator.cpp -+../../../src/hotspot/share/runtime/sharedRuntime.hpp -+../../../src/hotspot/share/runtime/arguments_ext.cpp -+../../../src/hotspot/share/runtime/prefetch.inline.hpp -+../../../src/hotspot/share/runtime/globals_ext.hpp -+../../../src/hotspot/share/runtime/basicLock.hpp -+../../../src/hotspot/share/runtime/compilationPolicy.cpp -+../../../src/hotspot/share/runtime/java.hpp -+../../../src/hotspot/share/runtime/objectMonitor.inline.hpp -+../../../src/hotspot/share/runtime/mutexLocker.cpp -+../../../src/hotspot/share/runtime/serviceThread.cpp -+../../../src/hotspot/share/runtime/statSampler.cpp -+../../../src/hotspot/share/runtime/vm_operations.hpp -+../../../src/hotspot/share/runtime/timer.cpp -+../../../src/hotspot/share/runtime/stackValue.hpp -+../../../src/hotspot/share/runtime/monitorChunk.hpp -+../../../src/hotspot/share/runtime/extendedPC.hpp -+../../../src/hotspot/share/runtime/biasedLocking.cpp -+../../../src/hotspot/share/runtime/vmThread.cpp -+../../../src/hotspot/share/runtime/timerTrace.cpp -+../../../src/hotspot/share/runtime/os_ext.hpp -+../../../src/hotspot/share/runtime/stubCodeGenerator.cpp -+../../../src/hotspot/share/runtime/threadSMR.cpp -+../../../src/hotspot/share/runtime/task.hpp -+../../../src/hotspot/share/runtime/perfData.hpp -+../../../src/hotspot/share/runtime/vframe_hp.hpp -+../../../src/hotspot/share/runtime/stubRoutines.hpp -+../../../src/hotspot/share/runtime/threadHeapSampler.hpp -+../../../src/hotspot/share/runtime/vm_version.cpp -+../../../src/hotspot/share/runtime/memprofiler.hpp -+../../../src/hotspot/share/runtime/fieldType.hpp -+../../../src/hotspot/share/runtime/safepointVerifiers.hpp -+../../../src/hotspot/share/runtime/globals.cpp -+../../../src/hotspot/share/runtime/threadStatisticalInfo.hpp -+../../../src/hotspot/share/runtime/handshake.cpp -+../../../src/hotspot/share/runtime/atomic.hpp -+../../../src/hotspot/share/runtime/jniPeriodicChecker.cpp -+../../../src/hotspot/share/runtime/deoptimization.hpp -+../../../src/hotspot/share/runtime/perfMemory.cpp -+../../../src/hotspot/share/runtime/interfaceSupport.inline.hpp -+../../../src/hotspot/share/runtime/os_perf.hpp -+../../../src/hotspot/share/runtime/globals_extension.hpp -+../../../src/hotspot/share/runtime/threadSMR.inline.hpp -+../../../src/hotspot/share/runtime/icache.hpp -+../../../src/hotspot/share/runtime/reflection.hpp -+../../../src/hotspot/share/runtime/javaCalls.hpp -+../../../src/hotspot/share/runtime/rtmLocking.hpp -+../../../src/hotspot/share/runtime/compilationPolicy.hpp -+../../../src/hotspot/share/runtime/basicLock.cpp -+../../../src/hotspot/share/runtime/java.cpp -+../../../src/hotspot/share/runtime/perfData.inline.hpp -+../../../src/hotspot/share/runtime/statSampler.hpp -+../../../src/hotspot/share/runtime/vm_operations.cpp -+../../../src/hotspot/share/runtime/mutexLocker.hpp -+../../../src/hotspot/share/runtime/serviceThread.hpp -+../../../src/hotspot/share/runtime/monitorChunk.cpp -+../../../src/hotspot/share/runtime/stackValue.cpp -+../../../src/hotspot/share/runtime/timer.hpp -+../../../src/hotspot/share/runtime/vmThread.hpp -+../../../src/hotspot/share/runtime/jfieldIDWorkaround.hpp -+../../../src/hotspot/share/runtime/biasedLocking.hpp -+../../../src/hotspot/share/runtime/registerMap.hpp -+../../../src/hotspot/share/runtime/threadSMR.hpp -+../../../src/hotspot/share/runtime/task.cpp -+../../../src/hotspot/share/runtime/perfData.cpp -+../../../src/hotspot/share/runtime/stubCodeGenerator.hpp -+../../../src/hotspot/share/runtime/timerTrace.hpp -+../../../src/hotspot/share/runtime/stubRoutines.cpp -+../../../src/hotspot/share/runtime/interfaceSupport.cpp -+../../../src/hotspot/share/runtime/vframe_hp.cpp -+../../../src/hotspot/share/runtime/threadHeapSampler.cpp -+../../../src/hotspot/share/runtime/vm_version.hpp -+../../../src/hotspot/share/runtime/javaFrameAnchor.hpp -+../../../src/hotspot/share/runtime/memprofiler.cpp -+../../../src/hotspot/share/runtime/globals.hpp -+../../../src/hotspot/share/runtime/safepointVerifiers.cpp -+../../../src/hotspot/share/runtime/fieldType.cpp -+../../../src/hotspot/share/runtime/deoptimization.cpp -+../../../src/hotspot/share/runtime/jniPeriodicChecker.hpp -+../../../src/hotspot/share/runtime/handshake.hpp -+../../../src/hotspot/share/runtime/thread.inline.hpp -+../../../src/hotspot/share/runtime/perfMemory.hpp -+../../../src/hotspot/share/runtime/javaCalls.cpp -+../../../src/hotspot/share/runtime/reflection.cpp -+../../../src/hotspot/share/runtime/icache.cpp -+../../../src/hotspot/share/runtime/rtmLocking.cpp -+../../../src/hotspot/share/runtime/stackValueCollection.hpp -+../../../src/hotspot/share/runtime/safepointMechanism.cpp -+../../../src/hotspot/share/runtime/semaphore.inline.hpp -+../../../src/hotspot/share/runtime/vframe.hpp -+../../../src/hotspot/share/runtime/synchronizer.hpp -+../../../src/hotspot/share/runtime/fieldDescriptor.cpp -+../../../src/hotspot/share/runtime/init.cpp -+../../../src/hotspot/share/runtime/mutex.hpp -+../../../src/hotspot/share/runtime/thread.hpp -+../../../src/hotspot/share/runtime/jniHandles.hpp -+../../../src/hotspot/share/runtime/safepoint.cpp -+../../../src/hotspot/share/runtime/unhandledOops.cpp -+../../../src/hotspot/share/runtime/rframe.cpp -+../../../src/hotspot/share/runtime/safepointMechanism.inline.hpp -+../../../src/hotspot/share/runtime/osThread.hpp -+../../../src/hotspot/share/runtime/frame.inline.hpp -+../../../src/hotspot/share/runtime/frame.hpp -+../../../src/hotspot/share/runtime/os.hpp -+../../../src/hotspot/share/runtime/vframeArray.hpp -+../../../src/hotspot/share/runtime/vmStructs.cpp -+../../../src/hotspot/share/runtime/signature.hpp -+../../../src/hotspot/share/runtime/reflectionUtils.cpp -+../../../src/hotspot/share/runtime/orderAccess.hpp -+../../../src/hotspot/share/runtime/arguments.hpp -+../../../src/hotspot/share/runtime/handles.cpp -+../../../src/hotspot/share/runtime/objectMonitor.cpp -+../../../src/hotspot/share/runtime/sharedRuntimeMath.hpp -+../../../src/hotspot/share/runtime/sweeper.hpp -+../../../src/hotspot/share/runtime/park.cpp -+../../../src/hotspot/share/runtime/sharedRuntime.cpp -+../../../src/hotspot/share/runtime/relocator.hpp -+../../../src/hotspot/share/runtime/sharedRuntimeTrans.cpp -+../../../src/hotspot/share/runtime/arguments_ext.hpp -+../../../src/hotspot/share/libadt/set.cpp -+../../../src/hotspot/share/libadt/vectset.hpp -+../../../src/hotspot/share/libadt/dict.cpp -+../../../src/hotspot/share/libadt/set.hpp -+../../../src/hotspot/share/libadt/dict.hpp -+../../../src/hotspot/share/libadt/vectset.cpp -+../../../src/hotspot/share/code/codeCache.hpp -+../../../src/hotspot/share/code/pcDesc.hpp -+../../../src/hotspot/share/code/oopRecorder.cpp -+../../../src/hotspot/share/code/dependencies.cpp -+../../../src/hotspot/share/code/compiledMethod.inline.hpp -+../../../src/hotspot/share/code/compressedStream.hpp -+../../../src/hotspot/share/code/stubs.cpp -+../../../src/hotspot/share/code/exceptionHandlerTable.hpp -+../../../src/hotspot/share/code/nmethod.hpp -+../../../src/hotspot/share/code/compiledMethod.hpp -+../../../src/hotspot/share/code/compiledIC.cpp -+../../../src/hotspot/share/code/codeBlob.cpp -+../../../src/hotspot/share/code/codeHeapState.cpp -+../../../src/hotspot/share/code/icBuffer.cpp -+../../../src/hotspot/share/code/dependencyContext.hpp -+../../../src/hotspot/share/code/debugInfo.hpp -+../../../src/hotspot/share/code/vtableStubs.cpp -+../../../src/hotspot/share/code/nativeInst.hpp -+../../../src/hotspot/share/code/location.cpp -+../../../src/hotspot/share/code/relocInfo.cpp -+../../../src/hotspot/share/code/relocInfo_ext.hpp -+../../../src/hotspot/share/code/vmreg.cpp -+../../../src/hotspot/share/code/scopeDesc.hpp -+../../../src/hotspot/share/code/debugInfoRec.hpp -+../../../src/hotspot/share/code/codeHeapState.hpp -+../../../src/hotspot/share/code/dependencyContext.cpp -+../../../src/hotspot/share/code/icBuffer.hpp -+../../../src/hotspot/share/code/debugInfo.cpp -+../../../src/hotspot/share/code/vtableStubs.hpp -+../../../src/hotspot/share/code/relocInfo.hpp -+../../../src/hotspot/share/code/location.hpp -+../../../src/hotspot/share/code/vmreg.inline.hpp -+../../../src/hotspot/share/code/vmreg.hpp -+../../../src/hotspot/share/code/relocInfo_ext.cpp -+../../../src/hotspot/share/code/debugInfoRec.cpp -+../../../src/hotspot/share/code/scopeDesc.cpp -+../../../src/hotspot/share/code/codeCache.cpp -+../../../src/hotspot/share/code/pcDesc.cpp -+../../../src/hotspot/share/code/oopRecorder.hpp -+../../../src/hotspot/share/code/dependencies.hpp -+../../../src/hotspot/share/code/stubs.hpp -+../../../src/hotspot/share/code/compressedStream.cpp -+../../../src/hotspot/share/code/exceptionHandlerTable.cpp -+../../../src/hotspot/share/code/nmethod.cpp -+../../../src/hotspot/share/code/compiledMethod.cpp -+../../../src/hotspot/share/code/compiledIC.hpp -+../../../src/hotspot/share/code/codeBlob.hpp -+../../../src/hotspot/share/prims/jvmtiImpl.hpp -+../../../src/hotspot/share/prims/jvmtiTagMap.cpp -+../../../src/hotspot/share/prims/jvmtiExport.hpp -+../../../src/hotspot/share/prims/jvmtiEventController.inline.hpp -+../../../src/hotspot/share/prims/whitebox.inline.hpp -+../../../src/hotspot/share/prims/jvmtiTrace.cpp -+../../../src/hotspot/share/prims/cdsoffsets.hpp -+../../../src/hotspot/share/prims/jvmtiRawMonitor.cpp -+../../../src/hotspot/share/prims/jvmtiExtensions.hpp -+../../../src/hotspot/share/prims/jvmtiManageCapabilities.cpp -+../../../src/hotspot/share/prims/jvmtiRedefineClasses.cpp -+../../../src/hotspot/share/prims/nativeLookup.cpp -+../../../src/hotspot/share/prims/perf.cpp -+../../../src/hotspot/share/prims/jniCheck.cpp -+../../../src/hotspot/share/prims/forte.cpp -+../../../src/hotspot/share/prims/jvmtiEventController.hpp -+../../../src/hotspot/share/prims/jvmtiEnvThreadState.hpp -+../../../src/hotspot/share/prims/methodComparator.cpp -+../../../src/hotspot/share/prims/jvmtiThreadState.inline.hpp -+../../../src/hotspot/share/prims/resolvedMethodTable.hpp -+../../../src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp -+../../../src/hotspot/share/prims/whitebox.cpp -+../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.hpp -+../../../src/hotspot/share/prims/jvmtiAgentThread.hpp -+../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp -+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+../../../src/hotspot/share/prims/stackwalk.cpp -+../../../src/hotspot/share/prims/privilegedStack.hpp -+../../../src/hotspot/share/prims/jvmtiUtil.hpp -+../../../src/hotspot/share/prims/jvmtiEnvBase.hpp -+../../../src/hotspot/share/prims/jvmtiThreadState.cpp -+../../../src/hotspot/share/prims/methodHandles.hpp -+../../../src/hotspot/share/prims/jniFastGetField.hpp -+../../../src/hotspot/share/prims/wbtestmethods/parserTests.cpp -+../../../src/hotspot/share/prims/wbtestmethods/parserTests.hpp -+../../../src/hotspot/share/prims/unsafe.cpp -+../../../src/hotspot/share/prims/methodComparator.hpp -+../../../src/hotspot/share/prims/jvmtiEnvThreadState.cpp -+../../../src/hotspot/share/prims/resolvedMethodTable.cpp -+../../../src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp -+../../../src/hotspot/share/prims/evmCompat.cpp -+../../../src/hotspot/share/prims/whitebox.hpp -+../../../src/hotspot/share/prims/jvmtiEnter.inline.hpp -+../../../src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -+../../../src/hotspot/share/prims/stackwalk.hpp -+../../../src/hotspot/share/prims/privilegedStack.cpp -+../../../src/hotspot/share/prims/jvmtiCodeBlobEvents.hpp -+../../../src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+../../../src/hotspot/share/prims/jvmtiUtil.cpp -+../../../src/hotspot/share/prims/jvmtiEnvBase.cpp -+../../../src/hotspot/share/prims/methodHandles.cpp -+../../../src/hotspot/share/prims/jvmtiThreadState.hpp -+../../../src/hotspot/share/prims/jniFastGetField.cpp -+../../../src/hotspot/share/prims/jvm_misc.hpp -+../../../src/hotspot/share/prims/unsafe.hpp -+../../../src/hotspot/share/prims/jvmtiImpl.cpp -+../../../src/hotspot/share/prims/jvmtiTagMap.hpp -+../../../src/hotspot/share/prims/jvmtiExport.cpp -+../../../src/hotspot/share/prims/jvmtiTrace.hpp -+../../../src/hotspot/share/prims/cdsoffsets.cpp -+../../../src/hotspot/share/prims/jvmtiRawMonitor.hpp -+../../../src/hotspot/share/prims/jvmtiExtensions.cpp -+../../../src/hotspot/share/prims/jniExport.hpp -+../../../src/hotspot/share/prims/jvmtiManageCapabilities.hpp -+../../../src/hotspot/share/prims/jvmtiRedefineClasses.hpp -+../../../src/hotspot/share/prims/jni.cpp -+../../../src/hotspot/share/prims/jvm.cpp -+../../../src/hotspot/share/prims/jvmtiEnv.cpp -+../../../src/hotspot/share/prims/nativeLookup.hpp -+../../../src/hotspot/share/prims/jniCheck.hpp -+../../../src/hotspot/share/prims/jvmtiEventController.cpp -+../../../src/hotspot/share/prims/forte.hpp -+../../../src/hotspot/share/classfile/sharedPathsMiscInfo.hpp -+../../../src/hotspot/share/classfile/classLoaderStats.cpp -+../../../src/hotspot/share/classfile/javaClasses.cpp -+../../../src/hotspot/share/classfile/compactHashtable.hpp -+../../../src/hotspot/share/classfile/metadataOnStackMark.cpp -+../../../src/hotspot/share/classfile/classFileStream.hpp -+../../../src/hotspot/share/classfile/klassFactory.cpp -+../../../src/hotspot/share/classfile/moduleEntry.cpp -+../../../src/hotspot/share/classfile/packageEntry.cpp -+../../../src/hotspot/share/classfile/bytecodeAssembler.hpp -+../../../src/hotspot/share/classfile/classListParser.hpp -+../../../src/hotspot/share/classfile/javaClasses.inline.hpp -+../../../src/hotspot/share/classfile/classLoaderExt.hpp -+../../../src/hotspot/share/classfile/classLoader.hpp -+../../../src/hotspot/share/classfile/dictionary.hpp -+../../../src/hotspot/share/classfile/classLoaderData.inline.hpp -+../../../src/hotspot/share/classfile/stringTable.cpp -+../../../src/hotspot/share/classfile/stackMapFrame.hpp -+../../../src/hotspot/share/classfile/altHashing.cpp -+../../../src/hotspot/share/classfile/placeholders.cpp -+../../../src/hotspot/share/classfile/defaultMethods.hpp -+../../../src/hotspot/share/classfile/systemDictionaryShared.hpp -+../../../src/hotspot/share/classfile/classLoader.inline.hpp -+../../../src/hotspot/share/classfile/classFileError.cpp -+../../../src/hotspot/share/classfile/javaAssertions.cpp -+../../../src/hotspot/share/classfile/classFileParser.hpp -+../../../src/hotspot/share/classfile/verifier.hpp -+../../../src/hotspot/share/classfile/protectionDomainCache.hpp -+../../../src/hotspot/share/classfile/dictionary.inline.hpp -+../../../src/hotspot/share/classfile/stackMapTable.hpp -+../../../src/hotspot/share/classfile/resolutionErrors.hpp -+../../../src/hotspot/share/classfile/symbolTable.hpp -+../../../src/hotspot/share/classfile/vmSymbols.hpp -+../../../src/hotspot/share/classfile/compactHashtable.inline.hpp -+../../../src/hotspot/share/classfile/modules.cpp -+../../../src/hotspot/share/classfile/verificationType.cpp -+../../../src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp -+../../../src/hotspot/share/classfile/loaderConstraints.cpp -+../../../src/hotspot/share/classfile/classLoaderData.cpp -+../../../src/hotspot/share/classfile/systemDictionary.hpp -+../../../src/hotspot/share/classfile/altHashing.hpp -+../../../src/hotspot/share/classfile/stringTable.hpp -+../../../src/hotspot/share/classfile/stackMapFrame.cpp -+../../../src/hotspot/share/classfile/defaultMethods.cpp -+../../../src/hotspot/share/classfile/placeholders.hpp -+../../../src/hotspot/share/classfile/systemDictionaryShared.cpp -+../../../src/hotspot/share/classfile/javaAssertions.hpp -+../../../src/hotspot/share/classfile/protectionDomainCache.cpp -+../../../src/hotspot/share/classfile/classFileParser.cpp -+../../../src/hotspot/share/classfile/verifier.cpp -+../../../src/hotspot/share/classfile/stackMapTable.cpp -+../../../src/hotspot/share/classfile/vmSymbols.cpp -+../../../src/hotspot/share/classfile/symbolTable.cpp -+../../../src/hotspot/share/classfile/resolutionErrors.cpp -+../../../src/hotspot/share/classfile/verificationType.hpp -+../../../src/hotspot/share/classfile/modules.hpp -+../../../src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp -+../../../src/hotspot/share/classfile/loaderConstraints.hpp -+../../../src/hotspot/share/classfile/classLoaderData.hpp -+../../../src/hotspot/share/classfile/systemDictionary.cpp -+../../../src/hotspot/share/classfile/sharedPathsMiscInfo.cpp -+../../../src/hotspot/share/classfile/javaClasses.hpp -+../../../src/hotspot/share/classfile/classLoaderStats.hpp -+../../../src/hotspot/share/classfile/compactHashtable.cpp -+../../../src/hotspot/share/classfile/metadataOnStackMark.hpp -+../../../src/hotspot/share/classfile/classFileStream.cpp -+../../../src/hotspot/share/classfile/moduleEntry.hpp -+../../../src/hotspot/share/classfile/klassFactory.hpp -+../../../src/hotspot/share/classfile/packageEntry.hpp -+../../../src/hotspot/share/classfile/stackMapTableFormat.hpp -+../../../src/hotspot/share/classfile/bytecodeAssembler.cpp -+../../../src/hotspot/share/classfile/classListParser.cpp -+../../../src/hotspot/share/classfile/classLoaderExt.cpp -+../../../src/hotspot/share/classfile/classLoader.cpp -+../../../src/hotspot/share/classfile/dictionary.cpp -+../../../src/hotspot/share/utilities/numberSeq.hpp -+../../../src/hotspot/share/utilities/exceptions.cpp -+../../../src/hotspot/share/utilities/vmError.hpp -+../../../src/hotspot/share/utilities/globalCounter.hpp -+../../../src/hotspot/share/utilities/resourceHash.hpp -+../../../src/hotspot/share/utilities/pair.hpp -+../../../src/hotspot/share/utilities/constantTag.hpp -+../../../src/hotspot/share/utilities/bitMap.inline.hpp -+../../../src/hotspot/share/utilities/globalDefinitions_xlc.hpp -+../../../src/hotspot/share/utilities/defaultStream.hpp -+../../../src/hotspot/share/utilities/globalCounter.inline.hpp -+../../../src/hotspot/share/utilities/intHisto.hpp -+../../../src/hotspot/share/utilities/utf8.hpp -+../../../src/hotspot/share/utilities/copy.cpp -+../../../src/hotspot/share/utilities/globalDefinitions_visCPP.hpp -+../../../src/hotspot/share/utilities/json.hpp -+../../../src/hotspot/share/utilities/elfFuncDescTable.hpp -+../../../src/hotspot/share/utilities/bitMap.cpp -+../../../src/hotspot/share/utilities/count_trailing_zeros.hpp -+../../../src/hotspot/share/utilities/quickSort.hpp -+../../../src/hotspot/share/utilities/sizes.cpp -+../../../src/hotspot/share/utilities/decoder_elf.cpp -+../../../src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp -+../../../src/hotspot/share/utilities/ostream.hpp -+../../../src/hotspot/share/utilities/macros.hpp -+../../../src/hotspot/share/utilities/elfFile.cpp -+../../../src/hotspot/share/utilities/align.hpp -+../../../src/hotspot/share/utilities/xmlstream.hpp -+../../../src/hotspot/share/utilities/internalVMTests.cpp -+../../../src/hotspot/share/utilities/preserveException.cpp -+../../../src/hotspot/share/utilities/elfSymbolTable.hpp -+../../../src/hotspot/share/utilities/spinYield.cpp -+../../../src/hotspot/share/utilities/accessFlags.cpp -+../../../src/hotspot/share/utilities/formatBuffer.cpp -+../../../src/hotspot/share/utilities/errorReporter.hpp -+../../../src/hotspot/share/utilities/globalDefinitions_sparcWorks.hpp -+../../../src/hotspot/share/utilities/histogram.hpp -+../../../src/hotspot/share/utilities/stringUtils.cpp -+../../../src/hotspot/share/utilities/ticks.cpp -+../../../src/hotspot/share/utilities/dtrace_disabled.hpp -+../../../src/hotspot/share/utilities/debug.hpp -+../../../src/hotspot/share/utilities/growableArray.cpp -+../../../src/hotspot/share/utilities/globalDefinitions.hpp -+../../../src/hotspot/share/utilities/nativeCallStack.hpp -+../../../src/hotspot/share/utilities/hashtable.hpp -+../../../src/hotspot/share/utilities/decoder.hpp -+../../../src/hotspot/share/utilities/elfStringTable.cpp -+../../../src/hotspot/share/utilities/events.hpp -+../../../src/hotspot/share/utilities/ostream.cpp -+../../../src/hotspot/share/utilities/elfFile.hpp -+../../../src/hotspot/share/utilities/internalVMTests.hpp -+../../../src/hotspot/share/utilities/fakeRttiSupport.hpp -+../../../src/hotspot/share/utilities/xmlstream.cpp -+../../../src/hotspot/share/utilities/elfSymbolTable.cpp -+../../../src/hotspot/share/utilities/preserveException.hpp -+../../../src/hotspot/share/utilities/accessFlags.hpp -+../../../src/hotspot/share/utilities/spinYield.hpp -+../../../src/hotspot/share/utilities/formatBuffer.hpp -+../../../src/hotspot/share/utilities/errorReporter.cpp -+../../../src/hotspot/share/utilities/breakpoint.hpp -+../../../src/hotspot/share/utilities/histogram.cpp -+../../../src/hotspot/share/utilities/ticks.hpp -+../../../src/hotspot/share/utilities/stringUtils.hpp -+../../../src/hotspot/share/utilities/growableArray.hpp -+../../../src/hotspot/share/utilities/debug.cpp -+../../../src/hotspot/share/utilities/globalDefinitions.cpp -+../../../src/hotspot/share/utilities/bytes.hpp -+../../../src/hotspot/share/utilities/stack.hpp -+../../../src/hotspot/share/utilities/hashtable.cpp -+../../../src/hotspot/share/utilities/nativeCallStack.cpp -+../../../src/hotspot/share/utilities/events.cpp -+../../../src/hotspot/share/utilities/decoder.cpp -+../../../src/hotspot/share/utilities/elfStringTable.hpp -+../../../src/hotspot/share/utilities/exceptions.hpp -+../../../src/hotspot/share/utilities/globalDefinitions_gcc.hpp -+../../../src/hotspot/share/utilities/dtrace.hpp -+../../../src/hotspot/share/utilities/numberSeq.cpp -+../../../src/hotspot/share/utilities/vmError.cpp -+../../../src/hotspot/share/utilities/globalCounter.cpp -+../../../src/hotspot/share/utilities/constantTag.cpp -+../../../src/hotspot/share/utilities/stack.inline.hpp -+../../../src/hotspot/share/utilities/hashtable.inline.hpp -+../../../src/hotspot/share/utilities/concurrentHashTable.inline.hpp -+../../../src/hotspot/share/utilities/intHisto.cpp -+../../../src/hotspot/share/utilities/copy.hpp -+../../../src/hotspot/share/utilities/utf8.cpp -+../../../src/hotspot/share/utilities/json.cpp -+../../../src/hotspot/share/utilities/concurrentHashTable.hpp -+../../../src/hotspot/share/utilities/elfFuncDescTable.cpp -+../../../src/hotspot/share/utilities/bitMap.hpp -+../../../src/hotspot/share/utilities/decoder_elf.hpp -+../../../src/hotspot/share/utilities/linkedlist.hpp -+../../../src/hotspot/share/utilities/chunkedList.hpp -+../../../src/hotspot/share/utilities/sizes.hpp -+../../../src/hotspot/share/utilities/compilerWarnings.hpp -+../../../src/hotspot/share/adlc/dict2.hpp -+../../../src/hotspot/share/adlc/filebuff.cpp -+../../../src/hotspot/share/adlc/formssel.hpp -+../../../src/hotspot/share/adlc/adlc.hpp -+../../../src/hotspot/share/adlc/forms.cpp -+../../../src/hotspot/share/adlc/output_c.cpp -+../../../src/hotspot/share/adlc/formsopt.cpp -+../../../src/hotspot/share/adlc/dfa.cpp -+../../../src/hotspot/share/adlc/archDesc.cpp -+../../../src/hotspot/share/adlc/arena.cpp -+../../../src/hotspot/share/adlc/adlparse.hpp -+../../../src/hotspot/share/adlc/formsopt.hpp -+../../../src/hotspot/share/adlc/archDesc.hpp -+../../../src/hotspot/share/adlc/output_h.cpp -+../../../src/hotspot/share/adlc/arena.hpp -+../../../src/hotspot/share/adlc/adlparse.cpp -+../../../src/hotspot/share/adlc/filebuff.hpp -+../../../src/hotspot/share/adlc/dict2.cpp -+../../../src/hotspot/share/adlc/formssel.cpp -+../../../src/hotspot/share/adlc/main.cpp -+../../../src/hotspot/share/adlc/forms.hpp -+../../../src/hotspot/share/gc/parallel/vmPSOperations.cpp -+../../../src/hotspot/share/gc/parallel/psGenerationCounters.hpp -+../../../src/hotspot/share/gc/parallel/spaceCounters.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionManager.cpp -+../../../src/hotspot/share/gc/parallel/parallelArguments.cpp -+../../../src/hotspot/share/gc/parallel/psScavenge.cpp -+../../../src/hotspot/share/gc/parallel/asPSOldGen.hpp -+../../../src/hotspot/share/gc/parallel/psTasks.cpp -+../../../src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.hpp -+../../../src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionLAB.cpp -+../../../src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp -+../../../src/hotspot/share/gc/parallel/mutableNUMASpace.hpp -+../../../src/hotspot/share/gc/parallel/pcTasks.hpp -+../../../src/hotspot/share/gc/parallel/psMarkSweep.hpp -+../../../src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp -+../../../src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp -+../../../src/hotspot/share/gc/parallel/psOldGen.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionLAB.inline.hpp -+../../../src/hotspot/share/gc/parallel/generationSizer.cpp -+../../../src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp -+../../../src/hotspot/share/gc/parallel/asPSYoungGen.cpp -+../../../src/hotspot/share/gc/parallel/psVirtualspace.hpp -+../../../src/hotspot/share/gc/parallel/adjoiningVirtualSpaces.cpp -+../../../src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp -+../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp -+../../../src/hotspot/share/gc/parallel/psCompactionManager.hpp -+../../../src/hotspot/share/gc/parallel/gcTaskManager.cpp -+../../../src/hotspot/share/gc/parallel/gcTaskThread.cpp -+../../../src/hotspot/share/gc/parallel/immutableSpace.cpp -+../../../src/hotspot/share/gc/parallel/psParallelCompact.hpp -+../../../src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp -+../../../src/hotspot/share/gc/parallel/psYoungGen.cpp -+../../../src/hotspot/share/gc/parallel/psMemoryPool.cpp -+../../../src/hotspot/share/gc/parallel/mutableSpace.hpp -+../../../src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp -+../../../src/hotspot/share/gc/parallel/psCardTable.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp -+../../../src/hotspot/share/gc/parallel/adjoiningGenerations.cpp -+../../../src/hotspot/share/gc/parallel/objectStartArray.hpp -+../../../src/hotspot/share/gc/parallel/parMarkBitMap.cpp -+../../../src/hotspot/share/gc/parallel/psMarkSweepProxy.hpp -+../../../src/hotspot/share/gc/parallel/generationSizer.hpp -+../../../src/hotspot/share/gc/parallel/asPSYoungGen.hpp -+../../../src/hotspot/share/gc/parallel/psVirtualspace.cpp -+../../../src/hotspot/share/gc/parallel/adjoiningVirtualSpaces.hpp -+../../../src/hotspot/share/gc/parallel/gcTaskManager.hpp -+../../../src/hotspot/share/gc/parallel/gcTaskThread.hpp -+../../../src/hotspot/share/gc/parallel/psCompactionManager.cpp -+../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp -+../../../src/hotspot/share/gc/parallel/psParallelCompact.cpp -+../../../src/hotspot/share/gc/parallel/immutableSpace.hpp -+../../../src/hotspot/share/gc/parallel/psScavenge.inline.hpp -+../../../src/hotspot/share/gc/parallel/psMemoryPool.hpp -+../../../src/hotspot/share/gc/parallel/psYoungGen.hpp -+../../../src/hotspot/share/gc/parallel/mutableSpace.cpp -+../../../src/hotspot/share/gc/parallel/psCardTable.cpp -+../../../src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp -+../../../src/hotspot/share/gc/parallel/adjoiningGenerations.hpp -+../../../src/hotspot/share/gc/parallel/objectStartArray.cpp -+../../../src/hotspot/share/gc/parallel/parMarkBitMap.hpp -+../../../src/hotspot/share/gc/parallel/vmPSOperations.hpp -+../../../src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp -+../../../src/hotspot/share/gc/parallel/parallelArguments.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionManager.hpp -+../../../src/hotspot/share/gc/parallel/spaceCounters.cpp -+../../../src/hotspot/share/gc/parallel/psGenerationCounters.cpp -+../../../src/hotspot/share/gc/parallel/psScavenge.hpp -+../../../src/hotspot/share/gc/parallel/asPSOldGen.cpp -+../../../src/hotspot/share/gc/parallel/psTasks.hpp -+../../../src/hotspot/share/gc/parallel/jvmFlagConstraintsParallel.cpp -+../../../src/hotspot/share/gc/parallel/gcAdaptivePolicyCounters.cpp -+../../../src/hotspot/share/gc/parallel/objectStartArray.inline.hpp -+../../../src/hotspot/share/gc/parallel/psPromotionLAB.hpp -+../../../src/hotspot/share/gc/parallel/mutableNUMASpace.cpp -+../../../src/hotspot/share/gc/parallel/pcTasks.cpp -+../../../src/hotspot/share/gc/parallel/psMarkSweep.cpp -+../../../src/hotspot/share/gc/parallel/parallel_globals.hpp -+../../../src/hotspot/share/gc/parallel/psOldGen.cpp -+../../../src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp -+../../../src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp -+../../../src/hotspot/share/gc/g1/heapRegionManager.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedupQueue.hpp -+../../../src/hotspot/share/gc/g1/g1RemSetSummary.hpp -+../../../src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp -+../../../src/hotspot/share/gc/g1/g1Predictions.hpp -+../../../src/hotspot/share/gc/g1/g1FullCollector.cpp -+../../../src/hotspot/share/gc/g1/g1InCSetState.hpp -+../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.inline.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp -+../../../src/hotspot/share/gc/g1/g1CollectionSet.hpp -+../../../src/hotspot/share/gc/g1/g1BarrierSet.cpp -+../../../src/hotspot/share/gc/g1/heapRegionTracer.hpp -+../../../src/hotspot/share/gc/g1/g1Arguments.cpp -+../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp -+../../../src/hotspot/share/gc/g1/heapRegion.inline.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -+../../../src/hotspot/share/gc/g1/g1IHOPControl.cpp -+../../../src/hotspot/share/gc/g1/sparsePRT.hpp -+../../../src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp -+../../../src/hotspot/share/gc/g1/g1HotCardCache.hpp -+../../../src/hotspot/share/gc/g1/survRateGroup.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp -+../../../src/hotspot/share/gc/g1/g1CollectorState.hpp -+../../../src/hotspot/share/gc/g1/vm_operations_g1.cpp -+../../../src/hotspot/share/gc/g1/g1RootClosures.cpp -+../../../src/hotspot/share/gc/g1/dirtyCardQueue.cpp -+../../../src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp -+../../../src/hotspot/share/gc/g1/g1SharedClosures.hpp -+../../../src/hotspot/share/gc/g1/g1CardCounts.hpp -+../../../src/hotspot/share/gc/g1/g1EvacFailure.hpp -+../../../src/hotspot/share/gc/g1/heapRegionBounds.hpp -+../../../src/hotspot/share/gc/g1/satbMarkQueue.hpp -+../../../src/hotspot/share/gc/g1/g1HeapRegionEventSender.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMark.hpp -+../../../src/hotspot/share/gc/g1/g1Policy.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp -+../../../src/hotspot/share/gc/g1/g1HeapVerifier.cpp -+../../../src/hotspot/share/gc/g1/g1BarrierSetRuntime.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedupStat.hpp -+../../../src/hotspot/share/gc/g1/g1RootProcessor.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -+../../../src/hotspot/share/gc/g1/g1BarrierSetAssembler.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp -+../../../src/hotspot/share/gc/g1/g1CollectedHeap.hpp -+../../../src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp -+../../../src/hotspot/share/gc/g1/heapRegionBounds.inline.hpp -+../../../src/hotspot/share/gc/g1/g1CodeBlobClosure.hpp -+../../../src/hotspot/share/gc/g1/heapRegionType.hpp -+../../../src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp -+../../../src/hotspot/share/gc/g1/g1MMUTracker.cpp -+../../../src/hotspot/share/gc/g1/g1AllocRegion.hpp -+../../../src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp -+../../../src/hotspot/share/gc/g1/g1MemoryPool.cpp -+../../../src/hotspot/share/gc/g1/g1EvacStats.hpp -+../../../src/hotspot/share/gc/g1/g1HeapTransition.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp -+../../../src/hotspot/share/gc/g1/collectionSetChooser.cpp -+../../../src/hotspot/share/gc/g1/g1ParScanThreadState.hpp -+../../../src/hotspot/share/gc/g1/g1Analytics.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCMarkTask.hpp -+../../../src/hotspot/share/gc/g1/g1CodeCacheRemSet.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp -+../../../src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp -+../../../src/hotspot/share/gc/g1/c1/g1BarrierSetC1.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCMarker.hpp -+../../../src/hotspot/share/gc/g1/g1CodeRootSetTable.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.hpp -+../../../src/hotspot/share/gc/g1/g1CardTable.cpp -+../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp -+../../../src/hotspot/share/gc/g1/g1FromCardCache.cpp -+../../../src/hotspot/share/gc/g1/g1Allocator.hpp -+../../../src/hotspot/share/gc/g1/g1RemSet.cpp -+../../../src/hotspot/share/gc/g1/g1ThreadLocalData.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCTask.hpp -+../../../src/hotspot/share/gc/g1/g1SurvivorRegions.cpp -+../../../src/hotspot/share/gc/g1/ptrQueue.hpp -+../../../src/hotspot/share/gc/g1/g1YoungGenSizer.cpp -+../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedup.cpp -+../../../src/hotspot/share/gc/g1/heapRegion.cpp -+../../../src/hotspot/share/gc/g1/g1BiasedArray.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCScope.hpp -+../../../src/hotspot/share/gc/g1/g1MonitoringSupport.hpp -+../../../src/hotspot/share/gc/g1/heapRegionRemSet.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp -+../../../src/hotspot/share/gc/g1/g1CollectorPolicy.cpp -+../../../src/hotspot/share/gc/g1/g1OopClosures.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp -+../../../src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp -+../../../src/hotspot/share/gc/g1/g1OopClosures.inline.hpp -+../../../src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.hpp -+../../../src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp -+../../../src/hotspot/share/gc/g1/heapRegionSet.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp -+../../../src/hotspot/share/gc/g1/g1CodeBlobClosure.cpp -+../../../src/hotspot/share/gc/g1/g1CollectedHeap.cpp -+../../../src/hotspot/share/gc/g1/heapRegionType.cpp -+../../../src/hotspot/share/gc/g1/g1Allocator.inline.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp -+../../../src/hotspot/share/gc/g1/g1RootProcessor.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp -+../../../src/hotspot/share/gc/g1/g1AllocRegion.cpp -+../../../src/hotspot/share/gc/g1/g1MMUTracker.hpp -+../../../src/hotspot/share/gc/g1/g1MemoryPool.hpp -+../../../src/hotspot/share/gc/g1/g1EvacStats.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCAdjustTask.hpp -+../../../src/hotspot/share/gc/g1/g1HeapTransition.cpp -+../../../src/hotspot/share/gc/g1/collectionSetChooser.hpp -+../../../src/hotspot/share/gc/g1/g1HeapRegionTraceType.hpp -+../../../src/hotspot/share/gc/g1/g1Analytics.hpp -+../../../src/hotspot/share/gc/g1/g1ParScanThreadState.cpp -+../../../src/hotspot/share/gc/g1/g1YCTypes.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCMarkTask.cpp -+../../../src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp -+../../../src/hotspot/share/gc/g1/g1FullGCMarker.cpp -+../../../src/hotspot/share/gc/g1/heapRegionSet.inline.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp -+../../../src/hotspot/share/gc/g1/g1FromCardCache.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.inline.hpp -+../../../src/hotspot/share/gc/g1/g1CardTable.hpp -+../../../src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp -+../../../src/hotspot/share/gc/g1/g1RemSet.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCTask.cpp -+../../../src/hotspot/share/gc/g1/g1CardTable.inline.hpp -+../../../src/hotspot/share/gc/g1/g1SurvivorRegions.hpp -+../../../src/hotspot/share/gc/g1/vmStructs_g1.hpp -+../../../src/hotspot/share/gc/g1/g1Allocator.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedup.hpp -+../../../src/hotspot/share/gc/g1/g1YoungGenSizer.hpp -+../../../src/hotspot/share/gc/g1/ptrQueue.cpp -+../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy.hpp -+../../../src/hotspot/share/gc/g1/heapRegionRemSet.hpp -+../../../src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCScope.cpp -+../../../src/hotspot/share/gc/g1/heapRegion.hpp -+../../../src/hotspot/share/gc/g1/g1BiasedArray.cpp -+../../../src/hotspot/share/gc/g1/g1MonitoringSupport.cpp -+../../../src/hotspot/share/gc/g1/g1OopClosures.hpp -+../../../src/hotspot/share/gc/g1/g1CollectorPolicy.hpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp -+../../../src/hotspot/share/gc/g1/g1_globals.hpp -+../../../src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp -+../../../src/hotspot/share/gc/g1/heapRegionSet.hpp -+../../../src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp -+../../../src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp -+../../../src/hotspot/share/gc/g1/g1HeapSizingPolicy_ext.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedupQueue.cpp -+../../../src/hotspot/share/gc/g1/g1RemSetSummary.cpp -+../../../src/hotspot/share/gc/g1/heapRegionManager.hpp -+../../../src/hotspot/share/gc/g1/g1EdenRegions.hpp -+../../../src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp -+../../../src/hotspot/share/gc/g1/g1FullCollector.hpp -+../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp -+../../../src/hotspot/share/gc/g1/g1BarrierSet.hpp -+../../../src/hotspot/share/gc/g1/g1CollectionSet.cpp -+../../../src/hotspot/share/gc/g1/evacuationInfo.hpp -+../../../src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp -+../../../src/hotspot/share/gc/g1/c2/g1BarrierSetC2.hpp -+../../../src/hotspot/share/gc/g1/heapRegionTracer.cpp -+../../../src/hotspot/share/gc/g1/g1Arguments.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp -+../../../src/hotspot/share/gc/g1/sparsePRT.cpp -+../../../src/hotspot/share/gc/g1/g1IHOPControl.hpp -+../../../src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkBitMap.hpp -+../../../src/hotspot/share/gc/g1/g1HotCardCache.cpp -+../../../src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.hpp -+../../../src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -+../../../src/hotspot/share/gc/g1/survRateGroup.hpp -+../../../src/hotspot/share/gc/g1/g1EvacStats.inline.hpp -+../../../src/hotspot/share/gc/g1/dirtyCardQueue.hpp -+../../../src/hotspot/share/gc/g1/g1RootClosures.hpp -+../../../src/hotspot/share/gc/g1/g1HRPrinter.hpp -+../../../src/hotspot/share/gc/g1/vm_operations_g1.hpp -+../../../src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp -+../../../src/hotspot/share/gc/g1/heapRegionManager.inline.hpp -+../../../src/hotspot/share/gc/g1/satbMarkQueue.cpp -+../../../src/hotspot/share/gc/g1/g1HeapRegionEventSender.hpp -+../../../src/hotspot/share/gc/g1/g1CardCounts.cpp -+../../../src/hotspot/share/gc/g1/g1EvacFailure.cpp -+../../../src/hotspot/share/gc/g1/g1InitialMarkToMixedTimeTracker.hpp -+../../../src/hotspot/share/gc/g1/g1HeapVerifier.hpp -+../../../src/hotspot/share/gc/g1/g1Policy.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMark.cpp -+../../../src/hotspot/share/gc/g1/g1StringDedupStat.cpp -+../../../src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp -+../../../src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonMemoryPool.cpp -+../../../src/hotspot/share/gc/epsilon/epsilonArguments.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonHeap.cpp -+../../../src/hotspot/share/gc/epsilon/vmStructs_epsilon.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp -+../../../src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp -+../../../src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp -+../../../src/hotspot/share/gc/epsilon/epsilon_globals.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonMemoryPool.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonArguments.cpp -+../../../src/hotspot/share/gc/epsilon/epsilonHeap.hpp -+../../../src/hotspot/share/gc/epsilon/epsilonThreadLocalData.hpp -+../../../src/hotspot/share/gc/z/zMetronome.cpp -+../../../src/hotspot/share/gc/z/zHeap.cpp -+../../../src/hotspot/share/gc/z/zHash.inline.hpp -+../../../src/hotspot/share/gc/z/zValue.hpp -+../../../src/hotspot/share/gc/z/zLock.inline.hpp -+../../../src/hotspot/share/gc/z/zRelocationSetSelector.cpp -+../../../src/hotspot/share/gc/z/zCollectorPolicy.hpp -+../../../src/hotspot/share/gc/z/zAddress.hpp -+../../../src/hotspot/share/gc/z/zArguments.cpp -+../../../src/hotspot/share/gc/z/zTask.hpp -+../../../src/hotspot/share/gc/z/zVirtualMemory.cpp -+../../../src/hotspot/share/gc/z/zResurrection.cpp -+../../../src/hotspot/share/gc/z/zDirector.hpp -+../../../src/hotspot/share/gc/z/zList.hpp -+../../../src/hotspot/share/gc/z/zErrno.hpp -+../../../src/hotspot/share/gc/z/zBarrier.inline.hpp -+../../../src/hotspot/share/gc/z/zFuture.hpp -+../../../src/hotspot/share/gc/z/zReferenceProcessor.hpp -+../../../src/hotspot/share/gc/z/zLargePages.cpp -+../../../src/hotspot/share/gc/z/zFuture.inline.hpp -+../../../src/hotspot/share/gc/z/zForwardingTable.cpp -+../../../src/hotspot/share/gc/z/zMarkStack.cpp -+../../../src/hotspot/share/gc/z/zForwardingTable.inline.hpp -+../../../src/hotspot/share/gc/z/zWorkers.hpp -+../../../src/hotspot/share/gc/z/zLiveMap.cpp -+../../../src/hotspot/share/gc/z/zMemory.cpp -+../../../src/hotspot/share/gc/z/zOopClosures.inline.hpp -+../../../src/hotspot/share/gc/z/zNUMA.hpp -+../../../src/hotspot/share/gc/z/zRootsIterator.hpp -+../../../src/hotspot/share/gc/z/zGlobals.cpp -+../../../src/hotspot/share/gc/z/zVirtualMemory.inline.hpp -+../../../src/hotspot/share/gc/z/zRelocationSet.hpp -+../../../src/hotspot/share/gc/z/zArray.hpp -+../../../src/hotspot/share/gc/z/zResurrection.inline.hpp -+../../../src/hotspot/share/gc/z/zMemory.inline.hpp -+../../../src/hotspot/share/gc/z/zHeapIterator.cpp -+../../../src/hotspot/share/gc/z/zInitialize.cpp -+../../../src/hotspot/share/gc/z/zMarkCache.hpp -+../../../src/hotspot/share/gc/z/zPageCache.hpp -+../../../src/hotspot/share/gc/z/zTracer.hpp -+../../../src/hotspot/share/gc/z/zThread.cpp -+../../../src/hotspot/share/gc/z/zRelocate.hpp -+../../../src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp -+../../../src/hotspot/share/gc/z/zStat.cpp -+../../../src/hotspot/share/gc/z/z_globals.hpp -+../../../src/hotspot/share/gc/z/zBarrierSet.hpp -+../../../src/hotspot/share/gc/z/zLock.hpp -+../../../src/hotspot/share/gc/z/zBarrier.hpp -+../../../src/hotspot/share/gc/z/zPhysicalMemory.hpp -+../../../src/hotspot/share/gc/z/zDriver.hpp -+../../../src/hotspot/share/gc/z/zWeakRootsProcessor.cpp -+../../../src/hotspot/share/gc/z/zMessagePort.hpp -+../../../src/hotspot/share/gc/z/zPageTable.cpp -+../../../src/hotspot/share/gc/z/zCollectedHeap.hpp -+../../../src/hotspot/share/gc/z/zRuntimeWorkers.hpp -+../../../src/hotspot/share/gc/z/c1/zBarrierSetC1.hpp -+../../../src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp -+../../../src/hotspot/share/gc/z/zAddress.inline.hpp -+../../../src/hotspot/share/gc/z/zMark.cpp -+../../../src/hotspot/share/gc/z/vmStructs_z.cpp -+../../../src/hotspot/share/gc/z/zPreMappedMemory.inline.hpp -+../../../src/hotspot/share/gc/z/zOopClosures.cpp -+../../../src/hotspot/share/gc/z/zAllocationFlags.hpp -+../../../src/hotspot/share/gc/z/zPageTable.inline.hpp -+../../../src/hotspot/share/gc/z/zServiceability.cpp -+../../../src/hotspot/share/gc/z/zLargePages.inline.hpp -+../../../src/hotspot/share/gc/z/zPageAllocator.cpp -+../../../src/hotspot/share/gc/z/zBarrierSetAssembler.hpp -+../../../src/hotspot/share/gc/z/zPreMappedMemory.cpp -+../../../src/hotspot/share/gc/z/zPageCache.inline.hpp -+../../../src/hotspot/share/gc/z/zBarrierSetRuntime.cpp -+../../../src/hotspot/share/gc/z/zPage.cpp -+../../../src/hotspot/share/gc/z/zUtils.cpp -+../../../src/hotspot/share/gc/z/zObjectAllocator.hpp -+../../../src/hotspot/share/gc/z/zHash.hpp -+../../../src/hotspot/share/gc/z/zNMethodTable.cpp -+../../../src/hotspot/share/gc/z/zPageTableEntry.hpp -+../../../src/hotspot/share/gc/z/zCPU.hpp -+../../../src/hotspot/share/gc/z/zBitMap.inline.hpp -+../../../src/hotspot/share/gc/z/zStat.hpp -+../../../src/hotspot/share/gc/z/zBarrierSet.cpp -+../../../src/hotspot/share/gc/z/zBarrier.cpp -+../../../src/hotspot/share/gc/z/zHeap.inline.hpp -+../../../src/hotspot/share/gc/z/zDriver.cpp -+../../../src/hotspot/share/gc/z/zMessagePort.inline.hpp -+../../../src/hotspot/share/gc/z/zPhysicalMemory.cpp -+../../../src/hotspot/share/gc/z/zPageTable.hpp -+../../../src/hotspot/share/gc/z/zRelocationSet.inline.hpp -+../../../src/hotspot/share/gc/z/zPage.inline.hpp -+../../../src/hotspot/share/gc/z/zUtils.inline.hpp -+../../../src/hotspot/share/gc/z/zMarkTerminate.hpp -+../../../src/hotspot/share/gc/z/zWeakRootsProcessor.hpp -+../../../src/hotspot/share/gc/z/zCollectedHeap.cpp -+../../../src/hotspot/share/gc/z/zRuntimeWorkers.cpp -+../../../src/hotspot/share/gc/z/zArray.inline.hpp -+../../../src/hotspot/share/gc/z/zBitField.hpp -+../../../src/hotspot/share/gc/z/zAddressRangeMap.hpp -+../../../src/hotspot/share/gc/z/zMarkStackEntry.hpp -+../../../src/hotspot/share/gc/z/vmStructs_z.hpp -+../../../src/hotspot/share/gc/z/zMarkStack.inline.hpp -+../../../src/hotspot/share/gc/z/zMark.hpp -+../../../src/hotspot/share/gc/z/zOopClosures.hpp -+../../../src/hotspot/share/gc/z/zTracer.inline.hpp -+../../../src/hotspot/share/gc/z/zBarrierSetAssembler.cpp -+../../../src/hotspot/share/gc/z/zPageAllocator.hpp -+../../../src/hotspot/share/gc/z/zServiceability.hpp -+../../../src/hotspot/share/gc/z/zPreMappedMemory.hpp -+../../../src/hotspot/share/gc/z/zMark.inline.hpp -+../../../src/hotspot/share/gc/z/zBarrierSetRuntime.hpp -+../../../src/hotspot/share/gc/z/zAddressRangeMap.inline.hpp -+../../../src/hotspot/share/gc/z/zOop.inline.hpp -+../../../src/hotspot/share/gc/z/zUtils.hpp -+../../../src/hotspot/share/gc/z/zPage.hpp -+../../../src/hotspot/share/gc/z/zObjectAllocator.cpp -+../../../src/hotspot/share/gc/z/zCPU.cpp -+../../../src/hotspot/share/gc/z/zNMethodTable.hpp -+../../../src/hotspot/share/gc/z/zMetronome.hpp -+../../../src/hotspot/share/gc/z/zHeap.hpp -+../../../src/hotspot/share/gc/z/zLiveMap.inline.hpp -+../../../src/hotspot/share/gc/z/zCollectorPolicy.cpp -+../../../src/hotspot/share/gc/z/zRelocationSetSelector.hpp -+../../../src/hotspot/share/gc/z/zWorkers.inline.hpp -+../../../src/hotspot/share/gc/z/zArguments.hpp -+../../../src/hotspot/share/gc/z/zForwardingTableEntry.hpp -+../../../src/hotspot/share/gc/z/zTask.cpp -+../../../src/hotspot/share/gc/z/zAddress.cpp -+../../../src/hotspot/share/gc/z/zErrno.cpp -+../../../src/hotspot/share/gc/z/zBarrierSet.inline.hpp -+../../../src/hotspot/share/gc/z/zResurrection.hpp -+../../../src/hotspot/share/gc/z/zVirtualMemory.hpp -+../../../src/hotspot/share/gc/z/zDirector.cpp -+../../../src/hotspot/share/gc/z/zNMethodTableEntry.hpp -+../../../src/hotspot/share/gc/z/zList.inline.hpp -+../../../src/hotspot/share/gc/z/zReferenceProcessor.cpp -+../../../src/hotspot/share/gc/z/zLargePages.hpp -+../../../src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp -+../../../src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp -+../../../src/hotspot/share/gc/z/zMarkStack.hpp -+../../../src/hotspot/share/gc/z/zThreadLocalData.hpp -+../../../src/hotspot/share/gc/z/zBitMap.hpp -+../../../src/hotspot/share/gc/z/zForwardingTable.hpp -+../../../src/hotspot/share/gc/z/zMarkCache.inline.hpp -+../../../src/hotspot/share/gc/z/zWorkers.cpp -+../../../src/hotspot/share/gc/z/zRootsIterator.cpp -+../../../src/hotspot/share/gc/z/zNUMA.cpp -+../../../src/hotspot/share/gc/z/zGlobals.hpp -+../../../src/hotspot/share/gc/z/zMemory.hpp -+../../../src/hotspot/share/gc/z/zLiveMap.hpp -+../../../src/hotspot/share/gc/z/zRelocationSet.cpp -+../../../src/hotspot/share/gc/z/zMarkTerminate.inline.hpp -+../../../src/hotspot/share/gc/z/zInitialize.hpp -+../../../src/hotspot/share/gc/z/zHeapIterator.hpp -+../../../src/hotspot/share/gc/z/zThread.hpp -+../../../src/hotspot/share/gc/z/zTracer.cpp -+../../../src/hotspot/share/gc/z/zMarkCache.cpp -+../../../src/hotspot/share/gc/z/zPageCache.cpp -+../../../src/hotspot/share/gc/z/zRelocate.cpp -+../../../src/hotspot/share/gc/z/zOop.hpp -+../../../src/hotspot/share/gc/shared/gcCause.cpp -+../../../src/hotspot/share/gc/shared/oopStorageParState.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessorStats.hpp -+../../../src/hotspot/share/gc/shared/plab.hpp -+../../../src/hotspot/share/gc/shared/gcConfiguration.cpp -+../../../src/hotspot/share/gc/shared/spaceDecorator.cpp -+../../../src/hotspot/share/gc/shared/gcPolicyCounters.hpp -+../../../src/hotspot/share/gc/shared/allocTracer.cpp -+../../../src/hotspot/share/gc/shared/gcTraceTime.inline.hpp -+../../../src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp -+../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp -+../../../src/hotspot/share/gc/shared/collectedHeap.cpp -+../../../src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp -+../../../src/hotspot/share/gc/shared/collectedHeap.inline.hpp -+../../../src/hotspot/share/gc/shared/ageTable.hpp -+../../../src/hotspot/share/gc/shared/blockOffsetTable.cpp -+../../../src/hotspot/share/gc/shared/hSpaceCounters.hpp -+../../../src/hotspot/share/gc/shared/space.inline.hpp -+../../../src/hotspot/share/gc/shared/collectorCounters.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessor.cpp -+../../../src/hotspot/share/gc/shared/accessBarrierSupport.cpp -+../../../src/hotspot/share/gc/shared/oopStorage.inline.hpp -+../../../src/hotspot/share/gc/shared/taskqueue.hpp -+../../../src/hotspot/share/gc/shared/gcTraceTime.hpp -+../../../src/hotspot/share/gc/shared/gcThreadLocalData.hpp -+../../../src/hotspot/share/gc/shared/gcTraceSend.cpp -+../../../src/hotspot/share/gc/shared/weakProcessor.cpp -+../../../src/hotspot/share/gc/shared/space.hpp -+../../../src/hotspot/share/gc/shared/cardTableRS.hpp -+../../../src/hotspot/share/gc/shared/objectCountEventSender.hpp -+../../../src/hotspot/share/gc/shared/generationSpec.cpp -+../../../src/hotspot/share/gc/shared/cardGeneration.hpp -+../../../src/hotspot/share/gc/shared/vmGCOperations.cpp -+../../../src/hotspot/share/gc/shared/softRefGenPolicy.cpp -+../../../src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp -+../../../src/hotspot/share/gc/shared/gcArguments.hpp -+../../../src/hotspot/share/gc/shared/workerDataArray.hpp -+../../../src/hotspot/share/gc/shared/suspendibleThreadSet.hpp -+../../../src/hotspot/share/gc/shared/collectorPolicy.cpp -+../../../src/hotspot/share/gc/shared/barrierSet.hpp -+../../../src/hotspot/share/gc/shared/genMemoryPools.hpp -+../../../src/hotspot/share/gc/shared/ageTableTracer.hpp -+../../../src/hotspot/share/gc/shared/workerDataArray.inline.hpp -+../../../src/hotspot/share/gc/shared/concurrentGCThread.hpp -+../../../src/hotspot/share/gc/shared/plab.inline.hpp -+../../../src/hotspot/share/gc/shared/cardTable.cpp -+../../../src/hotspot/share/gc/shared/softRefPolicy.cpp -+../../../src/hotspot/share/gc/shared/genCollectedHeap.cpp -+../../../src/hotspot/share/gc/shared/gcLocker.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessor.inline.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp -+../../../src/hotspot/share/gc/shared/preservedMarks.inline.hpp -+../../../src/hotspot/share/gc/shared/c1/barrierSetC1.hpp -+../../../src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.hpp -+../../../src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp -+../../../src/hotspot/share/gc/shared/c1/barrierSetC1.cpp -+../../../src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.hpp -+../../../src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp -+../../../src/hotspot/share/gc/shared/cardTableBarrierSet.hpp -+../../../src/hotspot/share/gc/shared/oopStorage.hpp -+../../../src/hotspot/share/gc/shared/gcConfig.cpp -+../../../src/hotspot/share/gc/shared/barrierSetAssembler.hpp -+../../../src/hotspot/share/gc/shared/modRefBarrierSet.hpp -+../../../src/hotspot/share/gc/shared/memAllocator.cpp -+../../../src/hotspot/share/gc/shared/referencePolicy.hpp -+../../../src/hotspot/share/gc/shared/gcTrace.hpp -+../../../src/hotspot/share/gc/shared/generationCounters.hpp -+../../../src/hotspot/share/gc/shared/strongRootsScope.hpp -+../../../src/hotspot/share/gc/shared/gcUtil.cpp -+../../../src/hotspot/share/gc/shared/generation.hpp -+../../../src/hotspot/share/gc/shared/concurrentGCPhaseManager.hpp -+../../../src/hotspot/share/gc/shared/gcId.cpp -+../../../src/hotspot/share/gc/shared/gcStats.hpp -+../../../src/hotspot/share/gc/shared/workgroup.cpp -+../../../src/hotspot/share/gc/shared/gcTimer.hpp -+../../../src/hotspot/share/gc/shared/preservedMarks.cpp -+../../../src/hotspot/share/gc/shared/referenceDiscoverer.hpp -+../../../src/hotspot/share/gc/shared/cardGeneration.cpp -+../../../src/hotspot/share/gc/shared/generationSpec.hpp -+../../../src/hotspot/share/gc/shared/vmGCOperations.hpp -+../../../src/hotspot/share/gc/shared/softRefGenPolicy.hpp -+../../../src/hotspot/share/gc/shared/collectorPolicy.hpp -+../../../src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp -+../../../src/hotspot/share/gc/shared/barrierSet.cpp -+../../../src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp -+../../../src/hotspot/share/gc/shared/suspendibleThreadSet.cpp -+../../../src/hotspot/share/gc/shared/workerDataArray.cpp -+../../../src/hotspot/share/gc/shared/gcArguments.cpp -+../../../src/hotspot/share/gc/shared/ageTableTracer.cpp -+../../../src/hotspot/share/gc/shared/isGCActiveMark.hpp -+../../../src/hotspot/share/gc/shared/genMemoryPools.cpp -+../../../src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupStat.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.cpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.inline.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.inline.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.inline.hpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp -+../../../src/hotspot/share/gc/shared/stringdedup/stringDedupQueue.hpp -+../../../src/hotspot/share/gc/shared/softRefPolicy.hpp -+../../../src/hotspot/share/gc/shared/oopStorageParState.inline.hpp -+../../../src/hotspot/share/gc/shared/genCollectedHeap.hpp -+../../../src/hotspot/share/gc/shared/concurrentGCThread.cpp -+../../../src/hotspot/share/gc/shared/cardTable.hpp -+../../../src/hotspot/share/gc/shared/vmStructs_gc.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp -+../../../src/hotspot/share/gc/shared/gcLocker.cpp -+../../../src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp -+../../../src/hotspot/share/gc/shared/barrierSetConfig.hpp -+../../../src/hotspot/share/gc/shared/cardTableBarrierSet.cpp -+../../../src/hotspot/share/gc/shared/oopStorage.cpp -+../../../src/hotspot/share/gc/shared/gcConfig.hpp -+../../../src/hotspot/share/gc/shared/genOopClosures.inline.hpp -+../../../src/hotspot/share/gc/shared/gcName.hpp -+../../../src/hotspot/share/gc/shared/referencePolicy.cpp -+../../../src/hotspot/share/gc/shared/gcArguments.inline.hpp -+../../../src/hotspot/share/gc/shared/memAllocator.hpp -+../../../src/hotspot/share/gc/shared/strongRootsScope.cpp -+../../../src/hotspot/share/gc/shared/generationCounters.cpp -+../../../src/hotspot/share/gc/shared/gcUtil.hpp -+../../../src/hotspot/share/gc/shared/gcTrace.cpp -+../../../src/hotspot/share/gc/shared/memset_with_concurrent_readers.hpp -+../../../src/hotspot/share/gc/shared/gcId.hpp -+../../../src/hotspot/share/gc/shared/gcStats.cpp -+../../../src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp -+../../../src/hotspot/share/gc/shared/workgroup.hpp -+../../../src/hotspot/share/gc/shared/generation.cpp -+../../../src/hotspot/share/gc/shared/cardGeneration.inline.hpp -+../../../src/hotspot/share/gc/shared/preservedMarks.hpp -+../../../src/hotspot/share/gc/shared/gcUtil.inline.hpp -+../../../src/hotspot/share/gc/shared/gcTimer.cpp -+../../../src/hotspot/share/gc/shared/gcCause.hpp -+../../../src/hotspot/share/gc/shared/plab.cpp -+../../../src/hotspot/share/gc/shared/genOopClosures.hpp -+../../../src/hotspot/share/gc/shared/ageTable.inline.hpp -+../../../src/hotspot/share/gc/shared/spaceDecorator.hpp -+../../../src/hotspot/share/gc/shared/barrierSet.inline.hpp -+../../../src/hotspot/share/gc/shared/gcConfiguration.hpp -+../../../src/hotspot/share/gc/shared/copyFailedInfo.hpp -+../../../src/hotspot/share/gc/shared/allocTracer.hpp -+../../../src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp -+../../../src/hotspot/share/gc/shared/workerManager.hpp -+../../../src/hotspot/share/gc/shared/gcPolicyCounters.cpp -+../../../src/hotspot/share/gc/shared/gcLocker.inline.hpp -+../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp -+../../../src/hotspot/share/gc/shared/taskqueue.inline.hpp -+../../../src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp -+../../../src/hotspot/share/gc/shared/c2/barrierSetC2.hpp -+../../../src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.hpp -+../../../src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp -+../../../src/hotspot/share/gc/shared/c2/barrierSetC2.cpp -+../../../src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.hpp -+../../../src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp -+../../../src/hotspot/share/gc/shared/collectedHeap.hpp -+../../../src/hotspot/share/gc/shared/ageTable.cpp -+../../../src/hotspot/share/gc/shared/gc_globals.hpp -+../../../src/hotspot/share/gc/shared/blockOffsetTable.hpp -+../../../src/hotspot/share/gc/shared/gcHeapSummary.hpp -+../../../src/hotspot/share/gc/shared/hSpaceCounters.cpp -+../../../src/hotspot/share/gc/shared/accessBarrierSupport.hpp -+../../../src/hotspot/share/gc/shared/referenceProcessor.hpp -+../../../src/hotspot/share/gc/shared/collectorCounters.cpp -+../../../src/hotspot/share/gc/shared/gcTraceTime.cpp -+../../../src/hotspot/share/gc/shared/taskqueue.cpp -+../../../src/hotspot/share/gc/shared/cardTableBarrierSetAssembler.hpp -+../../../src/hotspot/share/gc/shared/cardTableRS.cpp -+../../../src/hotspot/share/gc/shared/weakProcessor.hpp -+../../../src/hotspot/share/gc/shared/space.cpp -+../../../src/hotspot/share/gc/shared/accessBarrierSupport.inline.hpp -+../../../src/hotspot/share/gc/shared/gcWhen.hpp -+../../../src/hotspot/share/gc/shared/objectCountEventSender.cpp -+../../../src/hotspot/share/gc/shared/modRefBarrierSetAssembler.hpp -+../../../src/hotspot/share/gc/cms/concurrentMarkSweepThread.hpp -+../../../src/hotspot/share/gc/cms/gSpaceCounters.hpp -+../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp -+../../../src/hotspot/share/gc/cms/cmsGCStats.cpp -+../../../src/hotspot/share/gc/cms/cmsCardTable.cpp -+../../../src/hotspot/share/gc/cms/cmsOopClosures.hpp -+../../../src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.hpp -+../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp -+../../../src/hotspot/share/gc/cms/cmsHeap.inline.hpp -+../../../src/hotspot/share/gc/cms/vmCMSOperations.hpp -+../../../src/hotspot/share/gc/cms/cms_globals.hpp -+../../../src/hotspot/share/gc/cms/yieldingWorkgroup.hpp -+../../../src/hotspot/share/gc/cms/cmsHeap.hpp -+../../../src/hotspot/share/gc/cms/cmsArguments.cpp -+../../../src/hotspot/share/gc/cms/adaptiveFreeList.cpp -+../../../src/hotspot/share/gc/cms/promotionInfo.cpp -+../../../src/hotspot/share/gc/cms/parNewGeneration.cpp -+../../../src/hotspot/share/gc/cms/freeChunk.hpp -+../../../src/hotspot/share/gc/cms/cmsLockVerifier.cpp -+../../../src/hotspot/share/gc/cms/allocationStats.cpp -+../../../src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp -+../../../src/hotspot/share/gc/cms/parOopClosures.hpp -+../../../src/hotspot/share/gc/cms/vmCMSOperations.cpp -+../../../src/hotspot/share/gc/cms/yieldingWorkgroup.cpp -+../../../src/hotspot/share/gc/cms/cmsOopClosures.inline.hpp -+../../../src/hotspot/share/gc/cms/promotionInfo.inline.hpp -+../../../src/hotspot/share/gc/cms/cmsHeap.cpp -+../../../src/hotspot/share/gc/cms/cmsArguments.hpp -+../../../src/hotspot/share/gc/cms/adaptiveFreeList.hpp -+../../../src/hotspot/share/gc/cms/promotionInfo.hpp -+../../../src/hotspot/share/gc/cms/parOopClosures.inline.hpp -+../../../src/hotspot/share/gc/cms/parNewGeneration.hpp -+../../../src/hotspot/share/gc/cms/freeChunk.cpp -+../../../src/hotspot/share/gc/cms/cmsLockVerifier.hpp -+../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp -+../../../src/hotspot/share/gc/cms/vmStructs_cms.hpp -+../../../src/hotspot/share/gc/cms/cmsCollectorPolicy.hpp -+../../../src/hotspot/share/gc/cms/allocationStats.hpp -+../../../src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp -+../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp -+../../../src/hotspot/share/gc/cms/gSpaceCounters.cpp -+../../../src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp -+../../../src/hotspot/share/gc/cms/cmsGCStats.hpp -+../../../src/hotspot/share/gc/cms/cmsCardTable.hpp -+../../../src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp -+../../../src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp -+../../../src/hotspot/share/gc/cms/parNewGeneration.inline.hpp -+../../../src/hotspot/share/gc/serial/markSweep.cpp -+../../../src/hotspot/share/gc/serial/cSpaceCounters.hpp -+../../../src/hotspot/share/gc/serial/serialHeap.hpp -+../../../src/hotspot/share/gc/serial/tenuredGeneration.hpp -+../../../src/hotspot/share/gc/serial/genMarkSweep.cpp -+../../../src/hotspot/share/gc/serial/defNewGeneration.inline.hpp -+../../../src/hotspot/share/gc/serial/serialHeap.inline.hpp -+../../../src/hotspot/share/gc/serial/defNewGeneration.cpp -+../../../src/hotspot/share/gc/serial/serialArguments.cpp -+../../../src/hotspot/share/gc/serial/serial_globals.hpp -+../../../src/hotspot/share/gc/serial/tenuredGeneration.cpp -+../../../src/hotspot/share/gc/serial/genMarkSweep.hpp -+../../../src/hotspot/share/gc/serial/markSweep.inline.hpp -+../../../src/hotspot/share/gc/serial/defNewGeneration.hpp -+../../../src/hotspot/share/gc/serial/serialArguments.hpp -+../../../src/hotspot/share/gc/serial/markSweep.hpp -+../../../src/hotspot/share/gc/serial/vmStructs_serial.hpp -+../../../src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp -+../../../src/hotspot/share/gc/serial/cSpaceCounters.cpp -+../../../src/hotspot/share/gc/serial/serialHeap.cpp -+../../../src/hotspot/share/oops/objArrayKlass.inline.hpp -+../../../src/hotspot/share/oops/cpCache.inline.hpp -+../../../src/hotspot/share/oops/annotations.hpp -+../../../src/hotspot/share/oops/accessBackend.inline.hpp -+../../../src/hotspot/share/oops/typeArrayKlass.inline.hpp -+../../../src/hotspot/share/oops/compressedOops.inline.hpp -+../../../src/hotspot/share/oops/methodCounters.hpp -+../../../src/hotspot/share/oops/generateOopMap.cpp -+../../../src/hotspot/share/oops/access.hpp -+../../../src/hotspot/share/oops/symbol.cpp -+../../../src/hotspot/share/oops/arrayOop.inline.hpp -+../../../src/hotspot/share/oops/instanceOop.cpp -+../../../src/hotspot/share/oops/methodData.inline.hpp -+../../../src/hotspot/share/oops/instanceRefKlass.cpp -+../../../src/hotspot/share/oops/method.inline.hpp -+../../../src/hotspot/share/oops/arrayKlass.cpp -+../../../src/hotspot/share/oops/weakHandle.hpp -+../../../src/hotspot/share/oops/klass.hpp -+../../../src/hotspot/share/oops/constantPool.hpp -+../../../src/hotspot/share/oops/oopHandle.hpp -+../../../src/hotspot/share/oops/accessDecorators.hpp -+../../../src/hotspot/share/oops/instanceKlass.cpp -+../../../src/hotspot/share/oops/typeArrayOop.inline.hpp -+../../../src/hotspot/share/oops/instanceMirrorKlass.hpp -+../../../src/hotspot/share/oops/objArrayKlass.hpp -+../../../src/hotspot/share/oops/array.hpp -+../../../src/hotspot/share/oops/typeArrayKlass.hpp -+../../../src/hotspot/share/oops/oopHandle.inline.hpp -+../../../src/hotspot/share/oops/accessBackend.hpp -+../../../src/hotspot/share/oops/oop.cpp -+../../../src/hotspot/share/oops/cpCache.hpp -+../../../src/hotspot/share/oops/compiledICHolder.hpp -+../../../src/hotspot/share/oops/fieldInfo.hpp -+../../../src/hotspot/share/oops/reflectionAccessorImplKlassHelper.hpp -+../../../src/hotspot/share/oops/verifyOopClosure.hpp -+../../../src/hotspot/share/oops/markOop.hpp -+../../../src/hotspot/share/oops/methodData.hpp -+../../../src/hotspot/share/oops/markOop.inline.hpp -+../../../src/hotspot/share/oops/objArrayOop.hpp -+../../../src/hotspot/share/oops/constMethod.cpp -+../../../src/hotspot/share/oops/klassVtable.hpp -+../../../src/hotspot/share/oops/instanceMirrorKlass.inline.hpp -+../../../src/hotspot/share/oops/oopsHierarchy.hpp -+../../../src/hotspot/share/oops/metadata.hpp -+../../../src/hotspot/share/oops/fieldStreams.hpp -+../../../src/hotspot/share/oops/method.hpp -+../../../src/hotspot/share/oops/objArrayKlass.cpp -+../../../src/hotspot/share/oops/instanceMirrorKlass.cpp -+../../../src/hotspot/share/oops/typeArrayKlass.cpp -+../../../src/hotspot/share/oops/accessBackend.cpp -+../../../src/hotspot/share/oops/oop.hpp -+../../../src/hotspot/share/oops/weakHandle.inline.hpp -+../../../src/hotspot/share/oops/cpCache.cpp -+../../../src/hotspot/share/oops/objArrayOop.inline.hpp -+../../../src/hotspot/share/oops/compiledICHolder.cpp -+../../../src/hotspot/share/oops/reflectionAccessorImplKlassHelper.cpp -+../../../src/hotspot/share/oops/klass.inline.hpp -+../../../src/hotspot/share/oops/markOop.cpp -+../../../src/hotspot/share/oops/instanceKlass.inline.hpp -+../../../src/hotspot/share/oops/methodData.cpp -+../../../src/hotspot/share/oops/objArrayOop.cpp -+../../../src/hotspot/share/oops/constMethod.hpp -+../../../src/hotspot/share/oops/oop.inline.hpp -+../../../src/hotspot/share/oops/klassVtable.cpp -+../../../src/hotspot/share/oops/method.cpp -+../../../src/hotspot/share/oops/oopsHierarchy.cpp -+../../../src/hotspot/share/oops/metadata.cpp -+../../../src/hotspot/share/oops/arrayKlass.inline.hpp -+../../../src/hotspot/share/oops/typeArrayOop.hpp -+../../../src/hotspot/share/oops/instanceRefKlass.inline.hpp -+../../../src/hotspot/share/oops/arrayOop.hpp -+../../../src/hotspot/share/oops/annotations.cpp -+../../../src/hotspot/share/oops/methodCounters.cpp -+../../../src/hotspot/share/oops/generateOopMap.hpp -+../../../src/hotspot/share/oops/symbol.hpp -+../../../src/hotspot/share/oops/instanceClassLoaderKlass.hpp -+../../../src/hotspot/share/oops/access.cpp -+../../../src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp -+../../../src/hotspot/share/oops/instanceOop.hpp -+../../../src/hotspot/share/oops/arrayKlass.hpp -+../../../src/hotspot/share/oops/weakHandle.cpp -+../../../src/hotspot/share/oops/constantPool.inline.hpp -+../../../src/hotspot/share/oops/instanceRefKlass.hpp -+../../../src/hotspot/share/oops/klass.cpp -+../../../src/hotspot/share/oops/array.inline.hpp -+../../../src/hotspot/share/oops/constantPool.cpp -+../../../src/hotspot/share/oops/access.inline.hpp -+../../../src/hotspot/share/oops/instanceKlass.hpp -+../../../src/hotspot/share/opto/ad.hpp -+../../../src/hotspot/share/opto/ifnode.cpp -+../../../src/hotspot/share/opto/phase.cpp -+../../../src/hotspot/share/opto/parseHelper.cpp -+../../../src/hotspot/share/opto/callGenerator.cpp -+../../../src/hotspot/share/opto/c2_globals.hpp -+../../../src/hotspot/share/opto/replacednodes.hpp -+../../../src/hotspot/share/opto/runtime.hpp -+../../../src/hotspot/share/opto/chaitin.hpp -+../../../src/hotspot/share/opto/subnode.hpp -+../../../src/hotspot/share/opto/divnode.hpp -+../../../src/hotspot/share/opto/intrinsicnode.cpp -+../../../src/hotspot/share/opto/multnode.cpp -+../../../src/hotspot/share/opto/live.cpp -+../../../src/hotspot/share/opto/macro.cpp -+../../../src/hotspot/share/opto/phaseX.hpp -+../../../src/hotspot/share/opto/convertnode.cpp -+../../../src/hotspot/share/opto/addnode.hpp -+../../../src/hotspot/share/opto/graphKit.hpp -+../../../src/hotspot/share/opto/type.hpp -+../../../src/hotspot/share/opto/connode.cpp -+../../../src/hotspot/share/opto/vectornode.cpp -+../../../src/hotspot/share/opto/regmask.hpp -+../../../src/hotspot/share/opto/escape.cpp -+../../../src/hotspot/share/opto/coalesce.cpp -+../../../src/hotspot/share/opto/matcher.cpp -+../../../src/hotspot/share/opto/cfgnode.hpp -+../../../src/hotspot/share/opto/opaquenode.cpp -+../../../src/hotspot/share/opto/classes.hpp -+../../../src/hotspot/share/opto/idealGraphPrinter.cpp -+../../../src/hotspot/share/opto/loopPredicate.cpp -+../../../src/hotspot/share/opto/mathexactnode.cpp -+../../../src/hotspot/share/opto/loopTransform.cpp -+../../../src/hotspot/share/opto/callnode.cpp -+../../../src/hotspot/share/opto/doCall.cpp -+../../../src/hotspot/share/opto/block.cpp -+../../../src/hotspot/share/opto/gcm.cpp -+../../../src/hotspot/share/opto/locknode.hpp -+../../../src/hotspot/share/opto/movenode.hpp -+../../../src/hotspot/share/opto/node.cpp -+../../../src/hotspot/share/opto/regalloc.cpp -+../../../src/hotspot/share/opto/countbitsnode.cpp -+../../../src/hotspot/share/opto/indexSet.cpp -+../../../src/hotspot/share/opto/stringopts.hpp -+../../../src/hotspot/share/opto/compile.hpp -+../../../src/hotspot/share/opto/opcodes.hpp -+../../../src/hotspot/share/opto/phasetype.hpp -+../../../src/hotspot/share/opto/mulnode.cpp -+../../../src/hotspot/share/opto/narrowptrnode.cpp -+../../../src/hotspot/share/opto/superword.hpp -+../../../src/hotspot/share/opto/memnode.hpp -+../../../src/hotspot/share/opto/rootnode.hpp -+../../../src/hotspot/share/opto/castnode.hpp -+../../../src/hotspot/share/opto/loopnode.cpp -+../../../src/hotspot/share/opto/loopopts.cpp -+../../../src/hotspot/share/opto/arraycopynode.cpp -+../../../src/hotspot/share/opto/c2compiler.hpp -+../../../src/hotspot/share/opto/idealKit.hpp -+../../../src/hotspot/share/opto/output.cpp -+../../../src/hotspot/share/opto/machnode.hpp -+../../../src/hotspot/share/opto/generateOptoStub.cpp -+../../../src/hotspot/share/opto/split_if.cpp -+../../../src/hotspot/share/opto/reg_split.cpp -+../../../src/hotspot/share/opto/matcher.hpp -+../../../src/hotspot/share/opto/idealGraphPrinter.hpp -+../../../src/hotspot/share/opto/mathexactnode.hpp -+../../../src/hotspot/share/opto/opaquenode.hpp -+../../../src/hotspot/share/opto/cfgnode.cpp -+../../../src/hotspot/share/opto/classes.cpp -+../../../src/hotspot/share/opto/callnode.hpp -+../../../src/hotspot/share/opto/block.hpp -+../../../src/hotspot/share/opto/node.hpp -+../../../src/hotspot/share/opto/movenode.cpp -+../../../src/hotspot/share/opto/regalloc.hpp -+../../../src/hotspot/share/opto/locknode.cpp -+../../../src/hotspot/share/opto/countbitsnode.hpp -+../../../src/hotspot/share/opto/stringopts.cpp -+../../../src/hotspot/share/opto/compile.cpp -+../../../src/hotspot/share/opto/indexSet.hpp -+../../../src/hotspot/share/opto/opcodes.cpp -+../../../src/hotspot/share/opto/narrowptrnode.hpp -+../../../src/hotspot/share/opto/mulnode.hpp -+../../../src/hotspot/share/opto/memnode.cpp -+../../../src/hotspot/share/opto/rootnode.cpp -+../../../src/hotspot/share/opto/superword.cpp -+../../../src/hotspot/share/opto/loopnode.hpp -+../../../src/hotspot/share/opto/castnode.cpp -+../../../src/hotspot/share/opto/adlcVMDeps.hpp -+../../../src/hotspot/share/opto/arraycopynode.hpp -+../../../src/hotspot/share/opto/c2compiler.cpp -+../../../src/hotspot/share/opto/machnode.cpp -+../../../src/hotspot/share/opto/output.hpp -+../../../src/hotspot/share/opto/optoreg.hpp -+../../../src/hotspot/share/opto/idealKit.cpp -+../../../src/hotspot/share/opto/ifg.cpp -+../../../src/hotspot/share/opto/phase.hpp -+../../../src/hotspot/share/opto/c2_globals.cpp -+../../../src/hotspot/share/opto/callGenerator.hpp -+../../../src/hotspot/share/opto/domgraph.cpp -+../../../src/hotspot/share/opto/macroArrayCopy.cpp -+../../../src/hotspot/share/opto/replacednodes.cpp -+../../../src/hotspot/share/opto/postaloc.cpp -+../../../src/hotspot/share/opto/lcm.cpp -+../../../src/hotspot/share/opto/runtime.cpp -+../../../src/hotspot/share/opto/subnode.cpp -+../../../src/hotspot/share/opto/chaitin.cpp -+../../../src/hotspot/share/opto/intrinsicnode.hpp -+../../../src/hotspot/share/opto/multnode.hpp -+../../../src/hotspot/share/opto/loopUnswitch.cpp -+../../../src/hotspot/share/opto/divnode.cpp -+../../../src/hotspot/share/opto/buildOopMap.cpp -+../../../src/hotspot/share/opto/convertnode.hpp -+../../../src/hotspot/share/opto/live.hpp -+../../../src/hotspot/share/opto/macro.hpp -+../../../src/hotspot/share/opto/parse2.cpp -+../../../src/hotspot/share/opto/bytecodeInfo.cpp -+../../../src/hotspot/share/opto/phaseX.cpp -+../../../src/hotspot/share/opto/parse3.cpp -+../../../src/hotspot/share/opto/addnode.cpp -+../../../src/hotspot/share/opto/parse.hpp -+../../../src/hotspot/share/opto/connode.hpp -+../../../src/hotspot/share/opto/type.cpp -+../../../src/hotspot/share/opto/graphKit.cpp -+../../../src/hotspot/share/opto/parse1.cpp -+../../../src/hotspot/share/opto/vectornode.hpp -+../../../src/hotspot/share/opto/coalesce.hpp -+../../../src/hotspot/share/opto/library_call.cpp -+../../../src/hotspot/share/opto/escape.hpp -+../../../src/hotspot/share/opto/regmask.cpp -+../../../src/hotspot/share/precompiled/precompiled.hpp -+../../../src/hotspot/share/compiler/abstractCompiler.cpp -+../../../src/hotspot/share/compiler/compilerDefinitions.cpp -+../../../src/hotspot/share/compiler/methodMatcher.cpp -+../../../src/hotspot/share/compiler/compilerOracle.cpp -+../../../src/hotspot/share/compiler/compileTask.hpp -+../../../src/hotspot/share/compiler/disassembler.cpp -+../../../src/hotspot/share/compiler/oopMap.hpp -+../../../src/hotspot/share/compiler/compileLog.hpp -+../../../src/hotspot/share/compiler/directivesParser.hpp -+../../../src/hotspot/share/compiler/compileBroker.cpp -+../../../src/hotspot/share/compiler/compilerDirectives.cpp -+../../../src/hotspot/share/compiler/methodLiveness.cpp -+../../../src/hotspot/share/compiler/oopMap.cpp -+../../../src/hotspot/share/compiler/compileLog.cpp -+../../../src/hotspot/share/compiler/directivesParser.cpp -+../../../src/hotspot/share/compiler/compileBroker.hpp -+../../../src/hotspot/share/compiler/compilerDirectives.hpp -+../../../src/hotspot/share/compiler/methodLiveness.hpp -+../../../src/hotspot/share/compiler/compilerDefinitions.hpp -+../../../src/hotspot/share/compiler/abstractCompiler.hpp -+../../../src/hotspot/share/compiler/methodMatcher.hpp -+../../../src/hotspot/share/compiler/compilerOracle.hpp -+../../../src/hotspot/share/compiler/compileTask.cpp -+../../../src/hotspot/share/compiler/disassembler.hpp -+../../../src/hotspot/share/logging/logTagSet.cpp -+../../../src/hotspot/share/logging/logOutput.hpp -+../../../src/hotspot/share/logging/logDecorations.hpp -+../../../src/hotspot/share/logging/logFileStreamOutput.hpp -+../../../src/hotspot/share/logging/logOutputList.hpp -+../../../src/hotspot/share/logging/logSelection.cpp -+../../../src/hotspot/share/logging/logLevel.hpp -+../../../src/hotspot/share/logging/logStream.cpp -+../../../src/hotspot/share/logging/logConfiguration.hpp -+../../../src/hotspot/share/logging/logTag.hpp -+../../../src/hotspot/share/logging/logDecorators.cpp -+../../../src/hotspot/share/logging/logMessage.hpp -+../../../src/hotspot/share/logging/logTagSetDescriptions.hpp -+../../../src/hotspot/share/logging/logSelectionList.hpp -+../../../src/hotspot/share/logging/logFileOutput.cpp -+../../../src/hotspot/share/logging/logMessageBuffer.hpp -+../../../src/hotspot/share/logging/logDiagnosticCommand.hpp -+../../../src/hotspot/share/logging/logTag.cpp -+../../../src/hotspot/share/logging/logConfiguration.cpp -+../../../src/hotspot/share/logging/logDecorators.hpp -+../../../src/hotspot/share/logging/logPrefix.hpp -+../../../src/hotspot/share/logging/logTagSetDescriptions.cpp -+../../../src/hotspot/share/logging/logMessageBuffer.cpp -+../../../src/hotspot/share/logging/logSelectionList.cpp -+../../../src/hotspot/share/logging/logFileOutput.hpp -+../../../src/hotspot/share/logging/logDiagnosticCommand.cpp -+../../../src/hotspot/share/logging/logHandle.hpp -+../../../src/hotspot/share/logging/logTagSet.hpp -+../../../src/hotspot/share/logging/log.hpp -+../../../src/hotspot/share/logging/logOutput.cpp -+../../../src/hotspot/share/logging/logFileStreamOutput.cpp -+../../../src/hotspot/share/logging/logDecorations.cpp -+../../../src/hotspot/share/logging/logOutputList.cpp -+../../../src/hotspot/share/logging/logTag_ext.hpp -+../../../src/hotspot/share/logging/logSelection.hpp -+../../../src/hotspot/share/logging/logLevel.cpp -+../../../src/hotspot/share/logging/logStream.hpp -+../../../src/hotspot/share/services/gcNotifier.cpp -+../../../src/hotspot/share/services/memBaseline.cpp -+../../../src/hotspot/share/services/heapDumper.hpp -+../../../src/hotspot/share/services/memoryPool.hpp -+../../../src/hotspot/share/services/nmtCommon.cpp -+../../../src/hotspot/share/services/mallocTracker.hpp -+../../../src/hotspot/share/services/nmtDCmd.cpp -+../../../src/hotspot/share/services/diagnosticCommand.cpp -+../../../src/hotspot/share/services/lowMemoryDetector.cpp -+../../../src/hotspot/share/services/writeableFlags.cpp -+../../../src/hotspot/share/services/threadService.cpp -+../../../src/hotspot/share/services/runtimeService.cpp -+../../../src/hotspot/share/services/attachListener.hpp -+../../../src/hotspot/share/services/memoryService.cpp -+../../../src/hotspot/share/services/memoryManager.hpp -+../../../src/hotspot/share/services/management.hpp -+../../../src/hotspot/share/services/memReporter.hpp -+../../../src/hotspot/share/services/memTracker.hpp -+../../../src/hotspot/share/services/allocationSite.hpp -+../../../src/hotspot/share/services/classLoadingService.cpp -+../../../src/hotspot/share/services/virtualMemoryTracker.hpp -+../../../src/hotspot/share/services/mallocSiteTable.cpp -+../../../src/hotspot/share/services/dtraceAttacher.hpp -+../../../src/hotspot/share/services/diagnosticArgument.cpp -+../../../src/hotspot/share/services/diagnosticFramework.hpp -+../../../src/hotspot/share/services/runtimeService.hpp -+../../../src/hotspot/share/services/threadService.hpp -+../../../src/hotspot/share/services/memoryService.hpp -+../../../src/hotspot/share/services/attachListener.cpp -+../../../src/hotspot/share/services/mallocTracker.inline.hpp -+../../../src/hotspot/share/services/memTracker.cpp -+../../../src/hotspot/share/services/management.cpp -+../../../src/hotspot/share/services/memReporter.cpp -+../../../src/hotspot/share/services/memoryManager.cpp -+../../../src/hotspot/share/services/classLoadingService.hpp -+../../../src/hotspot/share/services/memoryUsage.hpp -+../../../src/hotspot/share/services/dtraceAttacher.cpp -+../../../src/hotspot/share/services/mallocSiteTable.hpp -+../../../src/hotspot/share/services/virtualMemoryTracker.cpp -+../../../src/hotspot/share/services/diagnosticFramework.cpp -+../../../src/hotspot/share/services/diagnosticArgument.hpp -+../../../src/hotspot/share/services/gcNotifier.hpp -+../../../src/hotspot/share/services/memBaseline.hpp -+../../../src/hotspot/share/services/heapDumper.cpp -+../../../src/hotspot/share/services/memoryPool.cpp -+../../../src/hotspot/share/services/nmtCommon.hpp -+../../../src/hotspot/share/services/mallocTracker.cpp -+../../../src/hotspot/share/services/nmtDCmd.hpp -+../../../src/hotspot/share/services/lowMemoryDetector.hpp -+../../../src/hotspot/share/services/diagnosticCommand.hpp -+../../../src/hotspot/share/services/writeableFlags.hpp -+../../../src/hotspot/share/services/diagnosticCommand_ext.hpp -+../../../src/hotspot/share/aot/aotCodeHeap.cpp -+../../../src/hotspot/share/aot/aotCompiledMethod.cpp -+../../../src/hotspot/share/aot/aotLoader.hpp -+../../../src/hotspot/share/aot/compiledIC_aot.hpp -+../../../src/hotspot/share/aot/compiledIC_aot.cpp -+../../../src/hotspot/share/aot/aotCompiledMethod.hpp -+../../../src/hotspot/share/aot/aotCodeHeap.hpp -+../../../src/hotspot/share/aot/aotLoader.cpp -+../../../src/hotspot/share/aot/aotLoader.inline.hpp -+../../../src/hotspot/share/jvmci/vmStructs_jvmci.hpp -+../../../src/hotspot/share/jvmci/compilerRuntime.cpp -+../../../src/hotspot/share/jvmci/jvmciCodeInstaller.hpp -+../../../src/hotspot/share/jvmci/jvmci_globals.cpp -+../../../src/hotspot/share/jvmci/systemDictionary_jvmci.hpp -+../../../src/hotspot/share/jvmci/jvmciJavaClasses.hpp -+../../../src/hotspot/share/jvmci/jvmciRuntime.cpp -+../../../src/hotspot/share/jvmci/jvmciEnv.hpp -+../../../src/hotspot/share/jvmci/jvmciCompiler.cpp -+../../../src/hotspot/share/jvmci/vmSymbols_jvmci.hpp -+../../../src/hotspot/share/jvmci/jvmciCompilerToVM.hpp -+../../../src/hotspot/share/jvmci/jvmciEnv.cpp -+../../../src/hotspot/share/jvmci/jvmciCompiler.hpp -+../../../src/hotspot/share/jvmci/jvmciCompilerToVM.cpp -+../../../src/hotspot/share/jvmci/vmStructs_jvmci.cpp -+../../../src/hotspot/share/jvmci/compilerRuntime.hpp -+../../../src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp -+../../../src/hotspot/share/jvmci/jvmciCodeInstaller.cpp -+../../../src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp -+../../../src/hotspot/share/jvmci/jvmci_globals.hpp -+../../../src/hotspot/share/jvmci/jvmciJavaClasses.cpp -+../../../src/hotspot/share/jvmci/jvmciRuntime.hpp) -+ -+add_executable(hotspot ${SOURCE_FILES}) --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch b/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch deleted file mode 100644 index 49c840624d52..000000000000 --- a/jb/project/tools/patches/dcevm/0012-Set-HOTSPOT_VM_DISTRO-Dynamic-Code-Evolution.patch +++ /dev/null @@ -1,25 +0,0 @@ -From d56e73885111b386771f564ec6beb305338993df Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Mon, 19 Oct 2020 20:00:04 +0200 -Subject: [PATCH 12/34] Set HOTSPOT_VM_DISTRO=Dynamic Code Evolution - ---- - make/autoconf/version-numbers | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers -index aabdc5bed20..df8025a2e84 100644 ---- a/make/autoconf/version-numbers -+++ b/make/autoconf/version-numbers -@@ -45,7 +45,7 @@ PRODUCT_NAME=OpenJDK - PRODUCT_SUFFIX="Runtime Environment" - JDK_RC_PLATFORM_NAME=Platform - COMPANY_NAME=N/A --HOTSPOT_VM_DISTRO="OpenJDK" -+HOTSPOT_VM_DISTRO="Dynamic Code Evolution" - VENDOR_URL=https://openjdk.java.net/ - VENDOR_URL_BUG=https://bugreport.java.com/bugreport/ - VENDOR_URL_VM_BUG=https://bugreport.java.com/bugreport/crash.jsp --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch b/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch deleted file mode 100644 index 3c2bcd50a96d..000000000000 --- a/jb/project/tools/patches/dcevm/0013-Fix-G1-nmethod-registration.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 7ebad43ed45805b0a3736c510f708ff17697ba7e Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 11 Oct 2020 10:43:28 +0200 -Subject: [PATCH 13/34] Fix G1 nmethod registration - ---- - .../prims/jvmtiEnhancedRedefineClasses.cpp | 19 ++++++++++++++++--- - .../prims/jvmtiEnhancedRedefineClasses.hpp | 3 ++- - 2 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index b09ba554e07..718426f2819 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -216,7 +216,14 @@ void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { - } - } - --void VM_EnhancedRedefineClasses::mark_as_scavengable_g1(nmethod* nm) { -+void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { -+ // It should work not only for G1 but also for another GCs, but this way is safer now -+ if (!nm->is_zombie() && !nm->is_unloaded()) { -+ Universe::heap()->unregister_nmethod(nm); -+ } -+} -+ -+void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) { - // It should work not only for G1 but also for another GCs, but this way is safer now - if (!nm->is_zombie() && !nm->is_unloaded()) { - Universe::heap()->register_nmethod(nm); -@@ -521,8 +528,9 @@ void VM_EnhancedRedefineClasses::doit() { - // For now, mark all nmethod's as scavengable that are not scavengable already - if (ScavengeRootsInCode) { - if (UseG1GC) { -- // this should work also for other GCs -- CodeCache::nmethods_do(mark_as_scavengable_g1); -+ // G1 holds references to nmethods in regions based on oops values. Since oops in nmethod can be changed in ChangePointers* closures -+ // we unregister nmethods from G1 heap, then closures are processed (oops are changed) and finally we register nmethod to G1 again -+ CodeCache::nmethods_do(unregister_nmethod_g1); - } else { - CodeCache::nmethods_do(mark_as_scavengable); - } -@@ -545,6 +553,11 @@ void VM_EnhancedRedefineClasses::doit() { - - Universe::root_oops_do(&oopClosureNoBarrier); - -+ if (UseG1GC) { -+ // this should work also for other GCs -+ CodeCache::nmethods_do(register_nmethod_g1); -+ } -+ - } - log_trace(redefine, class, obsolete, metadata)("After updating instances"); - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index 9755944d70b..4c0412d343d 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -116,7 +116,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - - void rollback(); - static void mark_as_scavengable(nmethod* nm); -- static void mark_as_scavengable_g1(nmethod* nm); -+ static void unregister_nmethod_g1(nmethod* nm); -+ static void register_nmethod_g1(nmethod* nm); - static void unpatch_bytecode(Method* method); - static void fix_invoke_method(Method* method); - --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch b/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch deleted file mode 100644 index 1741c6091bd5..000000000000 --- a/jb/project/tools/patches/dcevm/0014-Initialize-method-s-_new_version-_old_version-to-NUL.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 5c7e5f245f79d7e8575461dab0c356ed74c8e9a3 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Thu, 22 Oct 2020 20:15:20 +0200 -Subject: [PATCH 14/34] Initialize method's _new_version/_old_version to NULL - ---- - src/hotspot/share/oops/method.cpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp -index 1c88511a5fc..ce940cf10a9 100644 ---- a/src/hotspot/share/oops/method.cpp -+++ b/src/hotspot/share/oops/method.cpp -@@ -91,7 +91,8 @@ Method* Method::allocate(ClassLoaderData* loader_data, - return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags); - } - --Method::Method(ConstMethod* xconst, AccessFlags access_flags) { -+Method::Method(ConstMethod* xconst, AccessFlags access_flags) : _new_version(NULL), -+ _old_version(NULL) { - NoSafepointVerifier no_safepoint; - set_constMethod(xconst); - set_access_flags(access_flags); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch b/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch deleted file mode 100644 index 72144d85d8f6..000000000000 --- a/jb/project/tools/patches/dcevm/0015-Clear-dcevm-code-separation.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 6ffac6e5064ec6633fdbeb8520333dca00bc6a62 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Fri, 23 Oct 2020 10:20:26 +0200 -Subject: [PATCH 15/34] Clear dcevm code separation - ---- - src/hotspot/share/classfile/systemDictionary.cpp | 4 ++-- - src/hotspot/share/gc/serial/genMarkSweep.cpp | 8 +++++--- - src/hotspot/share/interpreter/linkResolver.cpp | 16 +++++++++++----- - .../instrumentation/jfrEventClassTransformer.cpp | 2 +- - src/hotspot/share/oops/instanceKlass.cpp | 10 ++++++---- - src/hotspot/share/oops/method.cpp | 2 +- - .../share/prims/jvmtiGetLoadedClasses.cpp | 2 +- - src/hotspot/share/runtime/reflection.cpp | 2 +- - 8 files changed, 28 insertions(+), 18 deletions(-) - -diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp -index 8f2b46add4d..9ac6ec96cb5 100644 ---- a/src/hotspot/share/classfile/systemDictionary.cpp -+++ b/src/hotspot/share/classfile/systemDictionary.cpp -@@ -1241,7 +1241,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, - MutexLocker mu(THREAD, SystemDictionary_lock); - - Klass* check = find_class(h_name, k->class_loader_data()); -- assert((check == k && !k->is_redefining()) || (k->is_redefining() && check == k->old_version()), "should be present in the dictionary"); -+ assert(check == k && !k->is_redefining() || k->is_redefining() && check == k->old_version(), "should be present in the dictionary"); - } ); - - return k; -@@ -2290,7 +2290,7 @@ void SystemDictionary::check_constraints(unsigned int d_hash, - // also hold array classes. - - assert(check->is_instance_klass(), "noninstance in systemdictionary"); -- if ((defining == true) || ((k != check) && k->old_version() != check)) { -+ if ((defining == true) || (k != check && (!AllowEnhancedClassRedefinition || k->old_version() != check))) { - throwException = true; - ss.print("loader %s", loader_data->loader_name_and_id()); - ss.print(" attempted duplicate %s definition for %s. (%s)", -diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp -index 1d13c647452..548df01e557 100644 ---- a/src/hotspot/share/gc/serial/genMarkSweep.cpp -+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp -@@ -334,7 +334,9 @@ void GenMarkSweep::mark_sweep_phase4() { - - GenCompactClosure blk; - gch->generation_iterate(&blk, true); -- DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); -- DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); -- MarkSweep::_rescued_oops = NULL; -+ if (AllowEnhancedClassRedefinition) { -+ DcevmSharedGC::copy_rescued_objects_back(MarkSweep::_rescued_oops, true); -+ DcevmSharedGC::clear_rescued_objects_resource(MarkSweep::_rescued_oops); -+ MarkSweep::_rescued_oops = NULL; -+ } - } -diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp -index b6e9e0a308d..b2f24ddbeda 100644 ---- a/src/hotspot/share/interpreter/linkResolver.cpp -+++ b/src/hotspot/share/interpreter/linkResolver.cpp -@@ -282,9 +282,14 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass, - if (!base_klass->is_instance_klass()) { - return; // no relevant check to do - } -- -- Reflection::VerifyClassAccessResults vca_result = -- Reflection::verify_class_access(ref_klass->newest_version(), InstanceKlass::cast(base_klass->newest_version()), true); -+ Klass* refKlassNewest = ref_klass; -+ Klass* baseKlassNewest = base_klass; -+ if (AllowEnhancedClassRedefinition) { -+ refKlassNewest = ref_klass->newest_version(); -+ baseKlassNewest = base_klass->newest_version(); -+ } -+ Reflection::VerifyClassAccessResults vca_result = -+ Reflection::verify_class_access(refKlassNewest, InstanceKlass::cast(baseKlassNewest), true); - if (vca_result != Reflection::ACCESS_OK) { - ResourceMark rm(THREAD); - char* msg = Reflection::verify_class_access_msg(ref_klass, -@@ -566,7 +571,8 @@ void LinkResolver::check_method_accessability(Klass* ref_klass, - // We'll check for the method name first, as that's most likely - // to be false (so we'll short-circuit out of these tests). - if (sel_method->name() == vmSymbols::clone_name() && -- sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version() && -+ ( !AllowEnhancedClassRedefinition && sel_klass == SystemDictionary::Object_klass() || -+ AllowEnhancedClassRedefinition && sel_klass->newest_version() == SystemDictionary::Object_klass()->newest_version()) && - resolved_klass->is_array_klass()) { - // We need to change "protected" to "public". - assert(flags.is_protected(), "clone not protected?"); -@@ -1011,7 +1017,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, - // or by the method (in case of an instance field). - if (is_put && fd.access_flags().is_final()) { - -- if (sel_klass != current_klass && sel_klass != current_klass->active_version()) { -+ if (sel_klass != current_klass && (!AllowEnhancedClassRedefinition || sel_klass != current_klass->active_version())) { - ResourceMark rm(THREAD); - stringStream ss; - ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", -diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -index 96fc139bea3..f7284197c5a 100644 ---- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -+++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp -@@ -1471,7 +1471,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre - cld, - &cl_info, - ClassFileParser::INTERNAL, // internal visibility -- false, -+ false, - THREAD); - if (HAS_PENDING_EXCEPTION) { - log_pending_exception(PENDING_EXCEPTION); -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index 3be3a09ef8f..f8e60941046 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -199,7 +199,9 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { - // able to perform that loading but we can't exclude the compiler threads from - // executing this logic. But it should actually be impossible to trigger loading here. - Klass* k2 = _constants->klass_at(cp_index, THREAD); -- k2 = k2->newest_version(); -+ if (AllowEnhancedClassRedefinition) { -+ k2 = k2->newest_version(); -+ } - assert(!HAS_PENDING_EXCEPTION || PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass()), - "Exceptions should not be possible here"); - if (k2 == k) { -@@ -1003,7 +1005,7 @@ bool InstanceKlass::link_class_impl(TRAPS) { - #endif - set_init_state(linked); - // (DCEVM) Must check for old version in order to prevent infinite loops. -- if (JvmtiExport::should_post_class_prepare() && old_version() == NULL /* JVMTI deadlock otherwise */) { -+ if (JvmtiExport::should_post_class_prepare() && (!AllowEnhancedClassRedefinition || old_version() == NULL) /* JVMTI deadlock otherwise */) { - Thread *thread = THREAD; - assert(thread->is_Java_thread(), "thread->is_Java_thread()"); - JvmtiExport::post_class_prepare((JavaThread *) thread, this); -@@ -1084,7 +1086,7 @@ void InstanceKlass::initialize_impl(TRAPS) { - // we might end up throwing IE from link/symbol resolution sites - // that aren't expected to throw. This would wreak havoc. See 6320309. - while ((is_being_initialized() && !is_reentrant_initialization(jt)) -- || (old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { -+ || (AllowEnhancedClassRedefinition && old_version() != NULL && InstanceKlass::cast(old_version())->is_being_initialized())) { - wait = true; - jt->set_class_to_be_initialized(this); - ol.wait_uninterruptibly(jt); -@@ -3782,7 +3784,7 @@ void InstanceKlass::verify_on(outputStream* st) { - - guarantee(sib->is_klass(), "should be klass"); - // TODO: (DCEVM) explain -- guarantee(sib->super() == super || super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); -+ guarantee(sib->super() == super || AllowEnhancedClassRedefinition && super->newest_version() == SystemDictionary::Object_klass(), "siblings should have same superklass"); - } - - // Verify local interfaces -diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp -index ce940cf10a9..2d8e5b0256b 100644 ---- a/src/hotspot/share/oops/method.cpp -+++ b/src/hotspot/share/oops/method.cpp -@@ -2208,7 +2208,7 @@ void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) { - // Add a method id to the jmethod_ids - jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) { - // FIXME: (DCEVM) ??? -- if (m != m->newest_version()) { -+ if (AllowEnhancedClassRedefinition && m != m->newest_version()) { - m = m->newest_version(); - } - ClassLoaderData* cld = loader_data; -diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -index 1c7677f270f..6c12ee64a6e 100644 ---- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -@@ -75,7 +75,7 @@ public: - // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was - // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we - // must use new versions only. -- if (k->new_version()==NULL) { -+ if (AllowEnhancedClassRedefinition && k->new_version()==NULL) { - _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); - if (_dictionary_walk) { - // Collect array classes this way when walking the dictionary (because array classes are -diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp -index 0e7722dba7d..d67457f02ac 100644 ---- a/src/hotspot/share/runtime/reflection.cpp -+++ b/src/hotspot/share/runtime/reflection.cpp -@@ -628,7 +628,7 @@ bool Reflection::verify_member_access(const Klass* current_class, - TRAPS) { - - // (DCEVM) Decide accessibility based on active version -- if (current_class != NULL) { -+ if (AllowEnhancedClassRedefinition && current_class != NULL) { - current_class = current_class->active_version(); - } - --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch b/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch deleted file mode 100644 index ac5132f7c98e..000000000000 --- a/jb/project/tools/patches/dcevm/0016-Fix-LoadedClassesClosure-fixes-problems-with-remote-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From dc675de6ac42819b8536827ea450fcad13a97448 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Wed, 11 Nov 2020 18:45:15 +0100 -Subject: [PATCH 16/34] Fix LoadedClassesClosure - fixes problems with remote - debugging - ---- - src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -index 6c12ee64a6e..2a469555dbd 100644 ---- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp -@@ -75,7 +75,7 @@ public: - // the new version (SystemDictionary stores only new versions). But the LoadedClassesClosure's functionality was - // changed in java8 where jvmtiLoadedClasses collects all classes from all classloaders, therefore we - // must use new versions only. -- if (AllowEnhancedClassRedefinition && k->new_version()==NULL) { -+ if (!AllowEnhancedClassRedefinition || k->new_version()==NULL) { - _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror()))); - if (_dictionary_walk) { - // Collect array classes this way when walking the dictionary (because array classes are --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch b/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch deleted file mode 100644 index 8491b58fb385..000000000000 --- a/jb/project/tools/patches/dcevm/0017-pre-dcevm15-Cleanup-code-related-to-removed-CMS.patch +++ /dev/null @@ -1,3934 +0,0 @@ -From 5cdb7847b227797e74bdf025065696ef6273dcd6 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Mon, 16 Nov 2020 20:54:06 +0100 -Subject: [PATCH 17/34] pre dcevm15 - Cleanup code related to removed CMS - ---- - .../share/gc/cms/compactibleFreeListSpace.cpp | 3148 ----------------- - .../share/gc/cms/compactibleFreeListSpace.hpp | 759 ---- - 2 files changed, 3907 deletions(-) - delete mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp - delete mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp - -diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp -deleted file mode 100644 -index a93f764f1b9..00000000000 ---- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp -+++ /dev/null -@@ -1,3148 +0,0 @@ --/* -- * Copyright (c) 2001, 2018, 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/cms/cmsHeap.hpp" --#include "gc/cms/cmsLockVerifier.hpp" --#include "gc/cms/compactibleFreeListSpace.hpp" --#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" --#include "gc/cms/concurrentMarkSweepThread.hpp" --#include "gc/shared/blockOffsetTable.inline.hpp" --#include "gc/shared/collectedHeap.inline.hpp" --#include "gc/shared/genOopClosures.inline.hpp" --#include "gc/shared/space.inline.hpp" --#include "gc/shared/spaceDecorator.hpp" --#include "logging/log.hpp" --#include "logging/logStream.hpp" --#include "memory/allocation.inline.hpp" --#include "memory/binaryTreeDictionary.inline.hpp" --#include "memory/iterator.inline.hpp" --#include "memory/resourceArea.hpp" --#include "memory/universe.hpp" --#include "oops/access.inline.hpp" --#include "oops/compressedOops.inline.hpp" --#include "oops/oop.inline.hpp" --#include "runtime/globals.hpp" --#include "runtime/handles.inline.hpp" --#include "runtime/init.hpp" --#include "runtime/java.hpp" --#include "runtime/orderAccess.hpp" --#include "runtime/vmThread.hpp" --#include "utilities/align.hpp" --#include "utilities/copy.hpp" -- --// Specialize for AdaptiveFreeList which tries to avoid --// splitting a chunk of a size that is under populated in favor of --// an over populated size. The general get_better_list() just returns --// the current list. --template <> --TreeList >* --TreeList >::get_better_list( -- BinaryTreeDictionary >* dictionary) { -- // A candidate chunk has been found. If it is already under -- // populated, get a chunk associated with the hint for this -- // chunk. -- -- TreeList >* curTL = this; -- if (curTL->surplus() <= 0) { -- /* Use the hint to find a size with a surplus, and reset the hint. */ -- TreeList >* hintTL = this; -- while (hintTL->hint() != 0) { -- assert(hintTL->hint() > hintTL->size(), -- "hint points in the wrong direction"); -- hintTL = dictionary->find_list(hintTL->hint()); -- assert(curTL != hintTL, "Infinite loop"); -- if (hintTL == NULL || -- hintTL == curTL /* Should not happen but protect against it */ ) { -- // No useful hint. Set the hint to NULL and go on. -- curTL->set_hint(0); -- break; -- } -- assert(hintTL->size() > curTL->size(), "hint is inconsistent"); -- if (hintTL->surplus() > 0) { -- // The hint led to a list that has a surplus. Use it. -- // Set the hint for the candidate to an overpopulated -- // size. -- curTL->set_hint(hintTL->size()); -- // Change the candidate. -- curTL = hintTL; -- break; -- } -- } -- } -- return curTL; --} -- --void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) { -- TreeList >* nd = find_list(size); -- if (nd) { -- if (split) { -- if (birth) { -- nd->increment_split_births(); -- nd->increment_surplus(); -- } else { -- nd->increment_split_deaths(); -- nd->decrement_surplus(); -- } -- } else { -- if (birth) { -- nd->increment_coal_births(); -- nd->increment_surplus(); -- } else { -- nd->increment_coal_deaths(); -- nd->decrement_surplus(); -- } -- } -- } -- // A list for this size may not be found (nd == 0) if -- // This is a death where the appropriate list is now -- // empty and has been removed from the list. -- // This is a birth associated with a LinAB. The chunk -- // for the LinAB is not in the dictionary. --} -- --bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { -- if (FLSAlwaysCoalesceLarge) return true; -- -- TreeList >* list_of_size = find_list(size); -- // None of requested size implies overpopulated. -- return list_of_size == NULL || list_of_size->coal_desired() <= 0 || -- list_of_size->count() > list_of_size->coal_desired(); --} -- --// For each list in the tree, calculate the desired, desired --// coalesce, count before sweep, and surplus before sweep. --class BeginSweepClosure : public AscendTreeCensusClosure > { -- double _percentage; -- float _inter_sweep_current; -- float _inter_sweep_estimate; -- float _intra_sweep_estimate; -- -- public: -- BeginSweepClosure(double p, float inter_sweep_current, -- float inter_sweep_estimate, -- float intra_sweep_estimate) : -- _percentage(p), -- _inter_sweep_current(inter_sweep_current), -- _inter_sweep_estimate(inter_sweep_estimate), -- _intra_sweep_estimate(intra_sweep_estimate) { } -- -- void do_list(AdaptiveFreeList* fl) { -- double coalSurplusPercent = _percentage; -- fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); -- fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent)); -- fl->set_before_sweep(fl->count()); -- fl->set_bfr_surp(fl->surplus()); -- } --}; -- --void AFLBinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent, -- float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { -- BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, -- inter_sweep_estimate, -- intra_sweep_estimate); -- bsc.do_tree(root()); --} -- --// Calculate surpluses for the lists in the tree. --class setTreeSurplusClosure : public AscendTreeCensusClosure > { -- double percentage; -- public: -- setTreeSurplusClosure(double v) { percentage = v; } -- -- void do_list(AdaptiveFreeList* fl) { -- double splitSurplusPercent = percentage; -- fl->set_surplus(fl->count() - -- (ssize_t)((double)fl->desired() * splitSurplusPercent)); -- } --}; -- --void AFLBinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) { -- setTreeSurplusClosure sts(splitSurplusPercent); -- sts.do_tree(root()); --} -- --// Set hints for the lists in the tree. --class setTreeHintsClosure : public DescendTreeCensusClosure > { -- size_t hint; -- public: -- setTreeHintsClosure(size_t v) { hint = v; } -- -- void do_list(AdaptiveFreeList* fl) { -- fl->set_hint(hint); -- assert(fl->hint() == 0 || fl->hint() > fl->size(), -- "Current hint is inconsistent"); -- if (fl->surplus() > 0) { -- hint = fl->size(); -- } -- } --}; -- --void AFLBinaryTreeDictionary::set_tree_hints(void) { -- setTreeHintsClosure sth(0); -- sth.do_tree(root()); --} -- --// Save count before previous sweep and splits and coalesces. --class clearTreeCensusClosure : public AscendTreeCensusClosure > { -- void do_list(AdaptiveFreeList* fl) { -- fl->set_prev_sweep(fl->count()); -- fl->set_coal_births(0); -- fl->set_coal_deaths(0); -- fl->set_split_births(0); -- fl->set_split_deaths(0); -- } --}; -- --void AFLBinaryTreeDictionary::clear_tree_census(void) { -- clearTreeCensusClosure ctc; -- ctc.do_tree(root()); --} -- --// Do reporting and post sweep clean up. --void AFLBinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) { -- // Does walking the tree 3 times hurt? -- set_tree_surplus(splitSurplusPercent); -- set_tree_hints(); -- LogTarget(Trace, gc, freelist, stats) log; -- if (log.is_enabled()) { -- LogStream out(log); -- report_statistics(&out); -- } -- clear_tree_census(); --} -- --// Print census information - counts, births, deaths, etc. --// for each list in the tree. Also print some summary --// information. --class PrintTreeCensusClosure : public AscendTreeCensusClosure > { -- int _print_line; -- size_t _total_free; -- AdaptiveFreeList _total; -- -- public: -- PrintTreeCensusClosure() { -- _print_line = 0; -- _total_free = 0; -- } -- AdaptiveFreeList* total() { return &_total; } -- size_t total_free() { return _total_free; } -- -- void do_list(AdaptiveFreeList* fl) { -- LogStreamHandle(Debug, gc, freelist, census) out; -- -- if (++_print_line >= 40) { -- AdaptiveFreeList::print_labels_on(&out, "size"); -- _print_line = 0; -- } -- fl->print_on(&out); -- _total_free += fl->count() * fl->size() ; -- total()->set_count( total()->count() + fl->count() ); -- total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() ); -- total()->set_surplus( total()->split_deaths() + fl->surplus() ); -- total()->set_desired( total()->desired() + fl->desired() ); -- total()->set_prev_sweep( total()->prev_sweep() + fl->prev_sweep() ); -- total()->set_before_sweep(total()->before_sweep() + fl->before_sweep()); -- total()->set_coal_births( total()->coal_births() + fl->coal_births() ); -- total()->set_coal_deaths( total()->coal_deaths() + fl->coal_deaths() ); -- total()->set_split_births(total()->split_births() + fl->split_births()); -- total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); -- } --}; -- --void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const { -- -- st->print_cr("BinaryTree"); -- AdaptiveFreeList::print_labels_on(st, "size"); -- PrintTreeCensusClosure ptc; -- ptc.do_tree(root()); -- -- AdaptiveFreeList* total = ptc.total(); -- AdaptiveFreeList::print_labels_on(st, " "); -- total->print_on(st, "TOTAL\t"); -- st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f deficit: %8.5f", -- ptc.total_free(), -- (double)(total->split_births() + total->coal_births() -- - total->split_deaths() - total->coal_deaths()) -- /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0), -- (double)(total->desired() - total->count()) -- /(total->desired() != 0 ? (double)total->desired() : 1.0)); --} -- --///////////////////////////////////////////////////////////////////////// --//// CompactibleFreeListSpace --///////////////////////////////////////////////////////////////////////// -- --// highest ranked free list lock rank --int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3; -- --// Defaults are 0 so things will break badly if incorrectly initialized. --size_t CompactibleFreeListSpace::IndexSetStart = 0; --size_t CompactibleFreeListSpace::IndexSetStride = 0; --size_t CompactibleFreeListSpace::_min_chunk_size_in_bytes = 0; -- --size_t MinChunkSize = 0; -- --void CompactibleFreeListSpace::set_cms_values() { -- // Set CMS global values -- assert(MinChunkSize == 0, "already set"); -- -- // MinChunkSize should be a multiple of MinObjAlignment and be large enough -- // for chunks to contain a FreeChunk. -- _min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes); -- MinChunkSize = _min_chunk_size_in_bytes / BytesPerWord; -- -- assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); -- IndexSetStart = MinChunkSize; -- IndexSetStride = MinObjAlignment; --} -- --// Constructor --CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) : -- _bt(bs, mr), -- // free list locks are in the range of values taken by _lockRank -- // This range currently is [_leaf+2, _leaf+3] -- // Note: this requires that CFLspace c'tors -- // are called serially in the order in which the locks are -- // are acquired in the program text. This is true today. -- _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true, -- Monitor::_safepoint_check_sometimes), -- _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1 -- "CompactibleFreeListSpace._dict_par_lock", true, -- Monitor::_safepoint_check_never), -- _rescan_task_size(CardTable::card_size_in_words * BitsPerWord * -- CMSRescanMultiple), -- _marking_task_size(CardTable::card_size_in_words * BitsPerWord * -- CMSConcMarkMultiple), -- _collector(NULL), -- _preconsumptionDirtyCardClosure(NULL) --{ -- assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, -- "FreeChunk is larger than expected"); -- _bt.set_space(this); -- initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); -- -- _dictionary = new AFLBinaryTreeDictionary(mr); -- -- assert(_dictionary != NULL, "CMS dictionary initialization"); -- // The indexed free lists are initially all empty and are lazily -- // filled in on demand. Initialize the array elements to NULL. -- initializeIndexedFreeListArray(); -- -- _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, -- SmallForLinearAlloc); -- -- // CMSIndexedFreeListReplenish should be at least 1 -- CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish); -- _promoInfo.setSpace(this); -- if (UseCMSBestFit) { -- _fitStrategy = FreeBlockBestFitFirst; -- } else { -- _fitStrategy = FreeBlockStrategyNone; -- } -- check_free_list_consistency(); -- -- // Initialize locks for parallel case. -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 -- "a freelist par lock", true, Mutex::_safepoint_check_sometimes); -- DEBUG_ONLY( -- _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); -- ) -- } -- _dictionary->set_par_lock(&_parDictionaryAllocLock); -- -- _used_stable = 0; --} -- --HeapWord* CompactibleFreeListSpace::forward_compact_top(size_t size, -- CompactPoint* cp, HeapWord* compact_top) { -- ShouldNotReachHere(); -- return NULL; --} -- --// Like CompactibleSpace forward() but always calls cross_threshold() to --// update the block offset table. Removed initialize_threshold call because --// CFLS does not use a block offset array for contiguous spaces. --HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size, -- CompactPoint* cp, HeapWord* compact_top) { -- // q is alive -- // First check if we should switch compaction space -- assert(this == cp->space, "'this' should be current compaction space."); -- size_t compaction_max_size = pointer_delta(end(), compact_top); -- assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size), -- "virtual adjustObjectSize_v() method is not correct"); -- size_t adjusted_size = adjustObjectSize(size); -- assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0, -- "no small fragments allowed"); -- assert(minimum_free_block_size() == MinChunkSize, -- "for de-virtualized reference below"); -- // Can't leave a nonzero size, residual fragment smaller than MinChunkSize -- if (adjusted_size + MinChunkSize > compaction_max_size && -- adjusted_size != compaction_max_size) { -- do { -- // switch to next compaction space -- cp->space->set_compaction_top(compact_top); -- cp->space = cp->space->next_compaction_space(); -- if (cp->space == NULL) { -- cp->gen = CMSHeap::heap()->young_gen(); -- assert(cp->gen != NULL, "compaction must succeed"); -- cp->space = cp->gen->first_compaction_space(); -- assert(cp->space != NULL, "generation must have a first compaction space"); -- } -- compact_top = cp->space->bottom(); -- cp->space->set_compaction_top(compact_top); -- // The correct adjusted_size may not be the same as that for this method -- // (i.e., cp->space may no longer be "this" so adjust the size again. -- // Use the virtual method which is not used above to save the virtual -- // dispatch. -- adjusted_size = cp->space->adjust_object_size_v(size); -- compaction_max_size = pointer_delta(cp->space->end(), compact_top); -- assert(cp->space->minimum_free_block_size() == 0, "just checking"); -- } while (adjusted_size > compaction_max_size); -- } -- -- // store the forwarding pointer into the mark word -- if ((HeapWord*)q != compact_top) { -- q->forward_to(oop(compact_top)); -- assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); -- } else { -- // if the object isn't moving we can just set the mark to the default -- // mark and handle it specially later on. -- q->init_mark_raw(); -- assert(q->forwardee() == NULL, "should be forwarded to NULL"); -- } -- -- compact_top += adjusted_size; -- -- // we need to update the offset table so that the beginnings of objects can be -- // found during scavenge. Note that we are updating the offset table based on -- // where the object will be once the compaction phase finishes. -- -- // Always call cross_threshold(). A contiguous space can only call it when -- // the compaction_top exceeds the current threshold but not for an -- // non-contiguous space. -- cp->threshold = -- cp->space->cross_threshold(compact_top - adjusted_size, compact_top); -- return compact_top; --} -- --// A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt --// and use of single_block instead of alloc_block. The name here is not really --// appropriate - maybe a more general name could be invented for both the --// contiguous and noncontiguous spaces. -- --HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) { -- _bt.single_block(start, the_end); -- return end(); --} -- --// Initialize them to NULL. --void CompactibleFreeListSpace::initializeIndexedFreeListArray() { -- for (size_t i = 0; i < IndexSetSize; i++) { -- // Note that on platforms where objects are double word aligned, -- // the odd array elements are not used. It is convenient, however, -- // to map directly from the object size to the array element. -- _indexedFreeList[i].reset(IndexSetSize); -- _indexedFreeList[i].set_size(i); -- assert(_indexedFreeList[i].count() == 0, "reset check failed"); -- assert(_indexedFreeList[i].head() == NULL, "reset check failed"); -- assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); -- assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); -- } --} -- --size_t CompactibleFreeListSpace::obj_size(const HeapWord* addr) const { -- return adjustObjectSize(oop(addr)->size()); --} -- --void CompactibleFreeListSpace::resetIndexedFreeListArray() { -- for (size_t i = 1; i < IndexSetSize; i++) { -- assert(_indexedFreeList[i].size() == (size_t) i, -- "Indexed free list sizes are incorrect"); -- _indexedFreeList[i].reset(IndexSetSize); -- assert(_indexedFreeList[i].count() == 0, "reset check failed"); -- assert(_indexedFreeList[i].head() == NULL, "reset check failed"); -- assert(_indexedFreeList[i].tail() == NULL, "reset check failed"); -- assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed"); -- } --} -- --void CompactibleFreeListSpace::reset(MemRegion mr) { -- resetIndexedFreeListArray(); -- dictionary()->reset(); -- if (BlockOffsetArrayUseUnallocatedBlock) { -- assert(end() == mr.end(), "We are compacting to the bottom of CMS gen"); -- // Everything's allocated until proven otherwise. -- _bt.set_unallocated_block(end()); -- } -- if (!mr.is_empty()) { -- assert(mr.word_size() >= MinChunkSize, "Chunk size is too small"); -- _bt.single_block(mr.start(), mr.word_size()); -- FreeChunk* fc = (FreeChunk*) mr.start(); -- fc->set_size(mr.word_size()); -- if (mr.word_size() >= IndexSetSize ) { -- returnChunkToDictionary(fc); -- } else { -- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -- _indexedFreeList[mr.word_size()].return_chunk_at_head(fc); -- } -- coalBirth(mr.word_size()); -- } -- _promoInfo.reset(); -- _smallLinearAllocBlock._ptr = NULL; -- _smallLinearAllocBlock._word_size = 0; --} -- --void CompactibleFreeListSpace::reset_after_compaction() { -- // Reset the space to the new reality - one free chunk. -- MemRegion mr(compaction_top(), end()); -- reset(mr); -- // Now refill the linear allocation block(s) if possible. -- refillLinearAllocBlocksIfNeeded(); --} -- --// Walks the entire dictionary, returning a coterminal --// chunk, if it exists. Use with caution since it involves --// a potentially complete walk of a potentially large tree. --FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() { -- -- assert_lock_strong(&_freelistLock); -- -- return dictionary()->find_chunk_ends_at(end()); --} -- -- --#ifndef PRODUCT --void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() { -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- _indexedFreeList[i].allocation_stats()->set_returned_bytes(0); -- } --} -- --size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() { -- size_t sum = 0; -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- sum += _indexedFreeList[i].allocation_stats()->returned_bytes(); -- } -- return sum; --} -- --size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const { -- size_t count = 0; -- for (size_t i = IndexSetStart; i < IndexSetSize; i++) { -- debug_only( -- ssize_t total_list_count = 0; -- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -- fc = fc->next()) { -- total_list_count++; -- } -- assert(total_list_count == _indexedFreeList[i].count(), -- "Count in list is incorrect"); -- ) -- count += _indexedFreeList[i].count(); -- } -- return count; --} -- --size_t CompactibleFreeListSpace::totalCount() { -- size_t num = totalCountInIndexedFreeLists(); -- num += dictionary()->total_count(); -- if (_smallLinearAllocBlock._word_size != 0) { -- num++; -- } -- return num; --} --#endif -- --bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const { -- FreeChunk* fc = (FreeChunk*) p; -- return fc->is_free(); --} -- --size_t CompactibleFreeListSpace::used() const { -- return capacity() - free(); --} -- --size_t CompactibleFreeListSpace::used_stable() const { -- return _used_stable; --} -- --void CompactibleFreeListSpace::recalculate_used_stable() { -- _used_stable = used(); --} -- --size_t CompactibleFreeListSpace::free() const { -- // "MT-safe, but not MT-precise"(TM), if you will: i.e. -- // if you do this while the structures are in flux you -- // may get an approximate answer only; for instance -- // because there is concurrent allocation either -- // directly by mutators or for promotion during a GC. -- // It's "MT-safe", however, in the sense that you are guaranteed -- // not to crash and burn, for instance, because of walking -- // pointers that could disappear as you were walking them. -- // The approximation is because the various components -- // that are read below are not read atomically (and -- // further the computation of totalSizeInIndexedFreeLists() -- // is itself a non-atomic computation. The normal use of -- // this is during a resize operation at the end of GC -- // and at that time you are guaranteed to get the -- // correct actual value. However, for instance, this is -- // also read completely asynchronously by the "perf-sampler" -- // that supports jvmstat, and you are apt to see the values -- // flicker in such cases. -- assert(_dictionary != NULL, "No _dictionary?"); -- return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) + -- totalSizeInIndexedFreeLists() + -- _smallLinearAllocBlock._word_size) * HeapWordSize; --} -- --size_t CompactibleFreeListSpace::max_alloc_in_words() const { -- assert(_dictionary != NULL, "No _dictionary?"); -- assert_locked(); -- size_t res = _dictionary->max_chunk_size(); -- res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, -- (size_t) SmallForLinearAlloc - 1)); -- // XXX the following could potentially be pretty slow; -- // should one, pessimistically for the rare cases when res -- // calculated above is less than IndexSetSize, -- // just return res calculated above? My reasoning was that -- // those cases will be so rare that the extra time spent doesn't -- // really matter.... -- // Note: do not change the loop test i >= res + IndexSetStride -- // to i > res below, because i is unsigned and res may be zero. -- for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride; -- i -= IndexSetStride) { -- if (_indexedFreeList[i].head() != NULL) { -- assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); -- return i; -- } -- } -- return res; --} -- --void LinearAllocBlock::print_on(outputStream* st) const { -- st->print_cr(" LinearAllocBlock: ptr = " PTR_FORMAT ", word_size = " SIZE_FORMAT -- ", refillsize = " SIZE_FORMAT ", allocation_size_limit = " SIZE_FORMAT, -- p2i(_ptr), _word_size, _refillSize, _allocation_size_limit); --} -- --void CompactibleFreeListSpace::print_on(outputStream* st) const { -- st->print_cr("COMPACTIBLE FREELIST SPACE"); -- st->print_cr(" Space:"); -- Space::print_on(st); -- -- st->print_cr("promoInfo:"); -- _promoInfo.print_on(st); -- -- st->print_cr("_smallLinearAllocBlock"); -- _smallLinearAllocBlock.print_on(st); -- -- // dump_memory_block(_smallLinearAllocBlock->_ptr, 128); -- -- st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy)); --} -- --void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) --const { -- reportIndexedFreeListStatistics(st); -- st->print_cr("Layout of Indexed Freelists"); -- st->print_cr("---------------------------"); -- AdaptiveFreeList::print_labels_on(st, "size"); -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- _indexedFreeList[i].print_on(st); -- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; fc = fc->next()) { -- st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", -- p2i(fc), p2i((HeapWord*)fc + i), -- fc->cantCoalesce() ? "\t CC" : ""); -- } -- } --} -- --void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st) --const { -- _promoInfo.print_on(st); --} -- --void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st) --const { -- _dictionary->report_statistics(st); -- st->print_cr("Layout of Freelists in Tree"); -- st->print_cr("---------------------------"); -- _dictionary->print_free_lists(st); --} -- --class BlkPrintingClosure: public BlkClosure { -- const CMSCollector* _collector; -- const CompactibleFreeListSpace* _sp; -- const CMSBitMap* _live_bit_map; -- const bool _post_remark; -- outputStream* _st; --public: -- BlkPrintingClosure(const CMSCollector* collector, -- const CompactibleFreeListSpace* sp, -- const CMSBitMap* live_bit_map, -- outputStream* st): -- _collector(collector), -- _sp(sp), -- _live_bit_map(live_bit_map), -- _post_remark(collector->abstract_state() > CMSCollector::FinalMarking), -- _st(st) { } -- size_t do_blk(HeapWord* addr); --}; -- --size_t BlkPrintingClosure::do_blk(HeapWord* addr) { -- size_t sz = _sp->block_size_no_stall(addr, _collector); -- assert(sz != 0, "Should always be able to compute a size"); -- if (_sp->block_is_obj(addr)) { -- const bool dead = _post_remark && !_live_bit_map->isMarked(addr); -- _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s", -- p2i(addr), -- dead ? "dead" : "live", -- sz, -- (!dead && CMSPrintObjectsInDump) ? ":" : "."); -- if (CMSPrintObjectsInDump && !dead) { -- oop(addr)->print_on(_st); -- _st->print_cr("--------------------------------------"); -- } -- } else { // free block -- _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s", -- p2i(addr), sz, CMSPrintChunksInDump ? ":" : "."); -- if (CMSPrintChunksInDump) { -- ((FreeChunk*)addr)->print_on(_st); -- _st->print_cr("--------------------------------------"); -- } -- } -- return sz; --} -- --void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st) { -- st->print_cr("========================="); -- st->print_cr("Block layout in CMS Heap:"); -- st->print_cr("========================="); -- BlkPrintingClosure bpcl(c, this, c->markBitMap(), st); -- blk_iterate(&bpcl); -- -- st->print_cr("======================================="); -- st->print_cr("Order & Layout of Promotion Info Blocks"); -- st->print_cr("======================================="); -- print_promo_info_blocks(st); -- -- st->print_cr("==========================="); -- st->print_cr("Order of Indexed Free Lists"); -- st->print_cr("========================="); -- print_indexed_free_lists(st); -- -- st->print_cr("================================="); -- st->print_cr("Order of Free Lists in Dictionary"); -- st->print_cr("================================="); -- print_dictionary_free_lists(st); --} -- -- --void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const { -- assert_lock_strong(&_freelistLock); -- Log(gc, freelist, stats) log; -- if (!log.is_debug()) { -- return; -- } -- log.debug("%s", title); -- -- LogStream out(log.debug()); -- _dictionary->report_statistics(&out); -- -- if (log.is_trace()) { -- LogStream trace_out(log.trace()); -- reportIndexedFreeListStatistics(&trace_out); -- size_t total_size = totalSizeInIndexedFreeLists() + -- _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); -- log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); -- } --} -- --void CompactibleFreeListSpace::reportIndexedFreeListStatistics(outputStream* st) const { -- assert_lock_strong(&_freelistLock); -- st->print_cr("Statistics for IndexedFreeLists:"); -- st->print_cr("--------------------------------"); -- size_t total_size = totalSizeInIndexedFreeLists(); -- size_t free_blocks = numFreeBlocksInIndexedFreeLists(); -- st->print_cr("Total Free Space: " SIZE_FORMAT, total_size); -- st->print_cr("Max Chunk Size: " SIZE_FORMAT, maxChunkSizeInIndexedFreeLists()); -- st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks); -- if (free_blocks != 0) { -- st->print_cr("Av. Block Size: " SIZE_FORMAT, total_size/free_blocks); -- } --} -- --size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { -- size_t res = 0; -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- debug_only( -- ssize_t recount = 0; -- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -- fc = fc->next()) { -- recount += 1; -- } -- assert(recount == _indexedFreeList[i].count(), -- "Incorrect count in list"); -- ) -- res += _indexedFreeList[i].count(); -- } -- return res; --} -- --size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const { -- for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { -- if (_indexedFreeList[i].head() != NULL) { -- assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList"); -- return (size_t)i; -- } -- } -- return 0; --} -- --void CompactibleFreeListSpace::set_end(HeapWord* value) { -- HeapWord* prevEnd = end(); -- assert(prevEnd != value, "unnecessary set_end call"); -- assert(prevEnd == NULL || !BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), -- "New end is below unallocated block"); -- _end = value; -- if (prevEnd != NULL) { -- // Resize the underlying block offset table. -- _bt.resize(pointer_delta(value, bottom())); -- if (value <= prevEnd) { -- assert(!BlockOffsetArrayUseUnallocatedBlock || value >= unallocated_block(), -- "New end is below unallocated block"); -- } else { -- // Now, take this new chunk and add it to the free blocks. -- // Note that the BOT has not yet been updated for this block. -- size_t newFcSize = pointer_delta(value, prevEnd); -- // Add the block to the free lists, if possible coalescing it -- // with the last free block, and update the BOT and census data. -- addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); -- } -- } --} -- --class FreeListSpaceDCTOC : public FilteringDCTOC { -- CompactibleFreeListSpace* _cfls; -- CMSCollector* _collector; -- bool _parallel; --protected: -- // Override. --#define walk_mem_region_with_cl_DECL(ClosureType) \ -- virtual void walk_mem_region_with_cl(MemRegion mr, \ -- HeapWord* bottom, HeapWord* top, \ -- ClosureType* cl); \ -- void walk_mem_region_with_cl_par(MemRegion mr, \ -- HeapWord* bottom, HeapWord* top, \ -- ClosureType* cl); \ -- void walk_mem_region_with_cl_nopar(MemRegion mr, \ -- HeapWord* bottom, HeapWord* top, \ -- ClosureType* cl) -- walk_mem_region_with_cl_DECL(OopIterateClosure); -- walk_mem_region_with_cl_DECL(FilteringClosure); -- --public: -- FreeListSpaceDCTOC(CompactibleFreeListSpace* sp, -- CMSCollector* collector, -- OopIterateClosure* cl, -- CardTable::PrecisionStyle precision, -- HeapWord* boundary, -- bool parallel) : -- FilteringDCTOC(sp, cl, precision, boundary), -- _cfls(sp), _collector(collector), _parallel(parallel) {} --}; -- --// We de-virtualize the block-related calls below, since we know that our --// space is a CompactibleFreeListSpace. -- --#define FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \ --void FreeListSpaceDCTOC::walk_mem_region_with_cl(MemRegion mr, \ -- HeapWord* bottom, \ -- HeapWord* top, \ -- ClosureType* cl) { \ -- if (_parallel) { \ -- walk_mem_region_with_cl_par(mr, bottom, top, cl); \ -- } else { \ -- walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \ -- } \ --} \ --void FreeListSpaceDCTOC::walk_mem_region_with_cl_par(MemRegion mr, \ -- HeapWord* bottom, \ -- HeapWord* top, \ -- ClosureType* cl) { \ -- /* Skip parts that are before "mr", in case "block_start" sent us \ -- back too far. */ \ -- HeapWord* mr_start = mr.start(); \ -- size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ -- HeapWord* next = bottom + bot_size; \ -- while (next < mr_start) { \ -- bottom = next; \ -- bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \ -- next = bottom + bot_size; \ -- } \ -- \ -- while (bottom < top) { \ -- if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) && \ -- !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ -- oop(bottom)) && \ -- !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ -- size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ -- bottom += _cfls->adjustObjectSize(word_sz); \ -- } else { \ -- bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \ -- } \ -- } \ --} \ --void FreeListSpaceDCTOC::walk_mem_region_with_cl_nopar(MemRegion mr, \ -- HeapWord* bottom, \ -- HeapWord* top, \ -- ClosureType* cl) { \ -- /* Skip parts that are before "mr", in case "block_start" sent us \ -- back too far. */ \ -- HeapWord* mr_start = mr.start(); \ -- size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -- HeapWord* next = bottom + bot_size; \ -- while (next < mr_start) { \ -- bottom = next; \ -- bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -- next = bottom + bot_size; \ -- } \ -- \ -- while (bottom < top) { \ -- if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) && \ -- !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \ -- oop(bottom)) && \ -- !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \ -- size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \ -- bottom += _cfls->adjustObjectSize(word_sz); \ -- } else { \ -- bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \ -- } \ -- } \ --} -- --// (There are only two of these, rather than N, because the split is due --// only to the introduction of the FilteringClosure, a local part of the --// impl of this abstraction.) --FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure) --FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure) -- --DirtyCardToOopClosure* --CompactibleFreeListSpace::new_dcto_cl(OopIterateClosure* cl, -- CardTable::PrecisionStyle precision, -- HeapWord* boundary, -- bool parallel) { -- return new FreeListSpaceDCTOC(this, _collector, cl, precision, boundary, parallel); --} -- -- --// Note on locking for the space iteration functions: --// since the collector's iteration activities are concurrent with --// allocation activities by mutators, absent a suitable mutual exclusion --// mechanism the iterators may go awry. For instance a block being iterated --// may suddenly be allocated or divided up and part of it allocated and --// so on. -- --// Apply the given closure to each block in the space. --void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) { -- assert_lock_strong(freelistLock()); -- HeapWord *cur, *limit; -- for (cur = bottom(), limit = end(); cur < limit; -- cur += cl->do_blk_careful(cur)); --} -- --// Apply the given closure to each block in the space. --void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) { -- assert_lock_strong(freelistLock()); -- HeapWord *cur, *limit; -- for (cur = bottom(), limit = end(); cur < limit; -- cur += cl->do_blk(cur)); --} -- --// Apply the given closure to each oop in the space. --void CompactibleFreeListSpace::oop_iterate(OopIterateClosure* cl) { -- assert_lock_strong(freelistLock()); -- HeapWord *cur, *limit; -- size_t curSize; -- for (cur = bottom(), limit = end(); cur < limit; -- cur += curSize) { -- curSize = block_size(cur); -- if (block_is_obj(cur)) { -- oop(cur)->oop_iterate(cl); -- } -- } --} -- --// NOTE: In the following methods, in order to safely be able to --// apply the closure to an object, we need to be sure that the --// object has been initialized. We are guaranteed that an object --// is initialized if we are holding the Heap_lock with the --// world stopped. --void CompactibleFreeListSpace::verify_objects_initialized() const { -- if (is_init_completed()) { -- assert_locked_or_safepoint(Heap_lock); -- if (Universe::is_fully_initialized()) { -- guarantee(SafepointSynchronize::is_at_safepoint(), -- "Required for objects to be initialized"); -- } -- } // else make a concession at vm start-up --} -- --// Apply the given closure to each object in the space --void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { -- assert_lock_strong(freelistLock()); -- NOT_PRODUCT(verify_objects_initialized()); -- HeapWord *cur, *limit; -- size_t curSize; -- for (cur = bottom(), limit = end(); cur < limit; -- cur += curSize) { -- curSize = block_size(cur); -- if (block_is_obj(cur)) { -- blk->do_object(oop(cur)); -- } -- } --} -- --// Apply the given closure to each live object in the space --// The usage of CompactibleFreeListSpace --// by the ConcurrentMarkSweepGeneration for concurrent GC's allows --// objects in the space with references to objects that are no longer --// valid. For example, an object may reference another object --// that has already been sweep up (collected). This method uses --// obj_is_alive() to determine whether it is safe to apply the closure to --// an object. See obj_is_alive() for details on how liveness of an --// object is decided. -- --void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { -- assert_lock_strong(freelistLock()); -- NOT_PRODUCT(verify_objects_initialized()); -- HeapWord *cur, *limit; -- size_t curSize; -- for (cur = bottom(), limit = end(); cur < limit; -- cur += curSize) { -- curSize = block_size(cur); -- if (block_is_obj(cur) && obj_is_alive(cur)) { -- blk->do_object(oop(cur)); -- } -- } --} -- --void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, -- UpwardsObjectClosure* cl) { -- assert_locked(freelistLock()); -- NOT_PRODUCT(verify_objects_initialized()); -- assert(!mr.is_empty(), "Should be non-empty"); -- // We use MemRegion(bottom(), end()) rather than used_region() below -- // because the two are not necessarily equal for some kinds of -- // spaces, in particular, certain kinds of free list spaces. -- // We could use the more complicated but more precise: -- // MemRegion(used_region().start(), align_up(used_region().end(), CardSize)) -- // but the slight imprecision seems acceptable in the assertion check. -- assert(MemRegion(bottom(), end()).contains(mr), -- "Should be within used space"); -- HeapWord* prev = cl->previous(); // max address from last time -- if (prev >= mr.end()) { // nothing to do -- return; -- } -- // This assert will not work when we go from cms space to perm -- // space, and use same closure. Easy fix deferred for later. XXX YSR -- // assert(prev == NULL || contains(prev), "Should be within space"); -- -- bool last_was_obj_array = false; -- HeapWord *blk_start_addr, *region_start_addr; -- if (prev > mr.start()) { -- region_start_addr = prev; -- blk_start_addr = prev; -- // The previous invocation may have pushed "prev" beyond the -- // last allocated block yet there may be still be blocks -- // in this region due to a particular coalescing policy. -- // Relax the assertion so that the case where the unallocated -- // block is maintained and "prev" is beyond the unallocated -- // block does not cause the assertion to fire. -- assert((BlockOffsetArrayUseUnallocatedBlock && -- (!is_in(prev))) || -- (blk_start_addr == block_start(region_start_addr)), "invariant"); -- } else { -- region_start_addr = mr.start(); -- blk_start_addr = block_start(region_start_addr); -- } -- HeapWord* region_end_addr = mr.end(); -- MemRegion derived_mr(region_start_addr, region_end_addr); -- while (blk_start_addr < region_end_addr) { -- const size_t size = block_size(blk_start_addr); -- if (block_is_obj(blk_start_addr)) { -- last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr); -- } else { -- last_was_obj_array = false; -- } -- blk_start_addr += size; -- } -- if (!last_was_obj_array) { -- assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()), -- "Should be within (closed) used space"); -- assert(blk_start_addr > prev, "Invariant"); -- cl->set_previous(blk_start_addr); // min address for next time -- } --} -- --// Callers of this iterator beware: The closure application should --// be robust in the face of uninitialized objects and should (always) --// return a correct size so that the next addr + size below gives us a --// valid block boundary. [See for instance, --// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful() --// in ConcurrentMarkSweepGeneration.cpp.] --HeapWord* --CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr, -- ObjectClosureCareful* cl) { -- assert_lock_strong(freelistLock()); -- // Can't use used_region() below because it may not necessarily -- // be the same as [bottom(),end()); although we could -- // use [used_region().start(),align_up(used_region().end(),CardSize)), -- // that appears too cumbersome, so we just do the simpler check -- // in the assertion below. -- assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr), -- "mr should be non-empty and within used space"); -- HeapWord *addr, *end; -- size_t size; -- for (addr = block_start_careful(mr.start()), end = mr.end(); -- addr < end; addr += size) { -- FreeChunk* fc = (FreeChunk*)addr; -- if (fc->is_free()) { -- // Since we hold the free list lock, which protects direct -- // allocation in this generation by mutators, a free object -- // will remain free throughout this iteration code. -- size = fc->size(); -- } else { -- // Note that the object need not necessarily be initialized, -- // because (for instance) the free list lock does NOT protect -- // object initialization. The closure application below must -- // therefore be correct in the face of uninitialized objects. -- size = cl->do_object_careful_m(oop(addr), mr); -- if (size == 0) { -- // An unparsable object found. Signal early termination. -- return addr; -- } -- } -- } -- return NULL; --} -- -- --HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const { -- NOT_PRODUCT(verify_objects_initialized()); -- return _bt.block_start(p); --} -- --HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const { -- return _bt.block_start_careful(p); --} -- --size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { -- NOT_PRODUCT(verify_objects_initialized()); -- // This must be volatile, or else there is a danger that the compiler -- // will compile the code below into a sometimes-infinite loop, by keeping -- // the value read the first time in a register. -- while (true) { -- // We must do this until we get a consistent view of the object. -- if (FreeChunk::indicatesFreeChunk(p)) { -- volatile FreeChunk* fc = (volatile FreeChunk*)p; -- size_t res = fc->size(); -- -- // Bugfix for systems with weak memory model (PPC64/IA64). The -- // block's free bit was set and we have read the size of the -- // block. Acquire and check the free bit again. If the block is -- // still free, the read size is correct. -- OrderAccess::acquire(); -- -- // If the object is still a free chunk, return the size, else it -- // has been allocated so try again. -- if (FreeChunk::indicatesFreeChunk(p)) { -- assert(res != 0, "Block size should not be 0"); -- return res; -- } -- } else { -- // Ensure klass read before size. -- Klass* k = oop(p)->klass_or_null_acquire(); -- if (k != NULL) { -- assert(k->is_klass(), "Should really be klass oop."); -- oop o = (oop)p; -- assert(oopDesc::is_oop(o, true /* ignore mark word */), "Should be an oop."); -- -- size_t res = o->size_given_klass(k); -- res = adjustObjectSize(res); -- assert(res != 0, "Block size should not be 0"); -- return res; -- } -- } -- } --} -- --// TODO: Now that is_parsable is gone, we should combine these two functions. --// A variant of the above that uses the Printezis bits for --// unparsable but allocated objects. This avoids any possible --// stalls waiting for mutators to initialize objects, and is --// thus potentially faster than the variant above. However, --// this variant may return a zero size for a block that is --// under mutation and for which a consistent size cannot be --// inferred without stalling; see CMSCollector::block_size_if_printezis_bits(). --size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p, -- const CMSCollector* c) --const { -- assert(MemRegion(bottom(), end()).contains(p), "p not in space"); -- // This must be volatile, or else there is a danger that the compiler -- // will compile the code below into a sometimes-infinite loop, by keeping -- // the value read the first time in a register. -- DEBUG_ONLY(uint loops = 0;) -- while (true) { -- // We must do this until we get a consistent view of the object. -- if (FreeChunk::indicatesFreeChunk(p)) { -- volatile FreeChunk* fc = (volatile FreeChunk*)p; -- size_t res = fc->size(); -- -- // Bugfix for systems with weak memory model (PPC64/IA64). The -- // free bit of the block was set and we have read the size of -- // the block. Acquire and check the free bit again. If the -- // block is still free, the read size is correct. -- OrderAccess::acquire(); -- -- if (FreeChunk::indicatesFreeChunk(p)) { -- assert(res != 0, "Block size should not be 0"); -- assert(loops == 0, "Should be 0"); -- return res; -- } -- } else { -- // Ensure klass read before size. -- Klass* k = oop(p)->klass_or_null_acquire(); -- if (k != NULL) { -- assert(k->is_klass(), "Should really be klass oop."); -- oop o = (oop)p; -- assert(oopDesc::is_oop(o), "Should be an oop"); -- -- size_t res = o->size_given_klass(k); -- res = adjustObjectSize(res); -- assert(res != 0, "Block size should not be 0"); -- return res; -- } else { -- // May return 0 if P-bits not present. -- return c->block_size_if_printezis_bits(p); -- } -- } -- assert(loops == 0, "Can loop at most once"); -- DEBUG_ONLY(loops++;) -- } --} -- --size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const { -- NOT_PRODUCT(verify_objects_initialized()); -- assert(MemRegion(bottom(), end()).contains(p), "p not in space"); -- FreeChunk* fc = (FreeChunk*)p; -- if (fc->is_free()) { -- return fc->size(); -- } else { -- // Ignore mark word because this may be a recently promoted -- // object whose mark word is used to chain together grey -- // objects (the last one would have a null value). -- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -- return adjustObjectSize(oop(p)->size()); -- } --} -- --// This implementation assumes that the property of "being an object" is --// stable. But being a free chunk may not be (because of parallel --// promotion.) --bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const { -- FreeChunk* fc = (FreeChunk*)p; -- assert(is_in_reserved(p), "Should be in space"); -- if (FreeChunk::indicatesFreeChunk(p)) return false; -- Klass* k = oop(p)->klass_or_null_acquire(); -- if (k != NULL) { -- // Ignore mark word because it may have been used to -- // chain together promoted objects (the last one -- // would have a null value). -- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -- return true; -- } else { -- return false; // Was not an object at the start of collection. -- } --} -- --// Check if the object is alive. This fact is checked either by consulting --// the main marking bitmap in the sweeping phase or, if it's a permanent --// generation and we're not in the sweeping phase, by checking the --// perm_gen_verify_bit_map where we store the "deadness" information if --// we did not sweep the perm gen in the most recent previous GC cycle. --bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const { -- assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(), -- "Else races are possible"); -- assert(block_is_obj(p), "The address should point to an object"); -- -- // If we're sweeping, we use object liveness information from the main bit map -- // for both perm gen and old gen. -- // We don't need to lock the bitmap (live_map or dead_map below), because -- // EITHER we are in the middle of the sweeping phase, and the -- // main marking bit map (live_map below) is locked, -- // OR we're in other phases and perm_gen_verify_bit_map (dead_map below) -- // is stable, because it's mutated only in the sweeping phase. -- // NOTE: This method is also used by jmap where, if class unloading is -- // off, the results can return "false" for legitimate perm objects, -- // when we are not in the midst of a sweeping phase, which can result -- // in jmap not reporting certain perm gen objects. This will be moot -- // if/when the perm gen goes away in the future. -- if (_collector->abstract_state() == CMSCollector::Sweeping) { -- CMSBitMap* live_map = _collector->markBitMap(); -- return live_map->par_isMarked((HeapWord*) p); -- } -- return true; --} -- --bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const { -- FreeChunk* fc = (FreeChunk*)p; -- assert(is_in_reserved(p), "Should be in space"); -- assert(_bt.block_start(p) == p, "Should be a block boundary"); -- if (!fc->is_free()) { -- // Ignore mark word because it may have been used to -- // chain together promoted objects (the last one -- // would have a null value). -- assert(oopDesc::is_oop(oop(p), true), "Should be an oop"); -- return true; -- } -- return false; --} -- --// "MT-safe but not guaranteed MT-precise" (TM); you may get an --// approximate answer if you don't hold the freelistlock when you call this. --size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const { -- size_t size = 0; -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- debug_only( -- // We may be calling here without the lock in which case we -- // won't do this modest sanity check. -- if (freelistLock()->owned_by_self()) { -- size_t total_list_size = 0; -- for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; -- fc = fc->next()) { -- total_list_size += i; -- } -- assert(total_list_size == i * _indexedFreeList[i].count(), -- "Count in list is incorrect"); -- } -- ) -- size += i * _indexedFreeList[i].count(); -- } -- return size; --} -- --HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) { -- MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); -- return allocate(size); --} -- --HeapWord* --CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) { -- return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size); --} -- --HeapWord* CompactibleFreeListSpace::allocate(size_t size) { -- assert_lock_strong(freelistLock()); -- HeapWord* res = NULL; -- assert(size == adjustObjectSize(size), -- "use adjustObjectSize() before calling into allocate()"); -- -- res = allocate_adaptive_freelists(size); -- -- if (res != NULL) { -- // check that res does lie in this space! -- assert(is_in_reserved(res), "Not in this space!"); -- assert(is_aligned((void*)res), "alignment check"); -- -- FreeChunk* fc = (FreeChunk*)res; -- fc->markNotFree(); -- assert(!fc->is_free(), "shouldn't be marked free"); -- assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized"); -- // Verify that the block offset table shows this to -- // be a single block, but not one which is unallocated. -- _bt.verify_single_block(res, size); -- _bt.verify_not_unallocated(res, size); -- // mangle a just allocated object with a distinct pattern. -- debug_only(fc->mangleAllocated(size)); -- } -- -- // During GC we do not need to recalculate the stable used value for -- // every allocation in old gen. It is done once at the end of GC instead -- // for performance reasons. -- if (!CMSHeap::heap()->is_gc_active()) { -- recalculate_used_stable(); -- } -- -- return res; --} -- --HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) { -- assert_lock_strong(freelistLock()); -- HeapWord* res = NULL; -- assert(size == adjustObjectSize(size), -- "use adjustObjectSize() before calling into allocate()"); -- -- // Strategy -- // if small -- // exact size from small object indexed list if small -- // small or large linear allocation block (linAB) as appropriate -- // take from lists of greater sized chunks -- // else -- // dictionary -- // small or large linear allocation block if it has the space -- // Try allocating exact size from indexTable first -- if (size < IndexSetSize) { -- res = (HeapWord*) getChunkFromIndexedFreeList(size); -- if(res != NULL) { -- assert(res != (HeapWord*)_indexedFreeList[size].head(), -- "Not removed from free list"); -- // no block offset table adjustment is necessary on blocks in -- // the indexed lists. -- -- // Try allocating from the small LinAB -- } else if (size < _smallLinearAllocBlock._allocation_size_limit && -- (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) { -- // if successful, the above also adjusts block offset table -- // Note that this call will refill the LinAB to -- // satisfy the request. This is different that -- // evm. -- // Don't record chunk off a LinAB? smallSplitBirth(size); -- } else { -- // Raid the exact free lists larger than size, even if they are not -- // overpopulated. -- res = (HeapWord*) getChunkFromGreater(size); -- } -- } else { -- // Big objects get allocated directly from the dictionary. -- res = (HeapWord*) getChunkFromDictionaryExact(size); -- if (res == NULL) { -- // Try hard not to fail since an allocation failure will likely -- // trigger a synchronous GC. Try to get the space from the -- // allocation blocks. -- res = getChunkFromSmallLinearAllocBlockRemainder(size); -- } -- } -- -- return res; --} -- --// A worst-case estimate of the space required (in HeapWords) to expand the heap --// when promoting obj. --size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const { -- // Depending on the object size, expansion may require refilling either a -- // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize -- // is added because the dictionary may over-allocate to avoid fragmentation. -- size_t space = obj_size; -- space += _promoInfo.refillSize() + 2 * MinChunkSize; -- return space; --} -- --FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) { -- FreeChunk* ret; -- -- assert(numWords >= MinChunkSize, "Size is less than minimum"); -- assert(linearAllocationWouldFail() || bestFitFirst(), -- "Should not be here"); -- -- size_t i; -- size_t currSize = numWords + MinChunkSize; -- assert(is_object_aligned(currSize), "currSize should be aligned"); -- for (i = currSize; i < IndexSetSize; i += IndexSetStride) { -- AdaptiveFreeList* fl = &_indexedFreeList[i]; -- if (fl->head()) { -- ret = getFromListGreater(fl, numWords); -- assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); -- return ret; -- } -- } -- -- currSize = MAX2((size_t)SmallForDictionary, -- (size_t)(numWords + MinChunkSize)); -- -- /* Try to get a chunk that satisfies request, while avoiding -- fragmentation that can't be handled. */ -- { -- ret = dictionary()->get_chunk(currSize); -- if (ret != NULL) { -- assert(ret->size() - numWords >= MinChunkSize, -- "Chunk is too small"); -- _bt.allocated((HeapWord*)ret, ret->size()); -- /* Carve returned chunk. */ -- (void) splitChunkAndReturnRemainder(ret, numWords); -- /* Label this as no longer a free chunk. */ -- assert(ret->is_free(), "This chunk should be free"); -- ret->link_prev(NULL); -- } -- assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); -- return ret; -- } -- ShouldNotReachHere(); --} -- --bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { -- assert(fc->size() < IndexSetSize, "Size of chunk is too large"); -- return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc); --} -- --bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { -- assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || -- (_smallLinearAllocBlock._word_size == fc->size()), -- "Linear allocation block shows incorrect size"); -- return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && -- (_smallLinearAllocBlock._word_size == fc->size())); --} -- --// Check if the purported free chunk is present either as a linear --// allocation block, the size-indexed table of (smaller) free blocks, --// or the larger free blocks kept in the binary tree dictionary. --bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const { -- if (verify_chunk_is_linear_alloc_block(fc)) { -- return true; -- } else if (fc->size() < IndexSetSize) { -- return verifyChunkInIndexedFreeLists(fc); -- } else { -- return dictionary()->verify_chunk_in_free_list(fc); -- } --} -- --#ifndef PRODUCT --void CompactibleFreeListSpace::assert_locked() const { -- CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock()); --} -- --void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const { -- CMSLockVerifier::assert_locked(lock); --} --#endif -- --FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { -- // In the parallel case, the main thread holds the free list lock -- // on behalf the parallel threads. -- FreeChunk* fc; -- { -- // If GC is parallel, this might be called by several threads. -- // This should be rare enough that the locking overhead won't affect -- // the sequential code. -- MutexLockerEx x(parDictionaryAllocLock(), -- Mutex::_no_safepoint_check_flag); -- fc = getChunkFromDictionary(size); -- } -- if (fc != NULL) { -- fc->dontCoalesce(); -- assert(fc->is_free(), "Should be free, but not coalescable"); -- // Verify that the block offset table shows this to -- // be a single block, but not one which is unallocated. -- _bt.verify_single_block((HeapWord*)fc, fc->size()); -- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -- } -- return fc; --} -- --oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) { -- assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); -- assert_locked(); -- -- // if we are tracking promotions, then first ensure space for -- // promotion (including spooling space for saving header if necessary). -- // then allocate and copy, then track promoted info if needed. -- // When tracking (see PromotionInfo::track()), the mark word may -- // be displaced and in this case restoration of the mark word -- // occurs in the (oop_since_save_marks_)iterate phase. -- if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) { -- return NULL; -- } -- // Call the allocate(size_t, bool) form directly to avoid the -- // additional call through the allocate(size_t) form. Having -- // the compile inline the call is problematic because allocate(size_t) -- // is a virtual method. -- HeapWord* res = allocate(adjustObjectSize(obj_size)); -- if (res != NULL) { -- Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size); -- // if we should be tracking promotions, do so. -- if (_promoInfo.tracking()) { -- _promoInfo.track((PromotedObject*)res); -- } -- } -- return oop(res); --} -- --HeapWord* --CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) { -- assert_locked(); -- assert(size >= MinChunkSize, "minimum chunk size"); -- assert(size < _smallLinearAllocBlock._allocation_size_limit, -- "maximum from smallLinearAllocBlock"); -- return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size); --} -- --HeapWord* --CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk, -- size_t size) { -- assert_locked(); -- assert(size >= MinChunkSize, "too small"); -- HeapWord* res = NULL; -- // Try to do linear allocation from blk, making sure that -- if (blk->_word_size == 0) { -- // We have probably been unable to fill this either in the prologue or -- // when it was exhausted at the last linear allocation. Bail out until -- // next time. -- assert(blk->_ptr == NULL, "consistency check"); -- return NULL; -- } -- assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check"); -- res = getChunkFromLinearAllocBlockRemainder(blk, size); -- if (res != NULL) return res; -- -- // about to exhaust this linear allocation block -- if (blk->_word_size == size) { // exactly satisfied -- res = blk->_ptr; -- _bt.allocated(res, blk->_word_size); -- } else if (size + MinChunkSize <= blk->_refillSize) { -- size_t sz = blk->_word_size; -- // Update _unallocated_block if the size is such that chunk would be -- // returned to the indexed free list. All other chunks in the indexed -- // free lists are allocated from the dictionary so that _unallocated_block -- // has already been adjusted for them. Do it here so that the cost -- // for all chunks added back to the indexed free lists. -- if (sz < SmallForDictionary) { -- _bt.allocated(blk->_ptr, sz); -- } -- // Return the chunk that isn't big enough, and then refill below. -- addChunkToFreeLists(blk->_ptr, sz); -- split_birth(sz); -- // Don't keep statistics on adding back chunk from a LinAB. -- } else { -- // A refilled block would not satisfy the request. -- return NULL; -- } -- -- blk->_ptr = NULL; blk->_word_size = 0; -- refillLinearAllocBlock(blk); -- assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, -- "block was replenished"); -- if (res != NULL) { -- split_birth(size); -- repairLinearAllocBlock(blk); -- } else if (blk->_ptr != NULL) { -- res = blk->_ptr; -- size_t blk_size = blk->_word_size; -- blk->_word_size -= size; -- blk->_ptr += size; -- split_birth(size); -- repairLinearAllocBlock(blk); -- // Update BOT last so that other (parallel) GC threads see a consistent -- // view of the BOT and free blocks. -- // Above must occur before BOT is updated below. -- OrderAccess::storestore(); -- _bt.split_block(res, blk_size, size); // adjust block offset table -- } -- return res; --} -- --HeapWord* CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder( -- LinearAllocBlock* blk, -- size_t size) { -- assert_locked(); -- assert(size >= MinChunkSize, "too small"); -- -- HeapWord* res = NULL; -- // This is the common case. Keep it simple. -- if (blk->_word_size >= size + MinChunkSize) { -- assert(blk->_ptr != NULL, "consistency check"); -- res = blk->_ptr; -- // Note that the BOT is up-to-date for the linAB before allocation. It -- // indicates the start of the linAB. The split_block() updates the -- // BOT for the linAB after the allocation (indicates the start of the -- // next chunk to be allocated). -- size_t blk_size = blk->_word_size; -- blk->_word_size -= size; -- blk->_ptr += size; -- split_birth(size); -- repairLinearAllocBlock(blk); -- // Update BOT last so that other (parallel) GC threads see a consistent -- // view of the BOT and free blocks. -- // Above must occur before BOT is updated below. -- OrderAccess::storestore(); -- _bt.split_block(res, blk_size, size); // adjust block offset table -- _bt.allocated(res, size); -- } -- return res; --} -- --FreeChunk* --CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) { -- assert_locked(); -- assert(size < SmallForDictionary, "just checking"); -- FreeChunk* res; -- res = _indexedFreeList[size].get_chunk_at_head(); -- if (res == NULL) { -- res = getChunkFromIndexedFreeListHelper(size); -- } -- _bt.verify_not_unallocated((HeapWord*) res, size); -- assert(res == NULL || res->size() == size, "Incorrect block size"); -- return res; --} -- --FreeChunk* --CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, -- bool replenish) { -- assert_locked(); -- FreeChunk* fc = NULL; -- if (size < SmallForDictionary) { -- assert(_indexedFreeList[size].head() == NULL || -- _indexedFreeList[size].surplus() <= 0, -- "List for this size should be empty or under populated"); -- // Try best fit in exact lists before replenishing the list -- if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) { -- // Replenish list. -- // -- // Things tried that failed. -- // Tried allocating out of the two LinAB's first before -- // replenishing lists. -- // Tried small linAB of size 256 (size in indexed list) -- // and replenishing indexed lists from the small linAB. -- // -- FreeChunk* newFc = NULL; -- const size_t replenish_size = CMSIndexedFreeListReplenish * size; -- if (replenish_size < SmallForDictionary) { -- // Do not replenish from an underpopulated size. -- if (_indexedFreeList[replenish_size].surplus() > 0 && -- _indexedFreeList[replenish_size].head() != NULL) { -- newFc = _indexedFreeList[replenish_size].get_chunk_at_head(); -- } else if (bestFitFirst()) { -- newFc = bestFitSmall(replenish_size); -- } -- } -- if (newFc == NULL && replenish_size > size) { -- assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant"); -- newFc = getChunkFromIndexedFreeListHelper(replenish_size, false); -- } -- // Note: The stats update re split-death of block obtained above -- // will be recorded below precisely when we know we are going to -- // be actually splitting it into more than one pieces below. -- if (newFc != NULL) { -- if (replenish || CMSReplenishIntermediate) { -- // Replenish this list and return one block to caller. -- size_t i; -- FreeChunk *curFc, *nextFc; -- size_t num_blk = newFc->size() / size; -- assert(num_blk >= 1, "Smaller than requested?"); -- assert(newFc->size() % size == 0, "Should be integral multiple of request"); -- if (num_blk > 1) { -- // we are sure we will be splitting the block just obtained -- // into multiple pieces; record the split-death of the original -- splitDeath(replenish_size); -- } -- // carve up and link blocks 0, ..., num_blk - 2 -- // The last chunk is not added to the lists but is returned as the -- // free chunk. -- for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), -- i = 0; -- i < (num_blk - 1); -- curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), -- i++) { -- curFc->set_size(size); -- // Don't record this as a return in order to try and -- // determine the "returns" from a GC. -- _bt.verify_not_unallocated((HeapWord*) fc, size); -- _indexedFreeList[size].return_chunk_at_tail(curFc, false); -- _bt.mark_block((HeapWord*)curFc, size); -- split_birth(size); -- // Don't record the initial population of the indexed list -- // as a split birth. -- } -- -- // check that the arithmetic was OK above -- assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, -- "inconsistency in carving newFc"); -- curFc->set_size(size); -- _bt.mark_block((HeapWord*)curFc, size); -- split_birth(size); -- fc = curFc; -- } else { -- // Return entire block to caller -- fc = newFc; -- } -- } -- } -- } else { -- // Get a free chunk from the free chunk dictionary to be returned to -- // replenish the indexed free list. -- fc = getChunkFromDictionaryExact(size); -- } -- // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk"); -- return fc; --} -- --FreeChunk* --CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { -- assert_locked(); -- FreeChunk* fc = _dictionary->get_chunk(size); -- if (fc == NULL) { -- return NULL; -- } -- _bt.allocated((HeapWord*)fc, fc->size()); -- if (fc->size() >= size + MinChunkSize) { -- fc = splitChunkAndReturnRemainder(fc, size); -- } -- assert(fc->size() >= size, "chunk too small"); -- assert(fc->size() < size + MinChunkSize, "chunk too big"); -- _bt.verify_single_block((HeapWord*)fc, fc->size()); -- return fc; --} -- --FreeChunk* --CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { -- assert_locked(); -- FreeChunk* fc = _dictionary->get_chunk(size); -- if (fc == NULL) { -- return fc; -- } -- _bt.allocated((HeapWord*)fc, fc->size()); -- if (fc->size() == size) { -- _bt.verify_single_block((HeapWord*)fc, size); -- return fc; -- } -- assert(fc->size() > size, "get_chunk() guarantee"); -- if (fc->size() < size + MinChunkSize) { -- // Return the chunk to the dictionary and go get a bigger one. -- returnChunkToDictionary(fc); -- fc = _dictionary->get_chunk(size + MinChunkSize); -- if (fc == NULL) { -- return NULL; -- } -- _bt.allocated((HeapWord*)fc, fc->size()); -- } -- assert(fc->size() >= size + MinChunkSize, "tautology"); -- fc = splitChunkAndReturnRemainder(fc, size); -- assert(fc->size() == size, "chunk is wrong size"); -- _bt.verify_single_block((HeapWord*)fc, size); -- return fc; --} -- --void --CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { -- assert_locked(); -- -- size_t size = chunk->size(); -- _bt.verify_single_block((HeapWord*)chunk, size); -- // adjust _unallocated_block downward, as necessary -- _bt.freed((HeapWord*)chunk, size); -- _dictionary->return_chunk(chunk); --#ifndef PRODUCT -- if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { -- TreeChunk >* tc = TreeChunk >::as_TreeChunk(chunk); -- TreeList >* tl = tc->list(); -- tl->verify_stats(); -- } --#endif // PRODUCT --} -- --void --CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { -- assert_locked(); -- size_t size = fc->size(); -- _bt.verify_single_block((HeapWord*) fc, size); -- _bt.verify_not_unallocated((HeapWord*) fc, size); -- _indexedFreeList[size].return_chunk_at_tail(fc); --#ifndef PRODUCT -- if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { -- _indexedFreeList[size].verify_stats(); -- } --#endif // PRODUCT --} -- --// Add chunk to end of last block -- if it's the largest --// block -- and update BOT and census data. We would --// of course have preferred to coalesce it with the --// last block, but it's currently less expensive to find the --// largest block than it is to find the last. --void --CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats( -- HeapWord* chunk, size_t size) { -- // check that the chunk does lie in this space! -- assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); -- // One of the parallel gc task threads may be here -- // whilst others are allocating. -- Mutex* lock = &_parDictionaryAllocLock; -- FreeChunk* ec; -- { -- MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); -- ec = dictionary()->find_largest_dict(); // get largest block -- if (ec != NULL && ec->end() == (uintptr_t*) chunk) { -- // It's a coterminal block - we can coalesce. -- size_t old_size = ec->size(); -- coalDeath(old_size); -- removeChunkFromDictionary(ec); -- size += old_size; -- } else { -- ec = (FreeChunk*)chunk; -- } -- } -- ec->set_size(size); -- debug_only(ec->mangleFreed(size)); -- if (size < SmallForDictionary) { -- lock = _indexedFreeListParLocks[size]; -- } -- MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); -- addChunkAndRepairOffsetTable((HeapWord*)ec, size, true); -- // record the birth under the lock since the recording involves -- // manipulation of the list on which the chunk lives and -- // if the chunk is allocated and is the last on the list, -- // the list can go away. -- coalBirth(size); --} -- --void --CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk, -- size_t size) { -- // check that the chunk does lie in this space! -- assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); -- assert_locked(); -- _bt.verify_single_block(chunk, size); -- -- FreeChunk* fc = (FreeChunk*) chunk; -- fc->set_size(size); -- debug_only(fc->mangleFreed(size)); -- if (size < SmallForDictionary) { -- returnChunkToFreeList(fc); -- } else { -- returnChunkToDictionary(fc); -- } --} -- --void --CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk, -- size_t size, bool coalesced) { -- assert_locked(); -- assert(chunk != NULL, "null chunk"); -- if (coalesced) { -- // repair BOT -- _bt.single_block(chunk, size); -- } -- addChunkToFreeLists(chunk, size); --} -- --// We _must_ find the purported chunk on our free lists; --// we assert if we don't. --void --CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) { -- size_t size = fc->size(); -- assert_locked(); -- debug_only(verifyFreeLists()); -- if (size < SmallForDictionary) { -- removeChunkFromIndexedFreeList(fc); -- } else { -- removeChunkFromDictionary(fc); -- } -- _bt.verify_single_block((HeapWord*)fc, size); -- debug_only(verifyFreeLists()); --} -- --void --CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) { -- size_t size = fc->size(); -- assert_locked(); -- assert(fc != NULL, "null chunk"); -- _bt.verify_single_block((HeapWord*)fc, size); -- _dictionary->remove_chunk(fc); -- // adjust _unallocated_block upward, as necessary -- _bt.allocated((HeapWord*)fc, size); --} -- --void --CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) { -- assert_locked(); -- size_t size = fc->size(); -- _bt.verify_single_block((HeapWord*)fc, size); -- NOT_PRODUCT( -- if (FLSVerifyIndexTable) { -- verifyIndexedFreeList(size); -- } -- ) -- _indexedFreeList[size].remove_chunk(fc); -- NOT_PRODUCT( -- if (FLSVerifyIndexTable) { -- verifyIndexedFreeList(size); -- } -- ) --} -- --FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) { -- /* A hint is the next larger size that has a surplus. -- Start search at a size large enough to guarantee that -- the excess is >= MIN_CHUNK. */ -- size_t start = align_object_size(numWords + MinChunkSize); -- if (start < IndexSetSize) { -- AdaptiveFreeList* it = _indexedFreeList; -- size_t hint = _indexedFreeList[start].hint(); -- while (hint < IndexSetSize) { -- assert(is_object_aligned(hint), "hint should be aligned"); -- AdaptiveFreeList *fl = &_indexedFreeList[hint]; -- if (fl->surplus() > 0 && fl->head() != NULL) { -- // Found a list with surplus, reset original hint -- // and split out a free chunk which is returned. -- _indexedFreeList[start].set_hint(hint); -- FreeChunk* res = getFromListGreater(fl, numWords); -- assert(res == NULL || res->is_free(), -- "Should be returning a free chunk"); -- return res; -- } -- hint = fl->hint(); /* keep looking */ -- } -- /* None found. */ -- it[start].set_hint(IndexSetSize); -- } -- return NULL; --} -- --/* Requires fl->size >= numWords + MinChunkSize */ --FreeChunk* CompactibleFreeListSpace::getFromListGreater(AdaptiveFreeList* fl, -- size_t numWords) { -- FreeChunk *curr = fl->head(); -- size_t oldNumWords = curr->size(); -- assert(numWords >= MinChunkSize, "Word size is too small"); -- assert(curr != NULL, "List is empty"); -- assert(oldNumWords >= numWords + MinChunkSize, -- "Size of chunks in the list is too small"); -- -- fl->remove_chunk(curr); -- // recorded indirectly by splitChunkAndReturnRemainder - -- // smallSplit(oldNumWords, numWords); -- FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); -- // Does anything have to be done for the remainder in terms of -- // fixing the card table? -- assert(new_chunk == NULL || new_chunk->is_free(), -- "Should be returning a free chunk"); -- return new_chunk; --} -- --FreeChunk* --CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk, -- size_t new_size) { -- assert_locked(); -- size_t size = chunk->size(); -- assert(size > new_size, "Split from a smaller block?"); -- assert(is_aligned(chunk), "alignment problem"); -- assert(size == adjustObjectSize(size), "alignment problem"); -- size_t rem_sz = size - new_size; -- assert(rem_sz == adjustObjectSize(rem_sz), "alignment problem"); -- assert(rem_sz >= MinChunkSize, "Free chunk smaller than minimum"); -- FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); -- assert(is_aligned(ffc), "alignment problem"); -- ffc->set_size(rem_sz); -- ffc->link_next(NULL); -- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -- // Above must occur before BOT is updated below. -- // adjust block offset table -- OrderAccess::storestore(); -- assert(chunk->is_free() && ffc->is_free(), "Error"); -- _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); -- if (rem_sz < SmallForDictionary) { -- // The freeList lock is held, but multiple GC task threads might be executing in parallel. -- bool is_par = Thread::current()->is_GC_task_thread(); -- if (is_par) _indexedFreeListParLocks[rem_sz]->lock(); -- returnChunkToFreeList(ffc); -- split(size, rem_sz); -- if (is_par) _indexedFreeListParLocks[rem_sz]->unlock(); -- } else { -- returnChunkToDictionary(ffc); -- split(size, rem_sz); -- } -- chunk->set_size(new_size); -- return chunk; --} -- --void --CompactibleFreeListSpace::sweep_completed() { -- // Now that space is probably plentiful, refill linear -- // allocation blocks as needed. -- refillLinearAllocBlocksIfNeeded(); --} -- --void --CompactibleFreeListSpace::gc_prologue() { -- assert_locked(); -- reportFreeListStatistics("Before GC:"); -- refillLinearAllocBlocksIfNeeded(); --} -- --void --CompactibleFreeListSpace::gc_epilogue() { -- assert_locked(); -- assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); -- _promoInfo.stopTrackingPromotions(); -- repairLinearAllocationBlocks(); -- reportFreeListStatistics("After GC:"); --} -- --// Iteration support, mostly delegated from a CMS generation -- --void CompactibleFreeListSpace::save_marks() { -- assert(Thread::current()->is_VM_thread(), -- "Global variable should only be set when single-threaded"); -- // Mark the "end" of the used space at the time of this call; -- // note, however, that promoted objects from this point -- // on are tracked in the _promoInfo below. -- set_saved_mark_word(unallocated_block()); --#ifdef ASSERT -- // Check the sanity of save_marks() etc. -- MemRegion ur = used_region(); -- MemRegion urasm = used_region_at_save_marks(); -- assert(ur.contains(urasm), -- " Error at save_marks(): [" PTR_FORMAT "," PTR_FORMAT ")" -- " should contain [" PTR_FORMAT "," PTR_FORMAT ")", -- p2i(ur.start()), p2i(ur.end()), p2i(urasm.start()), p2i(urasm.end())); --#endif -- // inform allocator that promotions should be tracked. -- assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); -- _promoInfo.startTrackingPromotions(); --} -- --bool CompactibleFreeListSpace::no_allocs_since_save_marks() { -- assert(_promoInfo.tracking(), "No preceding save_marks?"); -- return _promoInfo.noPromotions(); --} -- --bool CompactibleFreeListSpace::linearAllocationWouldFail() const { -- return _smallLinearAllocBlock._word_size == 0; --} -- --void CompactibleFreeListSpace::repairLinearAllocationBlocks() { -- // Fix up linear allocation blocks to look like free blocks -- repairLinearAllocBlock(&_smallLinearAllocBlock); --} -- --void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) { -- assert_locked(); -- if (blk->_ptr != NULL) { -- assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize, -- "Minimum block size requirement"); -- FreeChunk* fc = (FreeChunk*)(blk->_ptr); -- fc->set_size(blk->_word_size); -- fc->link_prev(NULL); // mark as free -- fc->dontCoalesce(); -- assert(fc->is_free(), "just marked it free"); -- assert(fc->cantCoalesce(), "just marked it uncoalescable"); -- } --} -- --void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() { -- assert_locked(); -- if (_smallLinearAllocBlock._ptr == NULL) { -- assert(_smallLinearAllocBlock._word_size == 0, -- "Size of linAB should be zero if the ptr is NULL"); -- // Reset the linAB refill and allocation size limit. -- _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc); -- } -- refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock); --} -- --void --CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) { -- assert_locked(); -- assert((blk->_ptr == NULL && blk->_word_size == 0) || -- (blk->_ptr != NULL && blk->_word_size >= MinChunkSize), -- "blk invariant"); -- if (blk->_ptr == NULL) { -- refillLinearAllocBlock(blk); -- } --} -- --void --CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) { -- assert_locked(); -- assert(blk->_word_size == 0 && blk->_ptr == NULL, -- "linear allocation block should be empty"); -- FreeChunk* fc; -- if (blk->_refillSize < SmallForDictionary && -- (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) { -- // A linAB's strategy might be to use small sizes to reduce -- // fragmentation but still get the benefits of allocation from a -- // linAB. -- } else { -- fc = getChunkFromDictionary(blk->_refillSize); -- } -- if (fc != NULL) { -- blk->_ptr = (HeapWord*)fc; -- blk->_word_size = fc->size(); -- fc->dontCoalesce(); // to prevent sweeper from sweeping us up -- } --} -- --// Support for compaction --void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { -- scan_and_forward(this, cp, false); -- // of the free lists doesn't work after. -- // Prepare_for_compaction() uses the space between live objects -- // so that later phase can skip dead space quickly. So verification -- // of the free lists doesn't work after. --} -- --void CompactibleFreeListSpace::adjust_pointers() { -- // In other versions of adjust_pointers(), a bail out -- // based on the amount of live data in the generation -- // (i.e., if 0, bail out) may be used. -- // Cannot test used() == 0 here because the free lists have already -- // been mangled by the compaction. -- -- scan_and_adjust_pointers(this); -- // See note about verification in prepare_for_compaction(). --} -- --void CompactibleFreeListSpace::compact() { -- scan_and_compact(this, false); --} -- --// Fragmentation metric = 1 - [sum of (fbs**2) / (sum of fbs)**2] --// where fbs is free block sizes --double CompactibleFreeListSpace::flsFrag() const { -- size_t itabFree = totalSizeInIndexedFreeLists(); -- double frag = 0.0; -- size_t i; -- -- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- double sz = i; -- frag += _indexedFreeList[i].count() * (sz * sz); -- } -- -- double totFree = itabFree + -- _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); -- if (totFree > 0) { -- frag = ((frag + _dictionary->sum_of_squared_block_sizes()) / -- (totFree * totFree)); -- frag = (double)1.0 - frag; -- } else { -- assert(frag == 0.0, "Follows from totFree == 0"); -- } -- return frag; --} -- --void CompactibleFreeListSpace::beginSweepFLCensus( -- float inter_sweep_current, -- float inter_sweep_estimate, -- float intra_sweep_estimate) { -- assert_locked(); -- size_t i; -- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- AdaptiveFreeList* fl = &_indexedFreeList[i]; -- log_trace(gc, freelist)("size[" SIZE_FORMAT "] : ", i); -- fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); -- fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); -- fl->set_before_sweep(fl->count()); -- fl->set_bfr_surp(fl->surplus()); -- } -- _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent, -- inter_sweep_current, -- inter_sweep_estimate, -- intra_sweep_estimate); --} -- --void CompactibleFreeListSpace::setFLSurplus() { -- assert_locked(); -- size_t i; -- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- AdaptiveFreeList *fl = &_indexedFreeList[i]; -- fl->set_surplus(fl->count() - -- (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); -- } --} -- --void CompactibleFreeListSpace::setFLHints() { -- assert_locked(); -- size_t i; -- size_t h = IndexSetSize; -- for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { -- AdaptiveFreeList *fl = &_indexedFreeList[i]; -- fl->set_hint(h); -- if (fl->surplus() > 0) { -- h = i; -- } -- } --} -- --void CompactibleFreeListSpace::clearFLCensus() { -- assert_locked(); -- size_t i; -- for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- AdaptiveFreeList *fl = &_indexedFreeList[i]; -- fl->set_prev_sweep(fl->count()); -- fl->set_coal_births(0); -- fl->set_coal_deaths(0); -- fl->set_split_births(0); -- fl->set_split_deaths(0); -- } --} -- --void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { -- log_debug(gc, freelist)("CMS: Large block " PTR_FORMAT, p2i(dictionary()->find_largest_dict())); -- setFLSurplus(); -- setFLHints(); -- printFLCensus(sweep_count); -- clearFLCensus(); -- assert_locked(); -- _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); --} -- --bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { -- if (size < SmallForDictionary) { -- AdaptiveFreeList *fl = &_indexedFreeList[size]; -- return (fl->coal_desired() < 0) || -- ((int)fl->count() > fl->coal_desired()); -- } else { -- return dictionary()->coal_dict_over_populated(size); -- } --} -- --void CompactibleFreeListSpace::smallCoalBirth(size_t size) { -- assert(size < SmallForDictionary, "Size too large for indexed list"); -- AdaptiveFreeList *fl = &_indexedFreeList[size]; -- fl->increment_coal_births(); -- fl->increment_surplus(); --} -- --void CompactibleFreeListSpace::smallCoalDeath(size_t size) { -- assert(size < SmallForDictionary, "Size too large for indexed list"); -- AdaptiveFreeList *fl = &_indexedFreeList[size]; -- fl->increment_coal_deaths(); -- fl->decrement_surplus(); --} -- --void CompactibleFreeListSpace::coalBirth(size_t size) { -- if (size < SmallForDictionary) { -- smallCoalBirth(size); -- } else { -- dictionary()->dict_census_update(size, -- false /* split */, -- true /* birth */); -- } --} -- --void CompactibleFreeListSpace::coalDeath(size_t size) { -- if(size < SmallForDictionary) { -- smallCoalDeath(size); -- } else { -- dictionary()->dict_census_update(size, -- false /* split */, -- false /* birth */); -- } --} -- --void CompactibleFreeListSpace::smallSplitBirth(size_t size) { -- assert(size < SmallForDictionary, "Size too large for indexed list"); -- AdaptiveFreeList *fl = &_indexedFreeList[size]; -- fl->increment_split_births(); -- fl->increment_surplus(); --} -- --void CompactibleFreeListSpace::smallSplitDeath(size_t size) { -- assert(size < SmallForDictionary, "Size too large for indexed list"); -- AdaptiveFreeList *fl = &_indexedFreeList[size]; -- fl->increment_split_deaths(); -- fl->decrement_surplus(); --} -- --void CompactibleFreeListSpace::split_birth(size_t size) { -- if (size < SmallForDictionary) { -- smallSplitBirth(size); -- } else { -- dictionary()->dict_census_update(size, -- true /* split */, -- true /* birth */); -- } --} -- --void CompactibleFreeListSpace::splitDeath(size_t size) { -- if (size < SmallForDictionary) { -- smallSplitDeath(size); -- } else { -- dictionary()->dict_census_update(size, -- true /* split */, -- false /* birth */); -- } --} -- --void CompactibleFreeListSpace::split(size_t from, size_t to1) { -- size_t to2 = from - to1; -- splitDeath(from); -- split_birth(to1); -- split_birth(to2); --} -- --void CompactibleFreeListSpace::print() const { -- print_on(tty); --} -- --void CompactibleFreeListSpace::prepare_for_verify() { -- assert_locked(); -- repairLinearAllocationBlocks(); -- // Verify that the SpoolBlocks look like free blocks of -- // appropriate sizes... To be done ... --} -- --class VerifyAllBlksClosure: public BlkClosure { -- private: -- const CompactibleFreeListSpace* _sp; -- const MemRegion _span; -- HeapWord* _last_addr; -- size_t _last_size; -- bool _last_was_obj; -- bool _last_was_live; -- -- public: -- VerifyAllBlksClosure(const CompactibleFreeListSpace* sp, -- MemRegion span) : _sp(sp), _span(span), -- _last_addr(NULL), _last_size(0), -- _last_was_obj(false), _last_was_live(false) { } -- -- virtual size_t do_blk(HeapWord* addr) { -- size_t res; -- bool was_obj = false; -- bool was_live = false; -- if (_sp->block_is_obj(addr)) { -- was_obj = true; -- oop p = oop(addr); -- guarantee(oopDesc::is_oop(p), "Should be an oop"); -- res = _sp->adjustObjectSize(p->size()); -- if (_sp->obj_is_alive(addr)) { -- was_live = true; -- p->verify(); -- } -- } else { -- FreeChunk* fc = (FreeChunk*)addr; -- res = fc->size(); -- if (FLSVerifyLists && !fc->cantCoalesce()) { -- guarantee(_sp->verify_chunk_in_free_list(fc), -- "Chunk should be on a free list"); -- } -- } -- if (res == 0) { -- Log(gc, verify) log; -- log.error("Livelock: no rank reduction!"); -- log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n" -- " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n", -- p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false", -- p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false"); -- LogStream ls(log.error()); -- _sp->print_on(&ls); -- guarantee(false, "Verification failed."); -- } -- _last_addr = addr; -- _last_size = res; -- _last_was_obj = was_obj; -- _last_was_live = was_live; -- return res; -- } --}; -- --class VerifyAllOopsClosure: public BasicOopIterateClosure { -- private: -- const CMSCollector* _collector; -- const CompactibleFreeListSpace* _sp; -- const MemRegion _span; -- const bool _past_remark; -- const CMSBitMap* _bit_map; -- -- protected: -- void do_oop(void* p, oop obj) { -- if (_span.contains(obj)) { // the interior oop points into CMS heap -- if (!_span.contains(p)) { // reference from outside CMS heap -- // Should be a valid object; the first disjunct below allows -- // us to sidestep an assertion in block_is_obj() that insists -- // that p be in _sp. Note that several generations (and spaces) -- // are spanned by _span (CMS heap) above. -- guarantee(!_sp->is_in_reserved(obj) || -- _sp->block_is_obj((HeapWord*)obj), -- "Should be an object"); -- guarantee(oopDesc::is_oop(obj), "Should be an oop"); -- obj->verify(); -- if (_past_remark) { -- // Remark has been completed, the object should be marked -- _bit_map->isMarked((HeapWord*)obj); -- } -- } else { // reference within CMS heap -- if (_past_remark) { -- // Remark has been completed -- so the referent should have -- // been marked, if referring object is. -- if (_bit_map->isMarked(_collector->block_start(p))) { -- guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?"); -- } -- } -- } -- } else if (_sp->is_in_reserved(p)) { -- // the reference is from FLS, and points out of FLS -- guarantee(oopDesc::is_oop(obj), "Should be an oop"); -- obj->verify(); -- } -- } -- -- template void do_oop_work(T* p) { -- T heap_oop = RawAccess<>::oop_load(p); -- if (!CompressedOops::is_null(heap_oop)) { -- oop obj = CompressedOops::decode_not_null(heap_oop); -- do_oop(p, obj); -- } -- } -- -- public: -- VerifyAllOopsClosure(const CMSCollector* collector, -- const CompactibleFreeListSpace* sp, MemRegion span, -- bool past_remark, CMSBitMap* bit_map) : -- _collector(collector), _sp(sp), _span(span), -- _past_remark(past_remark), _bit_map(bit_map) { } -- -- virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); } -- virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); } --}; -- --void CompactibleFreeListSpace::verify() const { -- assert_lock_strong(&_freelistLock); -- verify_objects_initialized(); -- MemRegion span = _collector->_span; -- bool past_remark = (_collector->abstract_state() == -- CMSCollector::Sweeping); -- -- ResourceMark rm; -- HandleMark hm; -- -- // Check integrity of CFL data structures -- _promoInfo.verify(); -- _dictionary->verify(); -- if (FLSVerifyIndexTable) { -- verifyIndexedFreeLists(); -- } -- // Check integrity of all objects and free blocks in space -- { -- VerifyAllBlksClosure cl(this, span); -- ((CompactibleFreeListSpace*)this)->blk_iterate(&cl); // cast off const -- } -- // Check that all references in the heap to FLS -- // are to valid objects in FLS or that references in -- // FLS are to valid objects elsewhere in the heap -- if (FLSVerifyAllHeapReferences) -- { -- VerifyAllOopsClosure cl(_collector, this, span, past_remark, -- _collector->markBitMap()); -- -- // Iterate over all oops in the heap. -- CMSHeap::heap()->oop_iterate(&cl); -- } -- -- if (VerifyObjectStartArray) { -- // Verify the block offset table -- _bt.verify(); -- } --} -- --#ifndef PRODUCT --void CompactibleFreeListSpace::verifyFreeLists() const { -- if (FLSVerifyLists) { -- _dictionary->verify(); -- verifyIndexedFreeLists(); -- } else { -- if (FLSVerifyDictionary) { -- _dictionary->verify(); -- } -- if (FLSVerifyIndexTable) { -- verifyIndexedFreeLists(); -- } -- } --} --#endif -- --void CompactibleFreeListSpace::verifyIndexedFreeLists() const { -- size_t i = 0; -- for (; i < IndexSetStart; i++) { -- guarantee(_indexedFreeList[i].head() == NULL, "should be NULL"); -- } -- for (; i < IndexSetSize; i++) { -- verifyIndexedFreeList(i); -- } --} -- --void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { -- FreeChunk* fc = _indexedFreeList[size].head(); -- FreeChunk* tail = _indexedFreeList[size].tail(); -- size_t num = _indexedFreeList[size].count(); -- size_t n = 0; -- guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, -- "Slot should have been empty"); -- for (; fc != NULL; fc = fc->next(), n++) { -- guarantee(fc->size() == size, "Size inconsistency"); -- guarantee(fc->is_free(), "!free?"); -- guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); -- guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); -- } -- guarantee(n == num, "Incorrect count"); --} -- --#ifndef PRODUCT --void CompactibleFreeListSpace::check_free_list_consistency() const { -- assert((TreeChunk >::min_size() <= IndexSetSize), -- "Some sizes can't be allocated without recourse to" -- " linear allocation buffers"); -- assert((TreeChunk >::min_size()*HeapWordSize == sizeof(TreeChunk >)), -- "else MIN_TREE_CHUNK_SIZE is wrong"); -- assert(IndexSetStart != 0, "IndexSetStart not initialized"); -- assert(IndexSetStride != 0, "IndexSetStride not initialized"); --} --#endif -- --void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { -- assert_lock_strong(&_freelistLock); -- LogTarget(Debug, gc, freelist, census) log; -- if (!log.is_enabled()) { -- return; -- } -- AdaptiveFreeList total; -- log.print("end sweep# " SIZE_FORMAT, sweep_count); -- ResourceMark rm; -- LogStream ls(log); -- outputStream* out = &ls; -- AdaptiveFreeList::print_labels_on(out, "size"); -- size_t total_free = 0; -- for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { -- const AdaptiveFreeList *fl = &_indexedFreeList[i]; -- total_free += fl->count() * fl->size(); -- if (i % (40*IndexSetStride) == 0) { -- AdaptiveFreeList::print_labels_on(out, "size"); -- } -- fl->print_on(out); -- total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); -- total.set_surplus( total.surplus() + fl->surplus() ); -- total.set_desired( total.desired() + fl->desired() ); -- total.set_prev_sweep( total.prev_sweep() + fl->prev_sweep() ); -- total.set_before_sweep(total.before_sweep() + fl->before_sweep()); -- total.set_count( total.count() + fl->count() ); -- total.set_coal_births( total.coal_births() + fl->coal_births() ); -- total.set_coal_deaths( total.coal_deaths() + fl->coal_deaths() ); -- total.set_split_births(total.split_births() + fl->split_births()); -- total.set_split_deaths(total.split_deaths() + fl->split_deaths()); -- } -- total.print_on(out, "TOTAL"); -- log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free); -- log.print("growth: %8.5f deficit: %8.5f", -- (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ -- (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), -- (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); -- _dictionary->print_dict_census(out); --} -- --/////////////////////////////////////////////////////////////////////////// --// CompactibleFreeListSpaceLAB --/////////////////////////////////////////////////////////////////////////// -- --#define VECTOR_257(x) \ -- /* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \ -- { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ -- x } -- --// Initialize with default setting for CMS, _not_ --// generic OldPLABSize, whose static default is different; if overridden at the --// command-line, this will get reinitialized via a call to --// modify_initialization() below. --AdaptiveWeightedAverage CompactibleFreeListSpaceLAB::_blocks_to_claim[] = -- VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CompactibleFreeListSpaceLAB::_default_dynamic_old_plab_size)); --size_t CompactibleFreeListSpaceLAB::_global_num_blocks[] = VECTOR_257(0); --uint CompactibleFreeListSpaceLAB::_global_num_workers[] = VECTOR_257(0); -- --CompactibleFreeListSpaceLAB::CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls) : -- _cfls(cfls) --{ -- assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above"); -- for (size_t i = CompactibleFreeListSpace::IndexSetStart; -- i < CompactibleFreeListSpace::IndexSetSize; -- i += CompactibleFreeListSpace::IndexSetStride) { -- _indexedFreeList[i].set_size(i); -- _num_blocks[i] = 0; -- } --} -- --static bool _CFLS_LAB_modified = false; -- --void CompactibleFreeListSpaceLAB::modify_initialization(size_t n, unsigned wt) { -- assert(!_CFLS_LAB_modified, "Call only once"); -- _CFLS_LAB_modified = true; -- for (size_t i = CompactibleFreeListSpace::IndexSetStart; -- i < CompactibleFreeListSpace::IndexSetSize; -- i += CompactibleFreeListSpace::IndexSetStride) { -- _blocks_to_claim[i].modify(n, wt, true /* force */); -- } --} -- --HeapWord* CompactibleFreeListSpaceLAB::alloc(size_t word_sz) { -- FreeChunk* res; -- assert(word_sz == _cfls->adjustObjectSize(word_sz), "Error"); -- if (word_sz >= CompactibleFreeListSpace::IndexSetSize) { -- // This locking manages sync with other large object allocations. -- MutexLockerEx x(_cfls->parDictionaryAllocLock(), -- Mutex::_no_safepoint_check_flag); -- res = _cfls->getChunkFromDictionaryExact(word_sz); -- if (res == NULL) return NULL; -- } else { -- AdaptiveFreeList* fl = &_indexedFreeList[word_sz]; -- if (fl->count() == 0) { -- // Attempt to refill this local free list. -- get_from_global_pool(word_sz, fl); -- // If it didn't work, give up. -- if (fl->count() == 0) return NULL; -- } -- res = fl->get_chunk_at_head(); -- assert(res != NULL, "Why was count non-zero?"); -- } -- res->markNotFree(); -- assert(!res->is_free(), "shouldn't be marked free"); -- assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); -- // mangle a just allocated object with a distinct pattern. -- debug_only(res->mangleAllocated(word_sz)); -- return (HeapWord*)res; --} -- --// Get a chunk of blocks of the right size and update related --// book-keeping stats --void CompactibleFreeListSpaceLAB::get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl) { -- // Get the #blocks we want to claim -- size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); -- assert(n_blks > 0, "Error"); -- assert(ResizeOldPLAB || n_blks == OldPLABSize, "Error"); -- // In some cases, when the application has a phase change, -- // there may be a sudden and sharp shift in the object survival -- // profile, and updating the counts at the end of a scavenge -- // may not be quick enough, giving rise to large scavenge pauses -- // during these phase changes. It is beneficial to detect such -- // changes on-the-fly during a scavenge and avoid such a phase-change -- // pothole. The following code is a heuristic attempt to do that. -- // It is protected by a product flag until we have gained -- // enough experience with this heuristic and fine-tuned its behavior. -- // WARNING: This might increase fragmentation if we overreact to -- // small spikes, so some kind of historical smoothing based on -- // previous experience with the greater reactivity might be useful. -- // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by -- // default. -- if (ResizeOldPLAB && CMSOldPLABResizeQuicker) { -- // -- // On a 32-bit VM, the denominator can become zero because of integer overflow, -- // which is why there is a cast to double. -- // -- size_t multiple = (size_t) (_num_blocks[word_sz]/(((double)CMSOldPLABToleranceFactor)*CMSOldPLABNumRefills*n_blks)); -- n_blks += CMSOldPLABReactivityFactor*multiple*n_blks; -- n_blks = MIN2(n_blks, CMSOldPLABMax); -- } -- assert(n_blks > 0, "Error"); -- _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl); -- // Update stats table entry for this block size -- _num_blocks[word_sz] += fl->count(); --} -- --void CompactibleFreeListSpaceLAB::compute_desired_plab_size() { -- for (size_t i = CompactibleFreeListSpace::IndexSetStart; -- i < CompactibleFreeListSpace::IndexSetSize; -- i += CompactibleFreeListSpace::IndexSetStride) { -- assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0), -- "Counter inconsistency"); -- if (_global_num_workers[i] > 0) { -- // Need to smooth wrt historical average -- if (ResizeOldPLAB) { -- _blocks_to_claim[i].sample( -- MAX2(CMSOldPLABMin, -- MIN2(CMSOldPLABMax, -- _global_num_blocks[i]/_global_num_workers[i]/CMSOldPLABNumRefills))); -- } -- // Reset counters for next round -- _global_num_workers[i] = 0; -- _global_num_blocks[i] = 0; -- log_trace(gc, plab)("[" SIZE_FORMAT "]: " SIZE_FORMAT, i, (size_t)_blocks_to_claim[i].average()); -- } -- } --} -- --// If this is changed in the future to allow parallel --// access, one would need to take the FL locks and, --// depending on how it is used, stagger access from --// parallel threads to reduce contention. --void CompactibleFreeListSpaceLAB::retire(int tid) { -- // We run this single threaded with the world stopped; -- // so no need for locks and such. -- NOT_PRODUCT(Thread* t = Thread::current();) -- assert(Thread::current()->is_VM_thread(), "Error"); -- for (size_t i = CompactibleFreeListSpace::IndexSetStart; -- i < CompactibleFreeListSpace::IndexSetSize; -- i += CompactibleFreeListSpace::IndexSetStride) { -- assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), -- "Can't retire more than what we obtained"); -- if (_num_blocks[i] > 0) { -- size_t num_retire = _indexedFreeList[i].count(); -- assert(_num_blocks[i] > num_retire, "Should have used at least one"); -- { -- // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], -- // Mutex::_no_safepoint_check_flag); -- -- // Update globals stats for num_blocks used -- _global_num_blocks[i] += (_num_blocks[i] - num_retire); -- _global_num_workers[i]++; -- assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); -- if (num_retire > 0) { -- _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); -- // Reset this list. -- _indexedFreeList[i] = AdaptiveFreeList(); -- _indexedFreeList[i].set_size(i); -- } -- } -- log_trace(gc, plab)("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT, -- tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); -- // Reset stats for next round -- _num_blocks[i] = 0; -- } -- } --} -- --// Used by par_get_chunk_of_blocks() for the chunks from the --// indexed_free_lists. Looks for a chunk with size that is a multiple --// of "word_sz" and if found, splits it into "word_sz" chunks and add --// to the free list "fl". "n" is the maximum number of chunks to --// be added to "fl". --bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl) { -- -- // We'll try all multiples of word_sz in the indexed set, starting with -- // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, -- // then try getting a big chunk and splitting it. -- { -- bool found; -- int k; -- size_t cur_sz; -- for (k = 1, cur_sz = k * word_sz, found = false; -- (cur_sz < CompactibleFreeListSpace::IndexSetSize) && -- (CMSSplitIndexedFreeListBlocks || k <= 1); -- k++, cur_sz = k * word_sz) { -- AdaptiveFreeList fl_for_cur_sz; // Empty. -- fl_for_cur_sz.set_size(cur_sz); -- { -- MutexLockerEx x(_indexedFreeListParLocks[cur_sz], -- Mutex::_no_safepoint_check_flag); -- AdaptiveFreeList* gfl = &_indexedFreeList[cur_sz]; -- if (gfl->count() != 0) { -- // nn is the number of chunks of size cur_sz that -- // we'd need to split k-ways each, in order to create -- // "n" chunks of size word_sz each. -- const size_t nn = MAX2(n/k, (size_t)1); -- gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); -- found = true; -- if (k > 1) { -- // Update split death stats for the cur_sz-size blocks list: -- // we increment the split death count by the number of blocks -- // we just took from the cur_sz-size blocks list and which -- // we will be splitting below. -- ssize_t deaths = gfl->split_deaths() + -- fl_for_cur_sz.count(); -- gfl->set_split_deaths(deaths); -- } -- } -- } -- // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. -- if (found) { -- if (k == 1) { -- fl->prepend(&fl_for_cur_sz); -- } else { -- // Divide each block on fl_for_cur_sz up k ways. -- FreeChunk* fc; -- while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) { -- // Must do this in reverse order, so that anybody attempting to -- // access the main chunk sees it as a single free block until we -- // change it. -- size_t fc_size = fc->size(); -- assert(fc->is_free(), "Error"); -- for (int i = k-1; i >= 0; i--) { -- FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); -- assert((i != 0) || -- ((fc == ffc) && ffc->is_free() && -- (ffc->size() == k*word_sz) && (fc_size == word_sz)), -- "Counting error"); -- ffc->set_size(word_sz); -- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -- ffc->link_next(NULL); -- // Above must occur before BOT is updated below. -- OrderAccess::storestore(); -- // splitting from the right, fc_size == i * word_sz -- _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); -- fc_size -= word_sz; -- assert(fc_size == i*word_sz, "Error"); -- _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); -- _bt.verify_single_block((HeapWord*)fc, fc_size); -- _bt.verify_single_block((HeapWord*)ffc, word_sz); -- // Push this on "fl". -- fl->return_chunk_at_head(ffc); -- } -- // TRAP -- assert(fl->tail()->next() == NULL, "List invariant."); -- } -- } -- // Update birth stats for this block size. -- size_t num = fl->count(); -- MutexLockerEx x(_indexedFreeListParLocks[word_sz], -- Mutex::_no_safepoint_check_flag); -- ssize_t births = _indexedFreeList[word_sz].split_births() + num; -- _indexedFreeList[word_sz].set_split_births(births); -- return true; -- } -- } -- return found; -- } --} -- --FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { -- -- FreeChunk* fc = NULL; -- FreeChunk* rem_fc = NULL; -- size_t rem; -- { -- MutexLockerEx x(parDictionaryAllocLock(), -- Mutex::_no_safepoint_check_flag); -- while (n > 0) { -- fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size())); -- if (fc != NULL) { -- break; -- } else { -- n--; -- } -- } -- if (fc == NULL) return NULL; -- // Otherwise, split up that block. -- assert((ssize_t)n >= 1, "Control point invariant"); -- assert(fc->is_free(), "Error: should be a free block"); -- _bt.verify_single_block((HeapWord*)fc, fc->size()); -- const size_t nn = fc->size() / word_sz; -- n = MIN2(nn, n); -- assert((ssize_t)n >= 1, "Control point invariant"); -- rem = fc->size() - n * word_sz; -- // If there is a remainder, and it's too small, allocate one fewer. -- if (rem > 0 && rem < MinChunkSize) { -- n--; rem += word_sz; -- } -- // Note that at this point we may have n == 0. -- assert((ssize_t)n >= 0, "Control point invariant"); -- -- // If n is 0, the chunk fc that was found is not large -- // enough to leave a viable remainder. We are unable to -- // allocate even one block. Return fc to the -- // dictionary and return, leaving "fl" empty. -- if (n == 0) { -- returnChunkToDictionary(fc); -- return NULL; -- } -- -- _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk -- dictionary()->dict_census_update(fc->size(), -- true /*split*/, -- false /*birth*/); -- -- // First return the remainder, if any. -- // Note that we hold the lock until we decide if we're going to give -- // back the remainder to the dictionary, since a concurrent allocation -- // may otherwise see the heap as empty. (We're willing to take that -- // hit if the block is a small block.) -- if (rem > 0) { -- size_t prefix_size = n * word_sz; -- rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); -- rem_fc->set_size(rem); -- rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -- rem_fc->link_next(NULL); -- // Above must occur before BOT is updated below. -- assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); -- OrderAccess::storestore(); -- _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); -- assert(fc->is_free(), "Error"); -- fc->set_size(prefix_size); -- if (rem >= IndexSetSize) { -- returnChunkToDictionary(rem_fc); -- dictionary()->dict_census_update(rem, true /*split*/, true /*birth*/); -- rem_fc = NULL; -- } -- // Otherwise, return it to the small list below. -- } -- } -- if (rem_fc != NULL) { -- MutexLockerEx x(_indexedFreeListParLocks[rem], -- Mutex::_no_safepoint_check_flag); -- _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); -- _indexedFreeList[rem].return_chunk_at_head(rem_fc); -- smallSplitBirth(rem); -- } -- assert(n * word_sz == fc->size(), -- "Chunk size " SIZE_FORMAT " is not exactly splittable by " -- SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, -- fc->size(), n, word_sz); -- return fc; --} -- --void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList* fl) { -- -- FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); -- -- if (fc == NULL) { -- return; -- } -- -- size_t n = fc->size() / word_sz; -- -- assert((ssize_t)n > 0, "Consistency"); -- // Now do the splitting up. -- // Must do this in reverse order, so that anybody attempting to -- // access the main chunk sees it as a single free block until we -- // change it. -- size_t fc_size = n * word_sz; -- // All but first chunk in this loop -- for (ssize_t i = n-1; i > 0; i--) { -- FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); -- ffc->set_size(word_sz); -- ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. -- ffc->link_next(NULL); -- // Above must occur before BOT is updated below. -- OrderAccess::storestore(); -- // splitting from the right, fc_size == (n - i + 1) * wordsize -- _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); -- fc_size -= word_sz; -- _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); -- _bt.verify_single_block((HeapWord*)ffc, ffc->size()); -- _bt.verify_single_block((HeapWord*)fc, fc_size); -- // Push this on "fl". -- fl->return_chunk_at_head(ffc); -- } -- // First chunk -- assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block"); -- // The blocks above should show their new sizes before the first block below -- fc->set_size(word_sz); -- fc->link_prev(NULL); // idempotent wrt free-ness, see assert above -- fc->link_next(NULL); -- _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); -- _bt.verify_single_block((HeapWord*)fc, fc->size()); -- fl->return_chunk_at_head(fc); -- -- assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); -- { -- // Update the stats for this block size. -- MutexLockerEx x(_indexedFreeListParLocks[word_sz], -- Mutex::_no_safepoint_check_flag); -- const ssize_t births = _indexedFreeList[word_sz].split_births() + n; -- _indexedFreeList[word_sz].set_split_births(births); -- // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; -- // _indexedFreeList[word_sz].set_surplus(new_surplus); -- } -- -- // TRAP -- assert(fl->tail()->next() == NULL, "List invariant."); --} -- --void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { -- assert(fl->count() == 0, "Precondition."); -- assert(word_sz < CompactibleFreeListSpace::IndexSetSize, -- "Precondition"); -- -- if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { -- // Got it -- return; -- } -- -- // Otherwise, we'll split a block from the dictionary. -- par_get_chunk_of_blocks_dictionary(word_sz, n, fl); --} -- --const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { -- const size_t ergo_max = _old_gen->reserved().word_size() / (CardTable::card_size_in_words * BitsPerWord); -- return ergo_max; --} -- --// Set up the space's par_seq_tasks structure for work claiming --// for parallel rescan. See CMSParRemarkTask where this is currently used. --// XXX Need to suitably abstract and generalize this and the next --// method into one. --void --CompactibleFreeListSpace:: --initialize_sequential_subtasks_for_rescan(int n_threads) { -- // The "size" of each task is fixed according to rescan_task_size. -- assert(n_threads > 0, "Unexpected n_threads argument"); -- const size_t task_size = rescan_task_size(); -- size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size; -- assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect"); -- assert(n_tasks == 0 || -- ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) && -- (used_region().start() + n_tasks*task_size >= used_region().end())), -- "n_tasks calculation incorrect"); -- SequentialSubTasksDone* pst = conc_par_seq_tasks(); -- assert(!pst->valid(), "Clobbering existing data?"); -- // Sets the condition for completion of the subtask (how many threads -- // need to finish in order to be done). -- pst->set_n_threads(n_threads); -- pst->set_n_tasks((int)n_tasks); --} -- --// Set up the space's par_seq_tasks structure for work claiming --// for parallel concurrent marking. See CMSConcMarkTask where this is currently used. --void --CompactibleFreeListSpace:: --initialize_sequential_subtasks_for_marking(int n_threads, -- HeapWord* low) { -- // The "size" of each task is fixed according to rescan_task_size. -- assert(n_threads > 0, "Unexpected n_threads argument"); -- const size_t task_size = marking_task_size(); -- assert(task_size > CardTable::card_size_in_words && -- (task_size % CardTable::card_size_in_words == 0), -- "Otherwise arithmetic below would be incorrect"); -- MemRegion span = _old_gen->reserved(); -- if (low != NULL) { -- if (span.contains(low)) { -- // Align low down to a card boundary so that -- // we can use block_offset_careful() on span boundaries. -- HeapWord* aligned_low = align_down(low, CardTable::card_size); -- // Clip span prefix at aligned_low -- span = span.intersection(MemRegion(aligned_low, span.end())); -- } else if (low > span.end()) { -- span = MemRegion(low, low); // Null region -- } // else use entire span -- } -- assert(span.is_empty() || -- ((uintptr_t)span.start() % CardTable::card_size == 0), -- "span should start at a card boundary"); -- size_t n_tasks = (span.word_size() + task_size - 1)/task_size; -- assert((n_tasks == 0) == span.is_empty(), "Inconsistency"); -- assert(n_tasks == 0 || -- ((span.start() + (n_tasks - 1)*task_size < span.end()) && -- (span.start() + n_tasks*task_size >= span.end())), -- "n_tasks calculation incorrect"); -- SequentialSubTasksDone* pst = conc_par_seq_tasks(); -- assert(!pst->valid(), "Clobbering existing data?"); -- // Sets the condition for completion of the subtask (how many threads -- // need to finish in order to be done). -- pst->set_n_threads(n_threads); -- pst->set_n_tasks((int)n_tasks); --} -diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp -deleted file mode 100644 -index 9fd2ea58320..00000000000 ---- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp -+++ /dev/null -@@ -1,759 +0,0 @@ --/* -- * Copyright (c) 2001, 2018, 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_CMS_COMPACTIBLEFREELISTSPACE_HPP --#define SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP -- --#include "gc/cms/adaptiveFreeList.hpp" --#include "gc/cms/promotionInfo.hpp" --#include "gc/shared/blockOffsetTable.hpp" --#include "gc/shared/cardTable.hpp" --#include "gc/shared/space.hpp" --#include "logging/log.hpp" --#include "memory/binaryTreeDictionary.hpp" --#include "memory/freeList.hpp" -- --// Classes in support of keeping track of promotions into a non-Contiguous --// space, in this case a CompactibleFreeListSpace. -- --// Forward declarations --class CMSCollector; --class CompactibleFreeListSpace; --class ConcurrentMarkSweepGeneration; --class BlkClosure; --class BlkClosureCareful; --class FreeChunk; --class UpwardsObjectClosure; --class ObjectClosureCareful; --class Klass; -- --class AFLBinaryTreeDictionary : public BinaryTreeDictionary > { -- public: -- AFLBinaryTreeDictionary(MemRegion mr) -- : BinaryTreeDictionary >(mr) {} -- -- // Find the list with size "size" in the binary tree and update -- // the statistics in the list according to "split" (chunk was -- // split or coalesce) and "birth" (chunk was added or removed). -- void dict_census_update(size_t size, bool split, bool birth); -- // Return true if the dictionary is overpopulated (more chunks of -- // this size than desired) for size "size". -- bool coal_dict_over_populated(size_t size); -- // Methods called at the beginning of a sweep to prepare the -- // statistics for the sweep. -- void begin_sweep_dict_census(double coalSurplusPercent, -- float inter_sweep_current, -- float inter_sweep_estimate, -- float intra_sweep_estimate); -- // Methods called after the end of a sweep to modify the -- // statistics for the sweep. -- void end_sweep_dict_census(double splitSurplusPercent); -- // Accessors for statistics -- void set_tree_surplus(double splitSurplusPercent); -- void set_tree_hints(void); -- // Reset statistics for all the lists in the tree. -- void clear_tree_census(void); -- // Print the statistics for all the lists in the tree. Also may -- // print out summaries. -- void print_dict_census(outputStream* st) const; --}; -- --class LinearAllocBlock { -- public: -- LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), -- _allocation_size_limit(0) {} -- void set(HeapWord* ptr, size_t word_size, size_t refill_size, -- size_t allocation_size_limit) { -- _ptr = ptr; -- _word_size = word_size; -- _refillSize = refill_size; -- _allocation_size_limit = allocation_size_limit; -- } -- HeapWord* _ptr; -- size_t _word_size; -- size_t _refillSize; -- size_t _allocation_size_limit; // Largest size that will be allocated -- -- void print_on(outputStream* st) const; --}; -- --// Concrete subclass of CompactibleSpace that implements --// a free list space, such as used in the concurrent mark sweep --// generation. -- --class CompactibleFreeListSpace: public CompactibleSpace { -- friend class VMStructs; -- friend class ConcurrentMarkSweepGeneration; -- friend class CMSCollector; -- // Local alloc buffer for promotion into this space. -- friend class CompactibleFreeListSpaceLAB; -- // Allow scan_and_* functions to call (private) overrides of the auxiliary functions on this class -- template -- friend void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space); -- template -- friend void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefinition_run); -- template -- friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); -- template -- friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp, bool redefinition_run); -- -- // "Size" of chunks of work (executed during parallel remark phases -- // of CMS collection); this probably belongs in CMSCollector, although -- // it's cached here because it's used in -- // initialize_sequential_subtasks_for_rescan() which modifies -- // par_seq_tasks which also lives in Space. XXX -- const size_t _rescan_task_size; -- const size_t _marking_task_size; -- -- // Yet another sequential tasks done structure. This supports -- // CMS GC, where we have threads dynamically -- // claiming sub-tasks from a larger parallel task. -- SequentialSubTasksDone _conc_par_seq_tasks; -- -- BlockOffsetArrayNonContigSpace _bt; -- -- CMSCollector* _collector; -- ConcurrentMarkSweepGeneration* _old_gen; -- -- // Data structures for free blocks (used during allocation/sweeping) -- -- // Allocation is done linearly from two different blocks depending on -- // whether the request is small or large, in an effort to reduce -- // fragmentation. We assume that any locking for allocation is done -- // by the containing generation. Thus, none of the methods in this -- // space are re-entrant. -- enum SomeConstants { -- SmallForLinearAlloc = 16, // size < this then use _sLAB -- SmallForDictionary = 257, // size < this then use _indexedFreeList -- IndexSetSize = SmallForDictionary // keep this odd-sized -- }; -- static size_t IndexSetStart; -- static size_t IndexSetStride; -- static size_t _min_chunk_size_in_bytes; -- -- private: -- enum FitStrategyOptions { -- FreeBlockStrategyNone = 0, -- FreeBlockBestFitFirst -- }; -- -- PromotionInfo _promoInfo; -- -- // Helps to impose a global total order on freelistLock ranks; -- // assumes that CFLSpace's are allocated in global total order -- static int _lockRank; -- -- // A lock protecting the free lists and free blocks; -- // mutable because of ubiquity of locking even for otherwise const methods -- mutable Mutex _freelistLock; -- -- // Locking verifier convenience function -- void assert_locked() const PRODUCT_RETURN; -- void assert_locked(const Mutex* lock) const PRODUCT_RETURN; -- -- // Linear allocation blocks -- LinearAllocBlock _smallLinearAllocBlock; -- -- AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks -- -- // Indexed array for small size blocks -- AdaptiveFreeList _indexedFreeList[IndexSetSize]; -- -- // Allocation strategy -- bool _fitStrategy; // Use best fit strategy -- -- // This is an address close to the largest free chunk in the heap. -- // It is currently assumed to be at the end of the heap. Free -- // chunks with addresses greater than nearLargestChunk are coalesced -- // in an effort to maintain a large chunk at the end of the heap. -- HeapWord* _nearLargestChunk; -- -- // Used to keep track of limit of sweep for the space -- HeapWord* _sweep_limit; -- -- // Stable value of used(). -- size_t _used_stable; -- -- // Used to make the young collector update the mod union table -- MemRegionClosure* _preconsumptionDirtyCardClosure; -- -- // Support for compacting cms -- HeapWord* cross_threshold(HeapWord* start, HeapWord* end); -- HeapWord* forward_compact_top(size_t size, CompactPoint* cp, HeapWord* compact_top); -- HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); -- -- // Initialization helpers. -- void initializeIndexedFreeListArray(); -- -- // Extra stuff to manage promotion parallelism. -- -- // A lock protecting the dictionary during par promotion allocation. -- mutable Mutex _parDictionaryAllocLock; -- Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } -- -- // Locks protecting the exact lists during par promotion allocation. -- Mutex* _indexedFreeListParLocks[IndexSetSize]; -- -- // Attempt to obtain up to "n" blocks of the size "word_sz" (which is -- // required to be smaller than "IndexSetSize".) If successful, -- // adds them to "fl", which is required to be an empty free list. -- // If the count of "fl" is negative, it's absolute value indicates a -- // number of free chunks that had been previously "borrowed" from global -- // list of size "word_sz", and must now be decremented. -- void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl); -- -- // Used by par_get_chunk_of_blocks() for the chunks from the -- // indexed_free_lists. -- bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl); -- -- // Used by par_get_chunk_of_blocks_dictionary() to get a chunk -- // evenly splittable into "n" "word_sz" chunks. Returns that -- // evenly splittable chunk. May split a larger chunk to get the -- // evenly splittable chunk. -- FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); -- -- // Used by par_get_chunk_of_blocks() for the chunks from the -- // dictionary. -- void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList* fl); -- -- // Allocation helper functions -- // Allocate using a strategy that takes from the indexed free lists -- // first. This allocation strategy assumes a companion sweeping -- // strategy that attempts to keep the needed number of chunks in each -- // indexed free lists. -- HeapWord* allocate_adaptive_freelists(size_t size); -- -- // Gets a chunk from the linear allocation block (LinAB). If there -- // is not enough space in the LinAB, refills it. -- HeapWord* getChunkFromLinearAllocBlock(LinearAllocBlock* blk, size_t size); -- HeapWord* getChunkFromSmallLinearAllocBlock(size_t size); -- // Get a chunk from the space remaining in the linear allocation block. Do -- // not attempt to refill if the space is not available, return NULL. Do the -- // repairs on the linear allocation block as appropriate. -- HeapWord* getChunkFromLinearAllocBlockRemainder(LinearAllocBlock* blk, size_t size); -- inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); -- -- // Helper function for getChunkFromIndexedFreeList. -- // Replenish the indexed free list for this "size". Do not take from an -- // underpopulated size. -- FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); -- -- // Get a chunk from the indexed free list. If the indexed free list -- // does not have a free chunk, try to replenish the indexed free list -- // then get the free chunk from the replenished indexed free list. -- inline FreeChunk* getChunkFromIndexedFreeList(size_t size); -- -- // The returned chunk may be larger than requested (or null). -- FreeChunk* getChunkFromDictionary(size_t size); -- // The returned chunk is the exact size requested (or null). -- FreeChunk* getChunkFromDictionaryExact(size_t size); -- -- // Find a chunk in the indexed free list that is the best -- // fit for size "numWords". -- FreeChunk* bestFitSmall(size_t numWords); -- // For free list "fl" of chunks of size > numWords, -- // remove a chunk, split off a chunk of size numWords -- // and return it. The split off remainder is returned to -- // the free lists. The old name for getFromListGreater -- // was lookInListGreater. -- FreeChunk* getFromListGreater(AdaptiveFreeList* fl, size_t numWords); -- // Get a chunk in the indexed free list or dictionary, -- // by considering a larger chunk and splitting it. -- FreeChunk* getChunkFromGreater(size_t numWords); -- // Verify that the given chunk is in the indexed free lists. -- bool verifyChunkInIndexedFreeLists(FreeChunk* fc) const; -- // Remove the specified chunk from the indexed free lists. -- void removeChunkFromIndexedFreeList(FreeChunk* fc); -- // Remove the specified chunk from the dictionary. -- void removeChunkFromDictionary(FreeChunk* fc); -- // Split a free chunk into a smaller free chunk of size "new_size". -- // Return the smaller free chunk and return the remainder to the -- // free lists. -- FreeChunk* splitChunkAndReturnRemainder(FreeChunk* chunk, size_t new_size); -- // Add a chunk to the free lists. -- void addChunkToFreeLists(HeapWord* chunk, size_t size); -- // Add a chunk to the free lists, preferring to suffix it -- // to the last free chunk at end of space if possible, and -- // updating the block census stats as well as block offset table. -- // Take any locks as appropriate if we are multithreaded. -- void addChunkToFreeListsAtEndRecordingStats(HeapWord* chunk, size_t size); -- // Add a free chunk to the indexed free lists. -- void returnChunkToFreeList(FreeChunk* chunk); -- // Add a free chunk to the dictionary. -- void returnChunkToDictionary(FreeChunk* chunk); -- -- // Functions for maintaining the linear allocation buffers (LinAB). -- // Repairing a linear allocation block refers to operations -- // performed on the remainder of a LinAB after an allocation -- // has been made from it. -- void repairLinearAllocationBlocks(); -- void repairLinearAllocBlock(LinearAllocBlock* blk); -- void refillLinearAllocBlock(LinearAllocBlock* blk); -- void refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk); -- void refillLinearAllocBlocksIfNeeded(); -- -- void verify_objects_initialized() const; -- -- // Statistics reporting helper functions -- void reportFreeListStatistics(const char* title) const; -- void reportIndexedFreeListStatistics(outputStream* st) const; -- size_t maxChunkSizeInIndexedFreeLists() const; -- size_t numFreeBlocksInIndexedFreeLists() const; -- // Accessor -- HeapWord* unallocated_block() const { -- if (BlockOffsetArrayUseUnallocatedBlock) { -- HeapWord* ub = _bt.unallocated_block(); -- assert(ub >= bottom() && -- ub <= end(), "space invariant"); -- return ub; -- } else { -- return end(); -- } -- } -- void freed(HeapWord* start, size_t size) { -- _bt.freed(start, size); -- } -- -- // Auxiliary functions for scan_and_{forward,adjust_pointers,compact} support. -- // See comments for CompactibleSpace for more information. -- inline HeapWord* scan_limit() const { -- return end(); -- } -- -- inline bool scanned_block_is_obj(const HeapWord* addr) const { -- return CompactibleFreeListSpace::block_is_obj(addr); // Avoid virtual call -- } -- -- inline size_t scanned_block_size(const HeapWord* addr) const { -- return CompactibleFreeListSpace::block_size(addr); // Avoid virtual call -- } -- -- inline size_t adjust_obj_size(size_t size) const { -- return adjustObjectSize(size); -- } -- -- inline size_t obj_size(const HeapWord* addr) const; -- -- protected: -- // Reset the indexed free list to its initial empty condition. -- void resetIndexedFreeListArray(); -- // Reset to an initial state with a single free block described -- // by the MemRegion parameter. -- void reset(MemRegion mr); -- // Return the total number of words in the indexed free lists. -- size_t totalSizeInIndexedFreeLists() const; -- -- public: -- // Constructor -- CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); -- // Accessors -- bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } -- AFLBinaryTreeDictionary* dictionary() const { return _dictionary; } -- HeapWord* nearLargestChunk() const { return _nearLargestChunk; } -- void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; } -- -- // Set CMS global values. -- static void set_cms_values(); -- -- // Return the free chunk at the end of the space. If no such -- // chunk exists, return NULL. -- FreeChunk* find_chunk_at_end(); -- -- void set_collector(CMSCollector* collector) { _collector = collector; } -- -- // Support for parallelization of rescan and marking. -- const size_t rescan_task_size() const { return _rescan_task_size; } -- const size_t marking_task_size() const { return _marking_task_size; } -- // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. -- const size_t max_flag_size_for_task_size() const; -- SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } -- void initialize_sequential_subtasks_for_rescan(int n_threads); -- void initialize_sequential_subtasks_for_marking(int n_threads, -- HeapWord* low = NULL); -- -- virtual MemRegionClosure* preconsumptionDirtyCardClosure() const { -- return _preconsumptionDirtyCardClosure; -- } -- -- void setPreconsumptionDirtyCardClosure(MemRegionClosure* cl) { -- _preconsumptionDirtyCardClosure = cl; -- } -- -- // Space enquiries -- size_t used() const; -- size_t free() const; -- size_t max_alloc_in_words() const; -- // XXX: should have a less conservative used_region() than that of -- // Space; we could consider keeping track of highest allocated -- // address and correcting that at each sweep, as the sweeper -- // goes through the entire allocated part of the generation. We -- // could also use that information to keep the sweeper from -- // sweeping more than is necessary. The allocator and sweeper will -- // of course need to synchronize on this, since the sweeper will -- // try to bump down the address and the allocator will try to bump it up. -- // For now, however, we'll just use the default used_region() -- // which overestimates the region by returning the entire -- // committed region (this is safe, but inefficient). -- -- // Returns monotonically increasing stable used space bytes for CMS. -- // This is required for jstat and other memory monitoring tools -- // that might otherwise see inconsistent used space values during a garbage -- // collection, promotion or allocation into compactibleFreeListSpace. -- // The value returned by this function might be smaller than the -- // actual value. -- size_t used_stable() const; -- // Recalculate and cache the current stable used() value. Only to be called -- // in places where we can be sure that the result is stable. -- void recalculate_used_stable(); -- -- // Returns a subregion of the space containing all the objects in -- // the space. -- MemRegion used_region() const { -- return MemRegion(bottom(), -- BlockOffsetArrayUseUnallocatedBlock ? -- unallocated_block() : end()); -- } -- -- virtual bool is_free_block(const HeapWord* p) const; -- -- // Resizing support -- void set_end(HeapWord* value); // override -- -- // Never mangle CompactibleFreeListSpace -- void mangle_unused_area() {} -- void mangle_unused_area_complete() {} -- -- // Mutual exclusion support -- Mutex* freelistLock() const { return &_freelistLock; } -- -- // Iteration support -- void oop_iterate(OopIterateClosure* cl); -- -- void object_iterate(ObjectClosure* blk); -- // Apply the closure to each object in the space whose references -- // point to objects in the heap. The usage of CompactibleFreeListSpace -- // by the ConcurrentMarkSweepGeneration for concurrent GC's allows -- // objects in the space with references to objects that are no longer -- // valid. For example, an object may reference another object -- // that has already been sweep up (collected). This method uses -- // obj_is_alive() to determine whether it is safe to iterate of -- // an object. -- void safe_object_iterate(ObjectClosure* blk); -- -- // Iterate over all objects that intersect with mr, calling "cl->do_object" -- // on each. There is an exception to this: if this closure has already -- // been invoked on an object, it may skip such objects in some cases. This is -- // Most likely to happen in an "upwards" (ascending address) iteration of -- // MemRegions. -- void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); -- -- // Requires that "mr" be entirely within the space. -- // Apply "cl->do_object" to all objects that intersect with "mr". -- // If the iteration encounters an unparseable portion of the region, -- // terminate the iteration and return the address of the start of the -- // subregion that isn't done. Return of "NULL" indicates that the -- // iteration completed. -- HeapWord* object_iterate_careful_m(MemRegion mr, -- ObjectClosureCareful* cl); -- -- // Override: provides a DCTO_CL specific to this kind of space. -- DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, -- CardTable::PrecisionStyle precision, -- HeapWord* boundary, -- bool parallel); -- -- void blk_iterate(BlkClosure* cl); -- void blk_iterate_careful(BlkClosureCareful* cl); -- HeapWord* block_start_const(const void* p) const; -- HeapWord* block_start_careful(const void* p) const; -- size_t block_size(const HeapWord* p) const; -- size_t block_size_no_stall(HeapWord* p, const CMSCollector* c) const; -- bool block_is_obj(const HeapWord* p) const; -- bool obj_is_alive(const HeapWord* p) const; -- size_t block_size_nopar(const HeapWord* p) const; -- bool block_is_obj_nopar(const HeapWord* p) const; -- -- // Iteration support for promotion -- void save_marks(); -- bool no_allocs_since_save_marks(); -- -- // Iteration support for sweeping -- void save_sweep_limit() { -- _sweep_limit = BlockOffsetArrayUseUnallocatedBlock ? -- unallocated_block() : end(); -- log_develop_trace(gc, sweep)(">>>>> Saving sweep limit " PTR_FORMAT -- " for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<", -- p2i(_sweep_limit), p2i(bottom()), p2i(end())); -- } -- NOT_PRODUCT( -- void clear_sweep_limit() { _sweep_limit = NULL; } -- ) -- HeapWord* sweep_limit() { return _sweep_limit; } -- -- // Apply "blk->do_oop" to the addresses of all reference fields in objects -- // promoted into this generation since the most recent save_marks() call. -- // Fields in objects allocated by applications of the closure -- // *are* included in the iteration. Thus, when the iteration completes -- // there should be no further such objects remaining. -- template -- void oop_since_save_marks_iterate(OopClosureType* blk); -- -- // Allocation support -- HeapWord* allocate(size_t size); -- HeapWord* par_allocate(size_t size); -- -- oop promote(oop obj, size_t obj_size); -- void gc_prologue(); -- void gc_epilogue(); -- -- // This call is used by a containing CMS generation / collector -- // to inform the CFLS space that a sweep has been completed -- // and that the space can do any related house-keeping functions. -- void sweep_completed(); -- -- // For an object in this space, the mark-word's two -- // LSB's having the value [11] indicates that it has been -- // promoted since the most recent call to save_marks() on -- // this generation and has not subsequently been iterated -- // over (using oop_since_save_marks_iterate() above). -- // This property holds only for single-threaded collections, -- // and is typically used for Cheney scans; for MT scavenges, -- // the property holds for all objects promoted during that -- // scavenge for the duration of the scavenge and is used -- // by card-scanning to avoid scanning objects (being) promoted -- // during that scavenge. -- bool obj_allocated_since_save_marks(const oop obj) const { -- assert(is_in_reserved(obj), "Wrong space?"); -- return ((PromotedObject*)obj)->hasPromotedMark(); -- } -- -- // A worst-case estimate of the space required (in HeapWords) to expand the -- // heap when promoting an obj of size obj_size. -- size_t expansionSpaceRequired(size_t obj_size) const; -- -- FreeChunk* allocateScratch(size_t size); -- -- // Returns true if either the small or large linear allocation buffer is empty. -- bool linearAllocationWouldFail() const; -- -- // Adjust the chunk for the minimum size. This version is called in -- // most cases in CompactibleFreeListSpace methods. -- inline static size_t adjustObjectSize(size_t size) { -- return align_object_size(MAX2(size, (size_t)MinChunkSize)); -- } -- // This is a virtual version of adjustObjectSize() that is called -- // only occasionally when the compaction space changes and the type -- // of the new compaction space is is only known to be CompactibleSpace. -- size_t adjust_object_size_v(size_t size) const { -- return adjustObjectSize(size); -- } -- // Minimum size of a free block. -- virtual size_t minimum_free_block_size() const { return MinChunkSize; } -- void removeFreeChunkFromFreeLists(FreeChunk* chunk); -- void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, -- bool coalesced); -- -- // Support for compaction. -- void prepare_for_compaction(CompactPoint* cp); -- void adjust_pointers(); -- void compact(); -- // Reset the space to reflect the fact that a compaction of the -- // space has been done. -- virtual void reset_after_compaction(); -- -- // Debugging support. -- void print() const; -- void print_on(outputStream* st) const; -- void prepare_for_verify(); -- void verify() const; -- void verifyFreeLists() const PRODUCT_RETURN; -- void verifyIndexedFreeLists() const; -- void verifyIndexedFreeList(size_t size) const; -- // Verify that the given chunk is in the free lists: -- // i.e. either the binary tree dictionary, the indexed free lists -- // or the linear allocation block. -- bool verify_chunk_in_free_list(FreeChunk* fc) const; -- // Verify that the given chunk is the linear allocation block. -- bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; -- // Do some basic checks on the the free lists. -- void check_free_list_consistency() const PRODUCT_RETURN; -- -- // Printing support -- void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); -- void print_indexed_free_lists(outputStream* st) const; -- void print_dictionary_free_lists(outputStream* st) const; -- void print_promo_info_blocks(outputStream* st) const; -- -- NOT_PRODUCT ( -- void initializeIndexedFreeListArrayReturnedBytes(); -- size_t sumIndexedFreeListArrayReturnedBytes(); -- // Return the total number of chunks in the indexed free lists. -- size_t totalCountInIndexedFreeLists() const; -- // Return the total number of chunks in the space. -- size_t totalCount(); -- ) -- -- // The census consists of counts of the quantities such as -- // the current count of the free chunks, number of chunks -- // created as a result of the split of a larger chunk or -- // coalescing of smaller chucks, etc. The counts in the -- // census is used to make decisions on splitting and -- // coalescing of chunks during the sweep of garbage. -- -- // Print the statistics for the free lists. -- void printFLCensus(size_t sweep_count) const; -- -- // Statistics functions -- // Initialize census for lists before the sweep. -- void beginSweepFLCensus(float inter_sweep_current, -- float inter_sweep_estimate, -- float intra_sweep_estimate); -- // Set the surplus for each of the free lists. -- void setFLSurplus(); -- // Set the hint for each of the free lists. -- void setFLHints(); -- // Clear the census for each of the free lists. -- void clearFLCensus(); -- // Perform functions for the census after the end of the sweep. -- void endSweepFLCensus(size_t sweep_count); -- // Return true if the count of free chunks is greater -- // than the desired number of free chunks. -- bool coalOverPopulated(size_t size); -- --// Record (for each size): --// --// split-births = #chunks added due to splits in (prev-sweep-end, --// this-sweep-start) --// split-deaths = #chunks removed for splits in (prev-sweep-end, --// this-sweep-start) --// num-curr = #chunks at start of this sweep --// num-prev = #chunks at end of previous sweep --// --// The above are quantities that are measured. Now define: --// --// num-desired := num-prev + split-births - split-deaths - num-curr --// --// Roughly, num-prev + split-births is the supply, --// split-deaths is demand due to other sizes --// and num-curr is what we have left. --// --// Thus, num-desired is roughly speaking the "legitimate demand" --// for blocks of this size and what we are striving to reach at the --// end of the current sweep. --// --// For a given list, let num-len be its current population. --// Define, for a free list of a given size: --// --// coal-overpopulated := num-len >= num-desired * coal-surplus --// (coal-surplus is set to 1.05, i.e. we allow a little slop when --// coalescing -- we do not coalesce unless we think that the current --// supply has exceeded the estimated demand by more than 5%). --// --// For the set of sizes in the binary tree, which is neither dense nor --// closed, it may be the case that for a particular size we have never --// had, or do not now have, or did not have at the previous sweep, --// chunks of that size. We need to extend the definition of --// coal-overpopulated to such sizes as well: --// --// For a chunk in/not in the binary tree, extend coal-overpopulated --// defined above to include all sizes as follows: --// --// . a size that is non-existent is coal-overpopulated --// . a size that has a num-desired <= 0 as defined above is --// coal-overpopulated. --// --// Also define, for a chunk heap-offset C and mountain heap-offset M: --// --// close-to-mountain := C >= 0.99 * M --// --// Now, the coalescing strategy is: --// --// Coalesce left-hand chunk with right-hand chunk if and --// only if: --// --// EITHER --// . left-hand chunk is of a size that is coal-overpopulated --// OR --// . right-hand chunk is close-to-mountain -- void smallCoalBirth(size_t size); -- void smallCoalDeath(size_t size); -- void coalBirth(size_t size); -- void coalDeath(size_t size); -- void smallSplitBirth(size_t size); -- void smallSplitDeath(size_t size); -- void split_birth(size_t size); -- void splitDeath(size_t size); -- void split(size_t from, size_t to1); -- -- double flsFrag() const; --}; -- --// A parallel-GC-thread-local allocation buffer for allocation into a --// CompactibleFreeListSpace. --class CompactibleFreeListSpaceLAB : public CHeapObj { -- // The space that this buffer allocates into. -- CompactibleFreeListSpace* _cfls; -- -- // Our local free lists. -- AdaptiveFreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; -- -- // Initialized from a command-line arg. -- -- // Allocation statistics in support of dynamic adjustment of -- // #blocks to claim per get_from_global_pool() call below. -- static AdaptiveWeightedAverage -- _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; -- static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; -- static uint _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; -- size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; -- -- // Internal work method -- void get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl); -- --public: -- static const int _default_dynamic_old_plab_size = 16; -- static const int _default_static_old_plab_size = 50; -- -- CompactibleFreeListSpaceLAB(CompactibleFreeListSpace* cfls); -- -- // Allocate and return a block of the given size, or else return NULL. -- HeapWord* alloc(size_t word_sz); -- -- // Return any unused portions of the buffer to the global pool. -- void retire(int tid); -- -- // Dynamic OldPLABSize sizing -- static void compute_desired_plab_size(); -- // When the settings are modified from default static initialization -- static void modify_initialization(size_t n, unsigned wt); --}; -- --size_t PromotionInfo::refillSize() const { -- const size_t CMSSpoolBlockSize = 256; -- const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) -- * CMSSpoolBlockSize); -- return CompactibleFreeListSpace::adjustObjectSize(sz); --} -- --#endif // SHARE_VM_GC_CMS_COMPACTIBLEFREELISTSPACE_HPP --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch b/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch deleted file mode 100644 index 077e41ca256c..000000000000 --- a/jb/project/tools/patches/dcevm/0018-pre-dcevm15-fix-GC-spaces-originally-in-removed-CMS-.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 1d682efa88c716e1849163d5abff3a3367581d16 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Mon, 16 Nov 2020 21:11:19 +0100 -Subject: [PATCH 18/34] pre dcevm15 - fix GC spaces originally in removed CMS - patch - ---- - src/hotspot/share/gc/shared/space.cpp | 16 ++++++++-------- - src/hotspot/share/gc/shared/space.hpp | 6 +++--- - src/hotspot/share/gc/shared/space.inline.hpp | 14 ++++++++------ - .../share/prims/jvmtiEnhancedRedefineClasses.cpp | 6 ++---- - 4 files changed, 21 insertions(+), 21 deletions(-) - -diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp -index 875a6dc854f..9772c32c42e 100644 ---- a/src/hotspot/share/gc/shared/space.cpp -+++ b/src/hotspot/share/gc/shared/space.cpp -@@ -375,11 +375,11 @@ HeapWord* CompactibleSpace::forward_compact_top(size_t size, CompactPoint* cp, H - } - - HeapWord* CompactibleSpace::forward(oop q, size_t size, -- CompactPoint* cp, HeapWord* compact_top) { -+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) { - compact_top = forward_compact_top(size, cp, compact_top); - - // store the forwarding pointer into the mark word -- if (cast_from_oop(q) != compact_top || (size_t)q->size() != size) { -+ if (force_forward || cast_from_oop(q) != compact_top || (size_t)q->size() != size) { - q->forward_to(oop(compact_top)); - assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); - } else { -@@ -501,7 +501,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { - - } else { - assert(space_index(old_obj) != space_index(new_obj), "old_obj and new_obj must be in different spaces"); -- if (tenured_gen->is_in_reserved(new_obj)) { -+ if (new_in_tenured) { - // Must never rescue when moving from the new into the old generation. - assert(GenCollectedHeap::heap()->young_gen()->is_in_reserved(old_obj), "old_obj must be in DefNewGeneration"); - assert(space_index(old_obj) > space_index(new_obj), "must be"); -@@ -824,14 +824,14 @@ void OffsetTableContigSpace::verify() const { - // Compute the forward sizes and leave out objects whose position could - // possibly overlap other objects. - HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, -- CompactPoint* cp, HeapWord* compact_top) { -+ CompactPoint* cp, HeapWord* compact_top, bool force_forward) { - size_t forward_size = size; - - // (DCEVM) There is a new version of the class of q => different size - if (oop(q)->klass()->new_version() != NULL) { - - size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); -- assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); - forward_size = new_size; - } - -@@ -845,7 +845,7 @@ HeapWord* CompactibleSpace::forward_with_rescue(HeapWord* q, size_t size, - return compact_top; - } - -- return forward(oop(q), forward_size, cp, compact_top); -+ return forward(oop(q), forward_size, cp, compact_top, force_forward); - } - - // Compute the forwarding addresses for the objects that need to be rescued. -@@ -861,11 +861,11 @@ HeapWord* CompactibleSpace::forward_rescued(CompactPoint* cp, HeapWord* compact_ - // (DCEVM) There is a new version of the class of q => different size - if (oop(q)->klass()->new_version() != NULL) { - size_t new_size = oop(q)->size_given_klass(oop(q)->klass()->new_version()); -- assert(size != new_size, "instances without changed size have to be updated prior to GC run"); -+ // assert(size != new_size, "instances without changed size have to be updated prior to GC run"); - size = new_size; - } - -- compact_top = cp->space->forward(oop(q), size, cp, compact_top); -+ compact_top = cp->space->forward(oop(q), size, cp, compact_top, true); - assert(compact_top <= end(), "must not write over end of space!"); - } - MarkSweep::_rescued_oops->clear(); -diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp -index c9bfc365f0f..f7648995454 100644 ---- a/src/hotspot/share/gc/shared/space.hpp -+++ b/src/hotspot/share/gc/shared/space.hpp -@@ -405,7 +405,7 @@ public: - virtual void prepare_for_compaction(CompactPoint* cp) = 0; - // MarkSweep support phase3 - DEBUG_ONLY(int space_index(oop obj)); -- bool must_rescue(oop old_obj, oop new_obj); -+ virtual bool must_rescue(oop old_obj, oop new_obj); - HeapWord* rescue(HeapWord* old_obj); - virtual void adjust_pointers(); - // MarkSweep support phase4 -@@ -436,11 +436,11 @@ public: - // function of the then-current compaction space, and updates "cp->threshold - // accordingly". - virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, -- HeapWord* compact_top); -+ HeapWord* compact_top, bool force_forward); - // (DCEVM) same as forwad, but can rescue objects. Invoked only during - // redefinition runs - HeapWord* forward_with_rescue(HeapWord* q, size_t size, CompactPoint* cp, -- HeapWord* compact_top); -+ HeapWord* compact_top, bool force_forward); - - HeapWord* forward_rescued(CompactPoint* cp, HeapWord* compact_top); - -diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp -index 5a93e93471b..fa645423685 100644 ---- a/src/hotspot/share/gc/shared/space.inline.hpp -+++ b/src/hotspot/share/gc/shared/space.inline.hpp -@@ -163,6 +163,8 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - HeapWord* cur_obj = space->bottom(); - HeapWord* scan_limit = space->scan_limit(); - -+ bool force_forward = false; -+ - while (cur_obj < scan_limit) { - assert(!space->scanned_block_is_obj(cur_obj) || - oop(cur_obj)->mark_raw().is_marked() || oop(cur_obj)->mark_raw().is_unlocked() || -@@ -174,14 +176,15 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - size_t size = space->scanned_block_size(cur_obj); - - if (redefinition_run) { -- compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top); -+ compact_top = cp->space->forward_with_rescue(cur_obj, size, cp, compact_top, force_forward); - if (first_dead == NULL && oop(cur_obj)->is_gc_marked()) { - /* Was moved (otherwise, forward would reset mark), - set first_dead to here */ - first_dead = cur_obj; -+ force_forward = true; - } - } else { -- compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); -+ compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top, false); - } - - cur_obj += size; -@@ -197,9 +200,9 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c - - // see if we might want to pretend this object is alive so that - // we don't have to compact quite as often. -- if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { -+ if (!redefinition_run && cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { - oop obj = oop(cur_obj); -- compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); -+ compact_top = cp->space->forward(obj, obj->size(), cp, compact_top, force_forward); - end_of_live = end; - } else { - // otherwise, it really is a free region. -@@ -362,8 +365,7 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space, bool redefiniti - Prefetch::write(compaction_top, copy_interval); - - // copy object and reinit its mark -- assert(cur_obj != compaction_top || oop(cur_obj)->klass()->new_version() != NULL, -- "everything in this pass should be moving"); -+ assert(redefinition_run || cur_obj != compaction_top, "everything in this pass should be moving"); - if (redefinition_run && oop(cur_obj)->klass()->new_version() != NULL) { - Klass* new_version = oop(cur_obj)->klass()->new_version(); - if (new_version->update_information() == NULL) { -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 718426f2819..1da6661dd3e 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -431,13 +431,11 @@ public: - Klass* new_klass = obj->klass()->new_version(); - - if (new_klass->update_information() != NULL) { -- int size_diff = obj->size() - obj->size_given_klass(new_klass); -- -- // Either new size is bigger or gap is to small to be filled -- if (size_diff < 0 || (size_diff > 0 && (size_t) size_diff < CollectedHeap::min_fill_size())) { -+ if (obj->size() - obj->size_given_klass(new_klass) != 0) { - // We need an instance update => set back to old klass - _needs_instance_update = true; - } else { -+ // Either new size is bigger or gap is to small to be filled - oop src = obj; - if (new_klass->is_copying_backwards()) { - copy_to_tmp(obj); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch b/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch deleted file mode 100644 index 2644ed0f716f..000000000000 --- a/jb/project/tools/patches/dcevm/0019-dcevm15-fix-java15-patch-compilation-issues.patch +++ /dev/null @@ -1,942 +0,0 @@ -From 297f564f6af79fb824f5b4e9119f1d3d0c827fb0 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Mon, 16 Nov 2020 20:20:12 +0100 -Subject: [PATCH 19/34] dcevm15 - fix java15 patch compilation issues - ---- - .../share/classfile/classFileParser.hpp | 8 +- - .../share/classfile/classLoaderData.cpp | 2 +- - src/hotspot/share/classfile/dictionary.hpp | 10 +- - src/hotspot/share/classfile/javaClasses.hpp | 2 + - .../share/gc/g1/g1FullGCCompactTask.cpp | 4 +- - .../share/gc/g1/g1FullGCCompactionPoint.cpp | 8 +- - .../share/gc/g1/g1FullGCPrepareTask.cpp | 4 +- - src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 14 +- - src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 2 +- - src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- - src/hotspot/share/gc/shared/space.cpp | 4 +- - .../share/interpreter/linkResolver.cpp | 2 +- - src/hotspot/share/oops/instanceKlass.cpp | 17 ++- - src/hotspot/share/oops/instanceKlass.hpp | 1 + - src/hotspot/share/oops/klass.cpp | 8 +- - src/hotspot/share/prims/jvm.cpp | 2 + - .../prims/jvmtiEnhancedRedefineClasses.cpp | 129 +++++++++--------- - .../prims/jvmtiEnhancedRedefineClasses.hpp | 14 +- - src/hotspot/share/prims/jvmtiEnv.cpp | 11 +- - .../share/prims/jvmtiRedefineClasses.cpp | 1 + - src/hotspot/share/prims/methodHandles.hpp | 3 + - src/hotspot/share/runtime/arguments.cpp | 22 +-- - src/hotspot/share/runtime/mutexLocker.cpp | 2 +- - 23 files changed, 159 insertions(+), 113 deletions(-) - -diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp -index e5761e61767..0d266b9047e 100644 ---- a/src/hotspot/share/classfile/classFileParser.hpp -+++ b/src/hotspot/share/classfile/classFileParser.hpp -@@ -150,9 +150,6 @@ class ClassFileParser { - const intArray* _method_ordering; - GrowableArray* _all_mirandas; - -- // Enhanced class redefinition -- const bool _pick_newest; -- - enum { fixed_buffer_size = 128 }; - u_char _linenumbertable_buffer[fixed_buffer_size]; - -@@ -206,6 +203,9 @@ class ClassFileParser { - bool _has_vanilla_constructor; - int _max_bootstrap_specifier_index; // detects BSS values - -+ // (DCEVM) Enhanced class redefinition -+ const bool _pick_newest; -+ - void parse_stream(const ClassFileStream* const stream, TRAPS); - - void mangle_hidden_class_name(InstanceKlass* const ik); -@@ -582,7 +582,7 @@ class ClassFileParser { - ClassLoaderData* loader_data() const { return _loader_data; } - const Symbol* class_name() const { return _class_name; } - const InstanceKlass* super_klass() const { return _super_klass; } -- Array* local_interfaces() const { return _local_interfaces; } -+ Array* local_interfaces() const { return _local_interfaces; } - - ReferenceType reference_type() const { return _rt; } - AccessFlags access_flags() const { return _access_flags; } -diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp -index 4d64c6b454a..aadcd50ef4a 100644 ---- a/src/hotspot/share/classfile/classLoaderData.cpp -+++ b/src/hotspot/share/classfile/classLoaderData.cpp -@@ -597,7 +597,7 @@ void ClassLoaderData::exchange_holders(ClassLoaderData* cld) { - oop holder_oop = _holder.peek(); - _holder.replace(cld->_holder.peek()); - cld->_holder.replace(holder_oop); -- WeakHandle exchange = _holder; -+ WeakHandle exchange = _holder; - _holder = cld->_holder; - cld->_holder = exchange; - } -diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp -index 114a983e783..a50f4ff84d2 100644 ---- a/src/hotspot/share/classfile/dictionary.hpp -+++ b/src/hotspot/share/classfile/dictionary.hpp -@@ -84,6 +84,11 @@ public: - void print_on(outputStream* st) const; - void verify(); - -+ // (DCEVM) Enhanced class redefinition -+ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); -+ -+ void rollback_redefinition(); -+ - private: - DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass); - -@@ -106,11 +111,6 @@ public: - - void free_entry(DictionaryEntry* entry); - -- // Enhanced class redefinition -- bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass); -- -- void rollback_redefinition(); -- - // (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k" - static InstanceKlass* old_if_redefined(InstanceKlass* k) { - return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k; -diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp -index a68c5139151..9abf2e1d105 100644 ---- a/src/hotspot/share/classfile/javaClasses.hpp -+++ b/src/hotspot/share/classfile/javaClasses.hpp -@@ -255,7 +255,9 @@ class java_lang_Class : AllStatic { - static void set_init_lock(oop java_class, oop init_lock); - static void set_protection_domain(oop java_class, oop protection_domain); - static void set_class_loader(oop java_class, oop class_loader); -+ public: // DCEVM - static void set_component_mirror(oop java_class, oop comp_mirror); -+ private: - static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, - Handle classData, TRAPS); - static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -index f70f4606dc8..a22ed48560d 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp -@@ -157,14 +157,14 @@ void G1FullGCCompactTask::serial_compaction_dcevm() { - - size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) { - size_t size = obj->size(); -- HeapWord* destination = (HeapWord*)obj->forwardee(); -+ HeapWord* destination = cast_from_oop(obj->forwardee()); - if (destination == NULL) { - // Object not moving - return size; - } - - // copy object and reinit its mark -- HeapWord* obj_addr = (HeapWord*) obj; -+ HeapWord* obj_addr = cast_from_oop(obj); - - if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) { - ++(*_rescue_oops_it); -diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -index 1e49571c999..755935a2c91 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp -@@ -174,7 +174,7 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_ - assert(_current_region != NULL, "Must have been initialized"); - - // Store a forwarding pointer if the object should be moved. -- if ((HeapWord*)object != _compaction_top || force_forward) { -+ if (cast_from_oop(object) != _compaction_top || force_forward) { - object->forward_to(oop(_compaction_top)); - } else { - if (object->forwardee() != NULL) { -@@ -188,11 +188,11 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_ - } else { - // Make sure object has the correct mark-word set or that it will be - // fixed when restoring the preserved marks. -- assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark -- object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet -+ assert(object->mark_raw() == markWord::prototype_for_klass(object->klass()) || // Correct mark -+ object->mark_must_be_preserved() || // Will be restored by PreservedMarksSet - (UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking - "should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT, -- p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object))); -+ p2i(object), object->mark_raw().value(), markWord::prototype_for_klass(object->klass()).value()); - } - assert(object->forwardee() == NULL, "should be forwarded to NULL"); - } -diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -index a45681b60cf..2f06b9617e4 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -@@ -269,7 +269,7 @@ size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object) - HeapWord* compact_top = _cp->forward_compact_top(forward_size); - - if (compact_top == NULL || must_rescue(object, oop(compact_top))) { -- _cp->rescued_oops()->append((HeapWord*)object); -+ _cp->rescued_oops()->append(cast_from_oop(object)); - } else { - _cp->forward_dcevm(object, forward_size, (size != forward_size)); - } -@@ -295,7 +295,7 @@ bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_ - int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version()); - int original_size = old_obj->size(); - -- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); -+ bool overlap = (cast_from_oop(old_obj) + original_size < cast_from_oop(new_obj) + new_size); - - return overlap; - } -diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp -index 803e645f843..3dee097f1d3 100644 ---- a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp -+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp -@@ -58,10 +58,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray* rescued_ - DcevmSharedGC::update_fields(rescued_obj, new_obj); - } else { - rescued_obj->set_klass(new_klass); -- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -+ Copy::aligned_disjoint_words(cast_from_oop(rescued_obj), cast_from_oop(new_obj), size); - } - } else { -- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size); -+ Copy::aligned_disjoint_words(cast_from_oop(rescued_obj), cast_from_oop(new_obj), size); - } - - new_obj->init_mark_raw(); -@@ -111,11 +111,11 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) { - - // Save object somewhere, there is an overlap in fields - if (new_klass_oop->is_copying_backwards()) { -- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) || -- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) { -+ if ((cast_from_oop(q) >= cast_from_oop(new_location) && cast_from_oop(q) < cast_from_oop(new_location) + new_size) || -+ (cast_from_oop(new_location) >= cast_from_oop(q) && cast_from_oop(new_location) < cast_from_oop(q) + size)) { - tmp = NEW_RESOURCE_ARRAY(HeapWord, size); - q = (oop) tmp; -- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size); -+ Copy::aligned_disjoint_words(cast_from_oop(tmp_obj), cast_from_oop(q), size); - } - } - -@@ -131,13 +131,13 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) { - - void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) { - assert(cur != NULL, "just checking"); -- char* to = (char*)(HeapWord*)new_location; -+ char* to = (char*)cast_from_oop(new_location); - while (*cur != 0) { - int size = *cur; - if (size > 0) { - cur++; - int offset = *cur; -- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset); -+ HeapWord* from = (HeapWord*)(((char *)cast_from_oop(tmp_obj)) + offset); - if (size == HeapWordSize) { - *((HeapWord*)to) = *from; - } else if (size == HeapWordSize * 2) { -diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp -index e2ef0171fb2..a4e27e00280 100644 ---- a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp -+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp -@@ -29,7 +29,7 @@ - #include "gc/shared/genOopClosures.hpp" - #include "gc/shared/taskqueue.hpp" - #include "memory/iterator.hpp" --#include "oops/markOop.hpp" -+#include "oops/markWord.hpp" - #include "oops/oop.hpp" - #include "runtime/timer.hpp" - #include "utilities/growableArray.hpp" -diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp -index f01d64d1434..5c1a09390f1 100644 ---- a/src/hotspot/share/gc/shared/gcConfig.cpp -+++ b/src/hotspot/share/gc/shared/gcConfig.cpp -@@ -100,7 +100,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { - void GCConfig::select_gc_ergonomically() { - if (AllowEnhancedClassRedefinition && !UseG1GC) { - // Enhanced class redefinition only supports serial GC at the moment -- FLAG_SET_ERGO(bool, UseSerialGC, true); -+ FLAG_SET_ERGO(UseSerialGC, true); - } else if (os::is_server_class_machine()) { - #if INCLUDE_G1GC - FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); -diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp -index 9772c32c42e..e8e3d7884c2 100644 ---- a/src/hotspot/share/gc/shared/space.cpp -+++ b/src/hotspot/share/gc/shared/space.cpp -@@ -440,7 +440,7 @@ int CompactibleSpace::space_index(oop obj) { - index++; - } - -- tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj); -+ tty->print_cr("could not compute space_index for %08xh", cast_from_oop(obj)); - index = 0; - - Generation* gen = heap->old_gen(); -@@ -485,7 +485,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) { - bool new_in_tenured = tenured_gen->is_in_reserved(new_obj); - if (old_in_tenured == new_in_tenured) { - // Rescue if object may overlap with a higher memory address. -- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size); -+ bool overlap = (cast_from_oop(old_obj) + original_size < cast_from_oop(new_obj) + new_size); - if (old_in_tenured) { - // Old and new address are in same space, so just compare the address. - // Must rescue if object moves towards the top of the space. -diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp -index b2f24ddbeda..9daeeb70b34 100644 ---- a/src/hotspot/share/interpreter/linkResolver.cpp -+++ b/src/hotspot/share/interpreter/linkResolver.cpp -@@ -1031,7 +1031,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, - assert(m != NULL, "information about the current method must be available for 'put' bytecodes"); - bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic && - fd.is_static() && -- !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name())); -+ !(m->is_static_initializer() || m->name() == vmSymbols::ha_class_initializer_name())); - bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) && - !fd.is_static() && - !m->is_object_initializer()); -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index f8e60941046..5e40d78a87e 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -1316,7 +1316,7 @@ void InstanceKlass::init_implementor() { - // (DCEVM) - init_implementor() for dcevm - void InstanceKlass::init_implementor_from_redefine() { - assert(is_interface(), "not interface"); -- Klass** addr = adr_implementor(); -+ Klass* volatile* addr = adr_implementor(); - assert(addr != NULL, "null addr"); - if (addr != NULL) { - *addr = NULL; -@@ -1659,6 +1659,21 @@ void InstanceKlass::methods_do(void f(Method* method)) { - } - } - -+void InstanceKlass::methods_do(void f(Method* method, TRAPS), TRAPS) { -+ // Methods aren't stable until they are loaded. This can be read outside -+ // a lock through the ClassLoaderData for profiling -+ if (!is_loaded()) { -+ return; -+ } -+ -+ int len = methods()->length(); -+ for (int index = 0; index < len; index++) { -+ Method* m = methods()->at(index); -+ assert(m->is_method(), "must be method"); -+ f(m, CHECK); -+ } -+} -+ - // (DCEVM) Update information contains mapping of fields from old class to the new class. - // Info is stored on HEAP, you need to call clear_update_information to free the space. - void InstanceKlass::store_update_information(GrowableArray &values) { -diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp -index 6ead9426728..b56d42cb177 100644 ---- a/src/hotspot/share/oops/instanceKlass.hpp -+++ b/src/hotspot/share/oops/instanceKlass.hpp -@@ -1069,6 +1069,7 @@ public: - void clear_update_information(); - - void methods_do(void f(Method* method)); -+ void methods_do(void f(Method* method, TRAPS), TRAPS); - void array_klasses_do(void f(Klass* k)); - void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); - -diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp -index 352d8f84631..88f5ec9ba4a 100644 ---- a/src/hotspot/share/oops/klass.cpp -+++ b/src/hotspot/share/oops/klass.cpp -@@ -200,13 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word - Klass::Klass(KlassID id) : _id(id), - _java_mirror(NULL), - _prototype_header(markWord::prototype()), -- _shared_class_path_index(-1), -- _new_version(NULL), - _old_version(NULL), -+ _new_version(NULL), -+ _redefinition_flags(Klass::NoRedefinition), - _is_redefining(false), -+ _update_information(NULL), - _is_copying_backwards(false), -- _redefinition_flags(Klass::NoRedefinition), -- _update_information(NULL) { -+ _shared_class_path_index(-1) { - CDS_ONLY(_shared_class_flags = 0;) - CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;) - _primary_supers[0] = this; -diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp -index 333b65ccfc1..13bcac352fb 100644 ---- a/src/hotspot/share/prims/jvm.cpp -+++ b/src/hotspot/share/prims/jvm.cpp -@@ -1054,6 +1054,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na - class_loader, - protection_domain, - &st, -+ NULL, - CHECK_NULL); - - if (log_is_enabled(Debug, class, resolve) && defined_k != NULL) { -@@ -1074,6 +1075,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na - class_loader, - &st, - cl_info, -+ NULL, - CHECK_NULL); - if (defined_k == NULL) { - THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a hidden class"); -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 1da6661dd3e..619e3988e3a 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -24,11 +24,14 @@ - - #include "precompiled.hpp" - #include "aot/aotLoader.hpp" -+#include "classfile/classFileParser.hpp" - #include "classfile/classFileStream.hpp" - #include "classfile/metadataOnStackMark.hpp" - #include "classfile/systemDictionary.hpp" - #include "classfile/verifier.hpp" - #include "classfile/dictionary.hpp" -+#include "classfile/classLoaderDataGraph.hpp" -+#include "interpreter/linkResolver.hpp" - #include "interpreter/oopMapCache.hpp" - #include "interpreter/rewriter.hpp" - #include "logging/logStream.hpp" -@@ -37,17 +40,22 @@ - #include "memory/resourceArea.hpp" - #include "memory/iterator.inline.hpp" - #include "oops/fieldStreams.hpp" -+#include "oops/fieldStreams.inline.hpp" - #include "oops/klassVtable.hpp" - #include "oops/oop.inline.hpp" - #include "oops/constantPool.inline.hpp" -+#include "oops/metadata.hpp" -+#include "oops/methodData.hpp" - #include "prims/jvmtiImpl.hpp" - #include "prims/jvmtiClassFileReconstituter.hpp" - #include "prims/jvmtiEnhancedRedefineClasses.hpp" - #include "prims/methodComparator.hpp" - #include "prims/resolvedMethodTable.hpp" -+#include "prims/methodHandles.hpp" - #include "runtime/deoptimization.hpp" - #include "runtime/jniHandles.inline.hpp" - #include "runtime/relocator.hpp" -+#include "runtime/fieldDescriptor.hpp" - #include "runtime/fieldDescriptor.inline.hpp" - #include "utilities/bitMap.inline.hpp" - #include "prims/jvmtiThreadState.inline.hpp" -@@ -55,6 +63,8 @@ - #include "oops/constantPool.inline.hpp" - #include "gc/g1/g1CollectedHeap.hpp" - #include "gc/shared/dcevmSharedGC.hpp" -+#include "gc/shared/scavengableNMethods.hpp" -+#include "ci/ciObjectFactory.hpp" - - Array* VM_EnhancedRedefineClasses::_old_methods = NULL; - Array* VM_EnhancedRedefineClasses::_new_methods = NULL; -@@ -66,6 +76,7 @@ int VM_EnhancedRedefineClasses::_matching_methods_length = 0; - int VM_EnhancedRedefineClasses::_deleted_methods_length = 0; - int VM_EnhancedRedefineClasses::_added_methods_length = 0; - Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL; -+u8 VM_EnhancedRedefineClasses::_id_counter = 0; - - // - // Create new instance of enhanced class redefiner. -@@ -88,6 +99,7 @@ VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const j - _class_load_kind = class_load_kind; - _res = JVMTI_ERROR_NONE; - _any_class_has_resolved_methods = false; -+ _id = next_id(); - } - - static inline InstanceKlass* get_ik(jclass def) { -@@ -211,9 +223,7 @@ class FieldCopier : public FieldClosure { - - // TODO: review... - void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { -- if (!nm->on_scavenge_root_list()) { -- CodeCache::add_scavenge_root_nmethod(nm); -- } -+ ScavengableNMethods::register_nmethod(nm); - } - - void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { -@@ -414,7 +424,7 @@ public: - _tmp_obj_size = size; - _tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize); - } -- Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size); -+ Copy::aligned_disjoint_words(cast_from_oop(o), cast_from_oop(_tmp_obj), size); - } - - virtual void do_object(oop obj) { -@@ -505,9 +515,6 @@ void VM_EnhancedRedefineClasses::doit() { - ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); - ClassLoaderDataGraph::classes_do(&clear_cpool_cache); - -- -- // SystemDictionary::methods_do(fix_invoke_method); -- - // JSR-292 support - if (_any_class_has_resolved_methods) { - bool trace_name_printed = false; -@@ -564,8 +571,8 @@ void VM_EnhancedRedefineClasses::doit() { - InstanceKlass* old = InstanceKlass::cast(cur->old_version()); - - // Swap marks to have same hashcodes -- markOop cur_mark = cur->prototype_header(); -- markOop old_mark = old->prototype_header(); -+ markWord cur_mark = cur->prototype_header(); -+ markWord old_mark = old->prototype_header(); - cur->set_prototype_header(old_mark); - old->set_prototype_header(cur_mark); - -@@ -579,14 +586,14 @@ void VM_EnhancedRedefineClasses::doit() { - // Revert pool holder for old version of klass (it was updated by one of ours closure!) - old->constants()->set_pool_holder(old); - -- Klass* array_klasses = old->array_klasses(); -+ ObjArrayKlass* array_klasses = old->array_klasses(); - if (array_klasses != NULL) { - assert(cur->array_klasses() == NULL, "just checking"); - - // Transfer the array classes, otherwise we might get cast exceptions when casting array types. - // Also, set array klasses element klass. - cur->set_array_klasses(array_klasses); -- ObjArrayKlass::cast(array_klasses)->set_element_klass(cur); -+ array_klasses->set_element_klass(cur); - java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses); - java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror()); - } -@@ -641,11 +648,15 @@ void VM_EnhancedRedefineClasses::doit() { - //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); - - // Disable any dependent concurrent compilations -- SystemDictionary::notice_modification(); -+ // SystemDictionary::notice_modification(); -+ -+ JvmtiExport::increment_redefinition_count(); - - // Set flag indicating that some invariants are no longer true. - // See jvmtiExport.hpp for detailed explanation. -- JvmtiExport::set_has_redefined_a_class(); -+ -+ // dcevm15: handled by _redefinition_count -+ // JvmtiExport::set_has_redefined_a_class(); - - #ifdef PRODUCT - if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { -@@ -718,7 +729,7 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { - } - - // Cannot redefine or retransform an anonymous class. -- if (InstanceKlass::cast(k)->is_anonymous()) { -+ if (InstanceKlass::cast(k)->is_unsafe_anonymous()) { - return false; - } - return true; -@@ -804,22 +815,30 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - - InstanceKlass* k; - -- if (InstanceKlass::cast(the_class)->is_anonymous()) { -- const InstanceKlass* host_class = the_class->host_klass(); -+ if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) { -+ const InstanceKlass* host_class = the_class->unsafe_anonymous_host(); - - // Make sure it's the real host class, not another anonymous class. -- while (host_class != NULL && host_class->is_anonymous()) { -- host_class = host_class->host_klass(); -+ while (host_class != NULL && host_class->is_unsafe_anonymous()) { -+ host_class = host_class->unsafe_anonymous_host(); - } - -+ ClassLoadInfo cl_info(protection_domain, -+ host_class, -+ NULL, // dynamic_nest_host -+ NULL, // cp_patches -+ Handle(), // classData -+ false, // is_hidden -+ false, // is_strong_hidden -+ true); // FIXME: check if correct. can_access_vm_annotations -+ - k = SystemDictionary::parse_stream(the_class_sym, - the_class_loader, -- protection_domain, - &st, -- host_class, -+ cl_info, - the_class, -- NULL, - THREAD); -+ - k->class_loader_data()->exchange_holders(the_class->class_loader_data()); - the_class->class_loader_data()->inc_keep_alive(); - } else { -@@ -966,7 +985,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ - // Check interfaces - - // Interfaces removed? -- Array* old_interfaces = the_class->transitive_interfaces(); -+ Array* old_interfaces = the_class->transitive_interfaces(); - for (i = 0; i < old_interfaces->length(); i++) { - InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i)); - if (!new_class->implements_interface_any_version(old_interface)) { -@@ -976,7 +995,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_ - } - - // Interfaces added? -- Array* new_interfaces = new_class->transitive_interfaces(); -+ Array* new_interfaces = new_class->transitive_interfaces(); - for (i = 0; ilength(); i++) { - if (!the_class->implements_interface_any_version(new_interfaces->at(i))) { - result = result | Klass::ModifyClass; -@@ -1389,8 +1408,8 @@ void VM_EnhancedRedefineClasses::rollback() { - // Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp - // The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not - // do that, they assume that cache entry is resolved already. --void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) { -- RawBytecodeStream bcs(method); -+void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method, TRAPS) { -+ RawBytecodeStream bcs(methodHandle(THREAD, method)); - Bytecodes::Code code; - Bytecodes::Code java_code; - while (!bcs.is_last_bytecode()) { -@@ -1454,11 +1473,11 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - HandleMark hm(_thread); - InstanceKlass *ik = InstanceKlass::cast(k); - -- constantPoolHandle other_cp = constantPoolHandle(ik->constants()); -+ constantPoolHandle other_cp = constantPoolHandle(_thread, ik->constants()); - - // Update host klass of anonymous classes (for example, produced by lambdas) to newest version. -- if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) { -- ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version())); -+ if (ik->is_unsafe_anonymous() && ik->unsafe_anonymous_host()->new_version() != NULL) { -+ ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version())); - } - - // Update implementor if there is only one, in this case implementor() can reference old class -@@ -1492,7 +1511,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - - // If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries - if (RewriteBytecodes) { -- ik->methods_do(unpatch_bytecode); -+ ik->methods_do(unpatch_bytecode, _thread); -+ } -+} -+ -+u8 VM_EnhancedRedefineClasses::next_id() { -+ while (true) { -+ u8 id = _id_counter; -+ u8 next_id = id + 1; -+ u8 result = Atomic::cmpxchg(&_id_counter, id, next_id); -+ if (result == id) { -+ return next_id; -+ } - } - } - -@@ -1512,31 +1542,8 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) { - } - } - --void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) { -- -- constantPoolHandle other_cp = constantPoolHandle(method->constants()); -- -- for (int i = 0; i < other_cp->length(); i++) { -- if (other_cp->tag_at(i).is_klass()) { -- Klass* klass = other_cp->resolved_klass_at(i); -- if (klass->new_version() != NULL) { -- // Constant pool entry points to redefined class -- update to the new version -- other_cp->klass_at_put(i, klass->newest_version()); -- } -- assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!"); -- } -- } -- -- ConstantPoolCache* cp_cache = other_cp->cache(); -- if (cp_cache != NULL) { -- cp_cache->clear_entries(); -- } -- --} -- - -- --void VM_EnhancedRedefineClasses::update_jmethod_ids() { -+void VM_EnhancedRedefineClasses::update_jmethod_ids(TRAPS) { - for (int j = 0; j < _matching_methods_length; ++j) { - Method* old_method = _matching_old_methods[j]; - jmethodID jmid = old_method->find_jmethod_id_or_null(); -@@ -1547,10 +1554,10 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() { - - if (jmid != NULL) { - // There is a jmethodID, change it to point to the new method -- methodHandle new_method_h(_matching_new_methods[j]); -+ methodHandle new_method_h(THREAD, _matching_new_methods[j]); - - if (old_method->new_version() == NULL) { -- methodHandle old_method_h(_matching_old_methods[j]); -+ methodHandle old_method_h(THREAD, _matching_old_methods[j]); - jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h()); - bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id); - } else { -@@ -1887,7 +1894,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - - // track number of methods that are EMCP for add_previous_version() call below - check_methods_and_mark_as_obsolete(); -- update_jmethod_ids(); -+ update_jmethod_ids(THREAD); - - _any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods; - -@@ -2119,12 +2126,12 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { - - Handle protection_domain(THREAD, klass->protection_domain()); - -+ ClassLoadInfo cl_info(protection_domain); -+ - ClassFileParser parser(&st, - klass->name(), - klass->class_loader_data(), -- protection_domain, -- NULL, // host_klass -- NULL, // cp_patches -+ &cl_info, - ClassFileParser::INTERNAL, // publicity level - true, - THREAD); -@@ -2134,7 +2141,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { - links.append(KlassPair(super_klass, klass)); - } - -- Array* local_interfaces = parser.local_interfaces(); -+ Array* local_interfaces = parser.local_interfaces(); - for (int j = 0; j < local_interfaces->length(); j++) { - Klass* iface = local_interfaces->at(j); - if (iface != NULL && _affected_klasses->contains(iface)) { -@@ -2157,7 +2164,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) { - links.append(KlassPair(super_klass, klass)); - } - -- Array* local_interfaces = klass->local_interfaces(); -+ Array* local_interfaces = klass->local_interfaces(); - for (int j = 0; j < local_interfaces->length(); j++) { - Klass* interfaceKlass = local_interfaces->at(j); - if (_affected_klasses->contains(interfaceKlass)) { -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index 4c0412d343d..0066088b3b0 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -32,7 +32,7 @@ - #include "memory/resourceArea.hpp" - #include "oops/objArrayKlass.hpp" - #include "oops/objArrayOop.hpp" --#include "gc/shared/vmGCOperations.hpp" -+#include "gc/shared/gcVMOperations.hpp" - #include "../../../java.base/unix/native/include/jni_md.h" - - // -@@ -59,6 +59,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - static int _deleted_methods_length; - static int _added_methods_length; - static Klass* _the_class_oop; -+ static u8 _id_counter; - - // The instance fields are used to pass information from - // doit_prologue() to doit() and doit_epilogue(). -@@ -91,6 +92,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - elapsedTimer _timer_heap_iterate; - elapsedTimer _timer_heap_full_gc; - -+ // Redefinition id used by JFR -+ u8 _id; -+ - // These routines are roughly in call order unless otherwise noted. - - // Load and link new classes (either redefined or affected by redefinition - subclass, ...) -@@ -118,15 +122,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - static void mark_as_scavengable(nmethod* nm); - static void unregister_nmethod_g1(nmethod* nm); - static void register_nmethod_g1(nmethod* nm); -- static void unpatch_bytecode(Method* method); -- static void fix_invoke_method(Method* method); -+ static void unpatch_bytecode(Method* method, TRAPS); - - // Figure out which new methods match old methods in name and signature, - // which methods have been added, and which are no longer present - void compute_added_deleted_matching_methods(); - - // Change jmethodIDs to point to the new methods -- void update_jmethod_ids(); -+ void update_jmethod_ids(TRAPS); - - // marking methods as old and/or obsolete - void check_methods_and_mark_as_obsolete(); -@@ -141,6 +144,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - - void flush_dependent_code(InstanceKlass* k_h, TRAPS); - -+ u8 next_id(); -+ - static void check_class(InstanceKlass* k_oop, TRAPS); - - static void dump_methods(); -@@ -181,6 +186,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - - bool allow_nested_vm_operations() const { return true; } - jvmtiError check_error() { return _res; } -+ u8 id() { return _id; } - - // Modifiable test must be shared between IsModifiableClass query - // and redefine implementation -diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp -index b6838ac034d..fba0f48abd7 100644 ---- a/src/hotspot/share/prims/jvmtiEnv.cpp -+++ b/src/hotspot/share/prims/jvmtiEnv.cpp -@@ -456,20 +456,23 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { - - EventRetransformClasses event; - jvmtiError error; -+ u8 op_id; - - if (AllowEnhancedClassRedefinition) { - MutexLocker sd_mutex(EnhancedRedefineClasses_lock); - VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); - VMThread::execute(&op); -+ op_id = op.id(); - error = (op.check_error()); - } else { - VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); - VMThread::execute(&op); -+ op_id = op.id(); - error = op.check_error(); - } - if (error == JVMTI_ERROR_NONE) { - event.set_classCount(class_count); -- event.set_redefinitionId(op.id()); -+ event.set_redefinitionId(op_id); - event.commit(); - } - return error; -@@ -484,19 +487,23 @@ JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_de - EventRedefineClasses event; - jvmtiError error; - -+ u8 op_id; -+ - if (AllowEnhancedClassRedefinition) { - MutexLocker sd_mutex(EnhancedRedefineClasses_lock); - VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); - VMThread::execute(&op); -+ op_id = op.id(); - error = (op.check_error()); - } else { - VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); - VMThread::execute(&op); -+ op_id = op.id(); - error = op.check_error(); - } - if (error == JVMTI_ERROR_NONE) { - event.set_classCount(class_count); -- event.set_redefinitionId(op.id()); -+ event.set_redefinitionId(op_id); - event.commit(); - } - return error; -diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp -index a7840848e10..346eac7c431 100644 ---- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp -@@ -1271,6 +1271,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { - the_class_loader, - &st, - cl_info, -+ NULL, - THREAD); - // Clear class_being_redefined just to be sure. - state->clear_class_being_redefined(); -diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp -index 54f36202a5f..917d31efd77 100644 ---- a/src/hotspot/share/prims/methodHandles.hpp -+++ b/src/hotspot/share/prims/methodHandles.hpp -@@ -180,6 +180,9 @@ public: - assert(ref_kind_is_valid(ref_kind), ""); - return (ref_kind & 1) != 0; - } -+ static bool ref_kind_is_static(int ref_kind) { -+ return !ref_kind_has_receiver(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial); -+ } - - static int ref_kind_to_flags(int ref_kind); - -diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index d05a2893498..3a92b8869dc 100644 ---- a/src/hotspot/share/runtime/arguments.cpp -+++ b/src/hotspot/share/runtime/arguments.cpp -@@ -2128,13 +2128,15 @@ bool Arguments::check_gc_consistency() { - // of collectors. - uint i = 0; - if (UseSerialGC) i++; -- if (UseConcMarkSweepGC) i++; -- if (UseParallelGC || UseParallelOldGC) i++; -+ if (UseParallelGC) i++; - if (UseG1GC) i++; -+ if (UseEpsilonGC) i++; -+ if (UseZGC) i++; -+ if (UseShenandoahGC) i++; - if (AllowEnhancedClassRedefinition) { - // Must use serial GC. This limitation applies because the instance size changing GC modifications - // are only built into the mark and compact algorithm. -- if ((!UseSerialGC && !UseG1GC) && i >= 1) { -+ if (!UseSerialGC && !UseG1GC && i >= 1) { - jio_fprintf(defaultStream::error_stream(), - "Must use the Serial or G1 GC with enhanced class redefinition.\n"); - return false; -@@ -4494,18 +4496,18 @@ void Arguments::setup_hotswap_agent() { - - // TODO: open it only for org.hotswap.agent module - // Use to access java.lang.reflect.Proxy/proxyCache -- create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++); - // Class of field java.lang.reflect.Proxy/proxyCache -- create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++); - // Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream -- create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++); - // java.beans.Introspector access -- create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++); - // java.beans.Introspector access -- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++); - // com.sun.beans.introspect.ClassInfo access -- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++); - // com.sun.beans.introspect.util.Cache access -- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); -+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++); - - } -diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp -index 6f982072909..14a3ed730fe 100644 ---- a/src/hotspot/share/runtime/mutexLocker.cpp -+++ b/src/hotspot/share/runtime/mutexLocker.cpp -@@ -287,7 +287,7 @@ void mutex_init() { - def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never); - def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never); - def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); -- def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel -+ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, _safepoint_check_always); // for ensuring that class redefinition is not done in parallel - def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions - def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always); - --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch b/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch deleted file mode 100644 index 07669d9f157c..000000000000 --- a/jb/project/tools/patches/dcevm/0020-dcevm15-G1-fixes.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 336cab4f72c6e642e3077ea8d1a4860de33f5a4d Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Tue, 17 Nov 2020 17:40:24 +0100 -Subject: [PATCH 20/34] dcevm15 - G1 fixes - ---- - src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -index 2f06b9617e4..476728a5d26 100644 ---- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp -@@ -240,7 +240,7 @@ void G1FullGCPrepareTask::prepare_serial_compaction_dcevm() { - - // collect remaining, not forwarded rescued oops using serial compact point - while (cp->last_rescued_oop() < cp->rescued_oops()->length()) { -- HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, false, true); -+ HeapRegion* hr = G1CollectedHeap::heap()->new_region(HeapRegion::GrainBytes / HeapWordSize, HeapRegionType::Eden, true, G1NUMA::AnyNodeIndex); - if (hr == NULL) { - vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "G1 - not enough of free regions after redefinition."); - } --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch b/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch deleted file mode 100644 index a3f5e53ea123..000000000000 --- a/jb/project/tools/patches/dcevm/0021-dcevm15-Fix-flush-dependent-code.patch +++ /dev/null @@ -1,133 +0,0 @@ -From cea4e2cca3c37233c728be7235f8f9d8be136cb5 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Tue, 17 Nov 2020 18:52:57 +0100 -Subject: [PATCH 21/34] dcevm15 - Fix flush dependent code - ---- - .../prims/jvmtiEnhancedRedefineClasses.cpp | 57 +++++++------------ - .../prims/jvmtiEnhancedRedefineClasses.hpp | 4 +- - 2 files changed, 25 insertions(+), 36 deletions(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 619e3988e3a..efaf11e1666 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -508,7 +508,7 @@ void VM_EnhancedRedefineClasses::doit() { - - // Deoptimize all compiled code that depends on this class (do only once, because it clears whole cache) - // if (_max_redefinition_flags > Klass::ModifyClass) { -- flush_dependent_code(NULL, thread); -+ flush_dependent_code(thread); - // } - - // Adjust constantpool caches for all classes that reference methods of the evolved class. -@@ -647,17 +647,8 @@ void VM_EnhancedRedefineClasses::doit() { - //MethodDataCleaner clean_weak_method_links; - //ClassLoaderDataGraph::classes_do(&clean_weak_method_links); - -- // Disable any dependent concurrent compilations -- // SystemDictionary::notice_modification(); -- - JvmtiExport::increment_redefinition_count(); - -- // Set flag indicating that some invariants are no longer true. -- // See jvmtiExport.hpp for detailed explanation. -- -- // dcevm15: handled by _redefinition_count -- // JvmtiExport::set_has_redefined_a_class(); -- - #ifdef PRODUCT - if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) { - #endif -@@ -1746,6 +1737,18 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst - transfer.transfer_registrations(_matching_old_methods, _matching_methods_length); - } - -+// First step is to walk the code cache for each class redefined and mark -+// dependent methods. Wait until all classes are processed to deoptimize everything. -+void VM_EnhancedRedefineClasses::mark_dependent_code(InstanceKlass* ik) { -+ assert_locked_or_safepoint(Compile_lock); -+ -+ // All dependencies have been recorded from startup or this is a second or -+ // subsequent use of RedefineClasses -+ if (0 && JvmtiExport::all_dependencies_are_recorded()) { -+ CodeCache::mark_for_evol_deoptimization(ik); -+ } -+} -+ - // DCEVM - it always deoptimizes everything! (because it is very difficult to find only correct dependencies) - // Deoptimize all compiled code that depends on this class. - // -@@ -1762,33 +1765,21 @@ void VM_EnhancedRedefineClasses::transfer_old_native_function_registrations(Inst - // subsequent calls to RedefineClasses need only throw away code - // that depends on the class. - // --void VM_EnhancedRedefineClasses::flush_dependent_code(InstanceKlass* k_h, TRAPS) { -+void VM_EnhancedRedefineClasses::flush_dependent_code(TRAPS) { - assert_locked_or_safepoint(Compile_lock); - - // All dependencies have been recorded from startup or this is a second or - // subsequent use of RedefineClasses - // FIXME: for now, deoptimize all! -- if (0 && k_h != NULL && JvmtiExport::all_dependencies_are_recorded()) { -- CodeCache::flush_evol_dependents_on(k_h); -- Klass* superCl = k_h->super(); -- // Deoptimize super classes since redefined class can has a new method override -- while (superCl != NULL && !superCl->is_redefining()) { -- CodeCache::flush_evol_dependents_on(InstanceKlass::cast(superCl)); -- superCl = superCl->super(); -+ if (0 && JvmtiExport::all_dependencies_are_recorded()) { -+ int deopt = CodeCache::mark_dependents_for_evol_deoptimization(); -+ log_debug(redefine, class, nmethod)("Marked %d dependent nmethods for deopt", deopt); -+ if (deopt != 0) { -+ CodeCache::flush_evol_dependents(); - } - } else { -- CodeCache::mark_all_nmethods_for_deoptimization(); -- -- ResourceMark rm(THREAD); -- DeoptimizationMarker dm; -- -- // Deoptimize all activations depending on marked nmethods -- Deoptimization::deoptimize_dependents(); -- -- // Make the dependent methods not entrant -- CodeCache::make_marked_nmethods_not_entrant(); -- -- // From now on we know that the dependency information is complete -+ CodeCache::mark_all_nmethods_for_evol_deoptimization(); -+ CodeCache::flush_evol_dependents(); - JvmtiExport::set_all_dependencies_are_recorded(true); - } - } -@@ -1881,11 +1872,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_ - JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); - jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); - -- // DCEVM Deoptimization is always for whole java world, call only once after all classes are redefined -- // Deoptimize all compiled code that depends on this class --// if (_max_redefinition_flags <= Klass::ModifyClass) { --// flush_dependent_code(the_class, THREAD); --// } -+ mark_dependent_code(the_class); - - _old_methods = the_class->methods(); - _new_methods = new_class->methods(); -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index 0066088b3b0..bd5e7d153be 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -142,7 +142,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // and in all direct and indirect subclasses. - void increment_class_counter(InstanceKlass *ik, TRAPS); - -- void flush_dependent_code(InstanceKlass* k_h, TRAPS); -+ void mark_dependent_code(InstanceKlass* ik); -+ -+ void flush_dependent_code(TRAPS); - - u8 next_id(); - --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch b/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch deleted file mode 100644 index bacf2ee70262..000000000000 --- a/jb/project/tools/patches/dcevm/0022-dcevm15-fix-ResolvedMethodTable.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 4f88dcec830d39452f69d1117729469fdb768a8f Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 22 Nov 2020 12:05:26 +0100 -Subject: [PATCH 22/34] dcevm15 - fix ResolvedMethodTable - ---- - src/hotspot/share/classfile/javaClasses.cpp | 5 - - src/hotspot/share/classfile/javaClasses.hpp | 1 - - .../share/prims/resolvedMethodTable.cpp | 139 +++++++++++------- - 3 files changed, 84 insertions(+), 61 deletions(-) - -diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp -index 9b086a241f7..9a627786d0f 100644 ---- a/src/hotspot/share/classfile/javaClasses.cpp -+++ b/src/hotspot/share/classfile/javaClasses.cpp -@@ -3996,11 +3996,6 @@ void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop - resolved_method->obj_field_put(_vmholder_offset, holder); - } - --void java_lang_invoke_ResolvedMethodName::set_vmholder_offset(oop resolved_method, Method* m) { -- assert(is_instance(resolved_method), "wrong type"); -- resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror()); --} -- - oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) { - const Method* method = m(); - -diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp -index 9abf2e1d105..8f5993b7225 100644 ---- a/src/hotspot/share/classfile/javaClasses.hpp -+++ b/src/hotspot/share/classfile/javaClasses.hpp -@@ -1107,7 +1107,6 @@ class java_lang_invoke_ResolvedMethodName : AllStatic { - - static Method* vmtarget(oop resolved_method); - static void set_vmtarget(oop resolved_method, Method* method); -- static void set_vmholder_offset(oop resolved_method, Method* method); - - static void set_vmholder(oop resolved_method, oop holder); - -diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp -index eb9fcda44f3..d0f1667b967 100644 ---- a/src/hotspot/share/prims/resolvedMethodTable.cpp -+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp -@@ -375,6 +375,67 @@ public: - } - }; - -+class AdjustMethodEntriesDcevm : public StackObj { -+ bool* _trace_name_printed; -+ GrowableArray* _oops_to_add; -+public: -+ AdjustMethodEntriesDcevm(GrowableArray* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {}; -+ bool operator()(WeakHandle* entry) { -+ oop mem_name = entry->peek(); -+ if (mem_name == NULL) { -+ // Removed -+ return true; -+ } -+ -+ Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); -+ -+ if (old_method->is_old()) { -+ -+ InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); -+ Method* newer_method; -+ -+ // Method* new_method; -+ if (old_method->is_deleted()) { -+ newer_method = Universe::throw_no_such_method_error(); -+ } else { -+ newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); -+ -+ log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); -+ -+ assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); -+ assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -+ assert(old_method != newer_method, "sanity check"); -+ -+ Thread* thread = Thread::current(); -+ ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method); -+ ResolvedMethodGet rmg(thread, newer_method); -+ -+ if (_local_table->get(thread, lookup, rmg)) { -+ // old method was already adjusted if new method exists in _the_table -+ return true; -+ } -+ } -+ -+ java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); -+ java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror()); -+ -+ newer_klass->set_has_resolved_methods(); -+ _oops_to_add->append(mem_name); -+ -+ ResourceMark rm; -+ if (!(*_trace_name_printed)) { -+ log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); -+ *_trace_name_printed = true; -+ } -+ log_debug(redefine, class, update, constantpool) -+ ("ResolvedMethod method update: %s(%s)", -+ newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); -+ } -+ -+ return true; -+ } -+}; -+ - // It is called at safepoint only for RedefineClasses - void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); -@@ -382,73 +443,41 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { - AdjustMethodEntries adjust(trace_name_printed); - _local_table->do_safepoint_scan(adjust); - } --#endif // INCLUDE_JVMTI - --// (DCEVM) It is called at safepoint only for RedefineClasses -+// It is called at safepoint only for RedefineClasses - void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); - // For each entry in RMT, change to new method -- GrowableArray* oops_to_add = new GrowableArray(); -- -- for (int i = 0; i < _the_table->table_size(); ++i) { -- for (ResolvedMethodEntry* entry = _the_table->bucket(i); -- entry != NULL; -- entry = entry->next()) { -- -- oop mem_name = entry->object_no_keepalive(); -- // except ones removed -- if (mem_name == NULL) { -- continue; -- } -- Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); -- -- if (old_method->is_old()) { -- -- InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version()); -- Method* newer_method; -- -- // Method* new_method; -- if (old_method->is_deleted()) { -- newer_method = Universe::throw_no_such_method_error(); -- } else { -- newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum()); -- -- log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string()); -- -- assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts"); -- assert(newer_method != NULL, "method_with_idnum() should not be NULL"); -- assert(old_method != newer_method, "sanity check"); -- -- if (_the_table->lookup(newer_method) != NULL) { -- // old method was already adjusted if new method exists in _the_table -- continue; -- } -- } -+ GrowableArray oops_to_add(0); -+ AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed); -+ _local_table->do_safepoint_scan(adjust); -+ Thread* thread = Thread::current(); -+ for (int i = 0; i < oops_to_add.length(); i++) { -+ oop mem_name = oops_to_add.at(i); -+ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); - -- java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method); -- java_lang_invoke_ResolvedMethodName::set_vmholder_offset(mem_name, newer_method); -+ // The hash table takes ownership of the WeakHandle, even if it's not inserted. - -- newer_klass->set_has_resolved_methods(); -- oops_to_add->append(mem_name); -+ ResolvedMethodTableLookup lookup(thread, method_hash(method), method); -+ ResolvedMethodGet rmg(thread, method); - -- ResourceMark rm; -- if (!(*trace_name_printed)) { -- log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); -- *trace_name_printed = true; -- } -- log_debug(redefine, class, update, constantpool) -- ("ResolvedMethod method update: %s(%s)", -- newer_method->name()->as_C_string(), newer_method->signature()->as_C_string()); -+ while (true) { -+ if (_local_table->get(thread, lookup, rmg)) { -+ break; -+ } -+ WeakHandle wh = WeakHandle::create(Handle(thread, mem_name)); -+ // The hash table takes ownership of the WeakHandle, even if it's not inserted. -+ if (_local_table->insert(thread, lookup, wh)) { -+ log_insert(method); -+ wh.resolve(); -+ break; - } -- } -- for (int i = 0; i < oops_to_add->length(); i++) { -- oop mem_name = oops_to_add->at(i); -- Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); -- _the_table->basic_add(method, Handle(Thread::current(), mem_name)); - } - } - } - -+#endif // INCLUDE_JVMTI -+ - // Verification - class VerifyResolvedMethod : StackObj { - public: --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch b/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch deleted file mode 100644 index 7d07940541a2..000000000000 --- a/jb/project/tools/patches/dcevm/0023-dcevm15-fix-Universe-root_oops_do.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 5379e56465d3d3930ec7ea91b1c64db2cdf70170 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 22 Nov 2020 12:05:50 +0100 -Subject: [PATCH 23/34] dcevm15 - fix Universe::root_oops_do - ---- - src/hotspot/share/memory/universe.cpp | 38 +++++++++------------------ - 1 file changed, 12 insertions(+), 26 deletions(-) - -diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp -index f6e4253b5a5..8dad437bd51 100644 ---- a/src/hotspot/share/memory/universe.cpp -+++ b/src/hotspot/share/memory/universe.cpp -@@ -39,6 +39,7 @@ - #include "gc/shared/gcConfig.hpp" - #include "gc/shared/gcLogPrecious.hpp" - #include "gc/shared/gcTraceTime.inline.hpp" -+#include "gc/shared/weakProcessor.hpp" - #include "interpreter/interpreter.hpp" - #include "logging/log.hpp" - #include "logging/logStream.hpp" -@@ -75,6 +76,7 @@ - #include "runtime/thread.inline.hpp" - #include "runtime/timerTrace.hpp" - #include "runtime/vmOperations.hpp" -+#include "services/management.hpp" - #include "services/memoryService.hpp" - #include "utilities/align.hpp" - #include "utilities/copy.hpp" -@@ -180,45 +182,29 @@ void Universe::basic_type_classes_do(KlassClosure *closure) { - - // FIXME: (DCEVM) This method should iterate all pointers that are not within heap objects. - void Universe::root_oops_do(OopClosure *oopClosure) { -- -- class AlwaysTrueClosure: public BoolObjectClosure { -- public: -- void do_object(oop p) { ShouldNotReachHere(); } -- bool do_object_b(oop p) { return true; } -- }; -- AlwaysTrueClosure always_true; -- - Universe::oops_do(oopClosure); - // ReferenceProcessor::oops_do(oopClosure); (tw) check why no longer there - JNIHandles::oops_do(oopClosure); // Global (strong) JNI handles - Threads::oops_do(oopClosure, NULL); - ObjectSynchronizer::oops_do(oopClosure); -- // TODO: review, flat profiler was removed in j10 -- // FlatProfiler::oops_do(oopClosure); -- JvmtiExport::oops_do(oopClosure); -+ // (DCEVM) TODO: Check if this is correct? -+ Management::oops_do(oopClosure); -+ OopStorageSet::vm_global()->oops_do(oopClosure); -+ CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); -+ ClassLoaderDataGraph::cld_do(&cld_closure); - - // Now adjust pointers in remaining weak roots. (All of which should - // have been cleared if they pointed to non-surviving objects.) - // Global (weak) JNI handles -- JNIHandles::weak_oops_do(&always_true, oopClosure); -+ WeakProcessor::oops_do(oopClosure); - - CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); - CodeCache::blobs_do(&blobClosure); -- StringTable::oops_do(oopClosure); -+ AOT_ONLY(AOTLoader::oops_do(oopClosure);) -+ // StringTable::oops_do was removed in j15 -+ // StringTable::oops_do(oopClosure); - -- // (DCEVM) TODO: Check if this is correct? -- //CodeCache::scavenge_root_nmethods_oops_do(oopClosure); -- //Management::oops_do(oopClosure); -- //ref_processor()->weak_oops_do(&oopClosure); -- //PSScavenge::reference_processor()->weak_oops_do(&oopClosure); -- --#if INCLUDE_AOT -- if (UseAOT) { -- AOTLoader::oops_do(oopClosure); -- } --#endif -- // SO_AllClasses -- SystemDictionary::oops_do(oopClosure); -+ // PSScavenge::reference_processor()->weak_oops_do(oopClosure); - } - - void Universe::oops_do(OopClosure* f) { --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch b/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch deleted file mode 100644 index 1034569627ee..000000000000 --- a/jb/project/tools/patches/dcevm/0024-Cleanup-dcevm-comments.patch +++ /dev/null @@ -1,67 +0,0 @@ -From c6ea68e66d37d70739f7b0ee74131322b4526a68 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 22 Nov 2020 12:03:32 +0100 -Subject: [PATCH 24/34] Cleanup dcevm comments - ---- - src/hotspot/share/classfile/classLoaderDataGraph.hpp | 2 +- - src/hotspot/share/classfile/systemDictionary.hpp | 2 +- - src/hotspot/share/gc/shared/gcConfig.cpp | 2 +- - src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.hpp b/src/hotspot/share/classfile/classLoaderDataGraph.hpp -index f380aa3fa34..8ce94cccb47 100644 ---- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp -+++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp -@@ -104,7 +104,7 @@ class ClassLoaderDataGraph : public AllStatic { - - static void dictionary_classes_do(KlassClosure* klass_closure); - -- // Enhanced class redefinition -+ // (DCEVM) Enhanced class redefinition - static void rollback_redefinition(); - - // VM_CounterDecay iteration support -diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp -index 931e655d631..1019dbd0d04 100644 ---- a/src/hotspot/share/classfile/systemDictionary.hpp -+++ b/src/hotspot/share/classfile/systemDictionary.hpp -@@ -455,7 +455,7 @@ public: - static bool is_well_known_klass(Symbol* class_name); - #endif - -- // Enhanced class redefinition -+ // (DCEVM) Enhanced class redefinition - static void remove_from_hierarchy(InstanceKlass* k); - static void update_constraints_after_redefinition(); - -diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp -index 5c1a09390f1..23fbf715378 100644 ---- a/src/hotspot/share/gc/shared/gcConfig.cpp -+++ b/src/hotspot/share/gc/shared/gcConfig.cpp -@@ -99,7 +99,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() { - - void GCConfig::select_gc_ergonomically() { - if (AllowEnhancedClassRedefinition && !UseG1GC) { -- // Enhanced class redefinition only supports serial GC at the moment -+ // (DCEVM) Enhanced class redefinition only supports serial GC at the moment - FLAG_SET_ERGO(UseSerialGC, true); - } else if (os::is_server_class_machine()) { - #if INCLUDE_G1GC -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -index bd5e7d153be..5de375fb888 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp -@@ -78,7 +78,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation { - // have any entries. - bool _any_class_has_resolved_methods; - -- // Enhanced class redefinition, affected klasses contain all classes which should be redefined -+ // (DCEVM) Enhanced class redefinition, affected klasses contain all classes which should be redefined - // either because of redefine, class hierarchy or interface change - GrowableArray* _affected_klasses; - --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch b/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch deleted file mode 100644 index dbc33ff000be..000000000000 --- a/jb/project/tools/patches/dcevm/0025-Fix-cpCache-in-not-AllowEnhancedClassRedefinition-mo.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 507d97966c7145d0ae2533459cc504c7b0d6d5b6 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 22 Nov 2020 18:49:05 +0100 -Subject: [PATCH 25/34] Fix cpCache in not AllowEnhancedClassRedefinition mode - ---- - src/hotspot/share/oops/cpCache.hpp | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp -index 121a13b1dda..64dcf6223f5 100644 ---- a/src/hotspot/share/oops/cpCache.hpp -+++ b/src/hotspot/share/oops/cpCache.hpp -@@ -148,13 +148,13 @@ class ConstantPoolCacheEntry { - void set_bytecode_2(Bytecodes::Code code); - void set_f1(Metadata* f1) { - Metadata* existing_f1 = _f1; // read once -- //assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); -+ assert(AllowEnhancedClassRedefinition || existing_f1 == NULL || existing_f1 == f1, "illegal field change"); - _f1 = f1; - } - void release_set_f1(Metadata* f1); - void set_f2(intx f2) { - intx existing_f2 = _f2; // read once -- //assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); -+ assert(AllowEnhancedClassRedefinition || existing_f2 == 0 || existing_f2 == f2, "illegal field change"); - _f2 = f2; - } - void set_f2_as_vfinal_method(Method* f2) { -@@ -215,7 +215,9 @@ class ConstantPoolCacheEntry { - void initialize_resolved_reference_index(int ref_index) { - assert(_f2 == 0, "set once"); // note: ref_index might be zero also - _f2 = ref_index; -- _flags = 1 << is_resolved_ref_shift; -+ if (AllowEnhancedClassRedefinition) { -+ _flags = 1 << is_resolved_ref_shift; -+ } - } - - void set_field( // sets entry to resolved field state --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch b/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch deleted file mode 100644 index 09c62476de4f..000000000000 --- a/jb/project/tools/patches/dcevm/0026-dcevm15-add-ClassLoaderDataGraph_lock-on.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b516b615c20fafa2094dfb9f4cb08245b26418d0 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 22 Nov 2020 19:51:46 +0100 -Subject: [PATCH 26/34] dcevm15 - add ClassLoaderDataGraph_lock on - ClassLoaderDataGraph::classes_do - -ClassLoaderDataGraph::classes_do need safepoint or lock, -find_sorted_affected_classes is not in safepoint therefore it must be -locked ---- - src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index efaf11e1666..197e1c0029f 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -2063,7 +2063,10 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) { - AffectedKlassClosure closure(_affected_klasses); - // Updated in j10, from original SystemDictionary::classes_do - -- ClassLoaderDataGraph::classes_do(&closure); -+ { -+ MutexLocker mcld(ClassLoaderDataGraph_lock); -+ ClassLoaderDataGraph::classes_do(&closure); -+ } - //ClassLoaderDataGraph::dictionary_classes_do(&closure); - - log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length()); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch b/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch deleted file mode 100644 index 9454776c0d92..000000000000 --- a/jb/project/tools/patches/dcevm/0027-dcevm15-check-if-has_nestmate_access_to-has-newest-h.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c6498946006879314bdc6218ee72da5d9c88f237 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sat, 28 Nov 2020 19:29:42 +0100 -Subject: [PATCH 27/34] dcevm15 - check if has_nestmate_access_to has newest - host class - ---- - src/hotspot/share/oops/instanceKlass.cpp | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp -index 5e40d78a87e..1d9623f2446 100644 ---- a/src/hotspot/share/oops/instanceKlass.cpp -+++ b/src/hotspot/share/oops/instanceKlass.cpp -@@ -445,6 +445,11 @@ bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) { - return false; - } - -+ if (AllowEnhancedClassRedefinition) { -+ // TODO: (DCEVM) check if it correct. It fix problems with lambdas (hidden) -+ cur_host = InstanceKlass::cast(cur_host->newest_version()); -+ } -+ - Klass* k_nest_host = k->nest_host(CHECK_false); - if (k_nest_host == NULL) { - return false; --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch b/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch deleted file mode 100644 index c2f943ec75aa..000000000000 --- a/jb/project/tools/patches/dcevm/0028-Remove-unused-fieldType.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 86c27155386c1c40642c99c63a242d1f5d8601a5 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sat, 28 Nov 2020 19:31:08 +0100 -Subject: [PATCH 28/34] Remove unused fieldType - ---- - src/hotspot/share/classfile/vmSymbols.hpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp -index 6a3b234b222..eb06684a288 100644 ---- a/src/hotspot/share/classfile/vmSymbols.hpp -+++ b/src/hotspot/share/classfile/vmSymbols.hpp -@@ -465,7 +465,6 @@ - template(static_offset_name, "staticOffset") \ - template(static_base_name, "staticBase") \ - template(field_offset_name, "fieldOffset") \ -- template(field_type_name, "fieldType") \ - \ - /* name symbols needed by intrinsics */ \ - \ --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch b/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch deleted file mode 100644 index 66c3844e93f2..000000000000 --- a/jb/project/tools/patches/dcevm/0029-mark_as_scavengable-only-alive-methods.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 025d0d2903963fb79f83cf0d90418783d3ef6813 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 17:18:16 +0100 -Subject: [PATCH 29/34] mark_as_scavengable only alive methods - ---- - .../share/prims/jvmtiEnhancedRedefineClasses.cpp | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index 197e1c0029f..e00fac1f693 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -223,19 +223,21 @@ class FieldCopier : public FieldClosure { - - // TODO: review... - void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) { -- ScavengableNMethods::register_nmethod(nm); -+ if (nm->is_alive()) { -+ ScavengableNMethods::register_nmethod(nm); -+ } - } - - void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) { - // It should work not only for G1 but also for another GCs, but this way is safer now -- if (!nm->is_zombie() && !nm->is_unloaded()) { -+ if (nm->is_alive()) { - Universe::heap()->unregister_nmethod(nm); - } - } - - void VM_EnhancedRedefineClasses::register_nmethod_g1(nmethod* nm) { - // It should work not only for G1 but also for another GCs, but this way is safer now -- if (!nm->is_zombie() && !nm->is_unloaded()) { -+ if (nm->is_alive()) { - Universe::heap()->register_nmethod(nm); - } - } -@@ -511,9 +513,9 @@ void VM_EnhancedRedefineClasses::doit() { - flush_dependent_code(thread); - // } - -- // Adjust constantpool caches for all classes that reference methods of the evolved class. -- ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); -- ClassLoaderDataGraph::classes_do(&clear_cpool_cache); -+ // Adjust constantpool caches for all classes that reference methods of the evolved class. -+ ClearCpoolCacheAndUnpatch clear_cpool_cache(thread); -+ ClassLoaderDataGraph::classes_do(&clear_cpool_cache); - - // JSR-292 support - if (_any_class_has_resolved_methods) { --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch b/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch deleted file mode 100644 index 20f9c81e6dc5..000000000000 --- a/jb/project/tools/patches/dcevm/0030-dcevm15-lock-on-ClassLoaderDataGraph-rollback_redefi.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 27aabfefe7d799545049bb81ba19d4ed2ff6379c Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 17:20:11 +0100 -Subject: [PATCH 30/34] dcevm15 - lock on - ClassLoaderDataGraph::rollback_redefinition - -rollback is not in safepoint, therefore must be locked ---- - src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index e00fac1f693..db5fb1c472b 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -1382,7 +1382,9 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne - // Rollback all changes - clear new classes from the system dictionary, return old classes to directory, free memory. - void VM_EnhancedRedefineClasses::rollback() { - log_info(redefine, class, load)("Rolling back redefinition, result=%d", _res); -+ ClassLoaderDataGraph_lock->lock(); - ClassLoaderDataGraph::rollback_redefinition(); -+ ClassLoaderDataGraph_lock->unlock(); - - for (int i = 0; i < _new_classes->length(); i++) { - SystemDictionary::remove_from_hierarchy(_new_classes->at(i)); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch b/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch deleted file mode 100644 index 1758fa26919b..000000000000 --- a/jb/project/tools/patches/dcevm/0031-ResourceMark-in-G1IterateObjectClosureTask-fixing-me.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 9b405cb642d5935c39c8dbd522ea2fdecfc29ef3 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 19:59:50 +0100 -Subject: [PATCH 31/34] ResourceMark in G1IterateObjectClosureTask fixing - memory leaks - -G1IterateObjectClosureTask is used only in redefinition full GC run ---- - src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -index a29d2dddc2d..2af6df6c1e4 100644 ---- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp -@@ -2362,6 +2362,9 @@ class G1IterateObjectClosureTask : public AbstractGangTask { - _cl(cl), _g1h(g1h), _hrclaimer(g1h->workers()->active_workers()) { } - - virtual void work(uint worker_id) { -+ Thread *thread = Thread::current(); -+ HandleMark hm(thread); // make sure any handles created are deleted -+ ResourceMark rm(thread); - IterateObjectClosureRegionClosure blk(_cl); - _g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id); - } --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch b/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch deleted file mode 100644 index e8fbfc04eeac..000000000000 --- a/jb/project/tools/patches/dcevm/0032-dcevm15-fix-hidded-classes.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 40fe40884d4efc50864bb3f2dd88f0a2e7122d5a Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 20:05:03 +0100 -Subject: [PATCH 32/34] dcevm15 - fix hidded classes - ---- - .../prims/jvmtiEnhancedRedefineClasses.cpp | 41 ++++++++++++++----- - 1 file changed, 30 insertions(+), 11 deletions(-) - -diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -index db5fb1c472b..590f7fdfafe 100644 ---- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp -@@ -722,7 +722,8 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) { - } - - // Cannot redefine or retransform an anonymous class. -- if (InstanceKlass::cast(k)->is_unsafe_anonymous()) { -+ // TODO: check if is correct in j15 -+ if (InstanceKlass::cast(k)->is_unsafe_anonymous() || InstanceKlass::cast(k)->is_hidden()) { - return false; - } - return true; -@@ -808,21 +809,27 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - - InstanceKlass* k; - -- if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) { -- const InstanceKlass* host_class = the_class->unsafe_anonymous_host(); -+ if (the_class->is_unsafe_anonymous() || the_class->is_hidden()) { -+ InstanceKlass* dynamic_host_class = NULL; -+ InstanceKlass* unsafe_anonymous_host = NULL; - -- // Make sure it's the real host class, not another anonymous class. -- while (host_class != NULL && host_class->is_unsafe_anonymous()) { -- host_class = host_class->unsafe_anonymous_host(); -+ if (the_class->is_hidden()) { -+ log_debug(redefine, class, load)("loading hidden class %s", the_class->name()->as_C_string()); -+ dynamic_host_class = the_class->nest_host(THREAD); -+ } -+ -+ if (the_class->is_unsafe_anonymous()) { -+ log_debug(redefine, class, load)("loading usafe anonymous %s", the_class->name()->as_C_string()); -+ unsafe_anonymous_host = the_class->unsafe_anonymous_host(); - } - - ClassLoadInfo cl_info(protection_domain, -- host_class, -- NULL, // dynamic_nest_host -+ unsafe_anonymous_host, - NULL, // cp_patches -+ dynamic_host_class, // dynamic_nest_host - Handle(), // classData -- false, // is_hidden -- false, // is_strong_hidden -+ the_class->is_hidden(), // is_hidden -+ !the_class->is_non_strong_hidden(), // is_strong_hidden - true); // FIXME: check if correct. can_access_vm_annotations - - k = SystemDictionary::parse_stream(the_class_sym, -@@ -833,7 +840,17 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) { - THREAD); - - k->class_loader_data()->exchange_holders(the_class->class_loader_data()); -- the_class->class_loader_data()->inc_keep_alive(); -+ -+ if (the_class->is_hidden()) { -+ // from jvm_lookup_define_class() (jvm.cpp): -+ // The hidden class loader data has been artificially been kept alive to -+ // this point. The mirror and any instances of this class have to keep -+ // it alive afterwards. -+ the_class->class_loader_data()->dec_keep_alive(); -+ } else { -+ the_class->class_loader_data()->inc_keep_alive(); -+ } -+ - } else { - k = SystemDictionary::resolve_from_stream(the_class_sym, - the_class_loader, -@@ -1475,6 +1492,8 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) { - ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version())); - } - -+ // FIXME: check new nest_host for hidden -+ - // Update implementor if there is only one, in this case implementor() can reference old class - if (ik->is_interface()) { - Klass* implKlass = ik->implementor(); --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch b/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch deleted file mode 100644 index f303ca4fa0a3..000000000000 --- a/jb/project/tools/patches/dcevm/0033-dcevm15-DON-T-clear-F2-in-CP-cache-after-indy-unevol.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 29920b076b4ad96d85adbce0a1d947e5022ba3ad Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 20:08:57 +0100 -Subject: [PATCH 33/34] dcevm15 - DON'T clear F2 in CP cache after indy - unevolving - -It's not clear why it was cleared in dcevm7-11 ---- - src/hotspot/share/oops/cpCache.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp -index 79a38dbeff0..650e6fab42d 100644 ---- a/src/hotspot/share/oops/cpCache.cpp -+++ b/src/hotspot/share/oops/cpCache.cpp -@@ -650,7 +650,7 @@ void ConstantPoolCacheEntry::clear_entry() { - - if (clearData) { - if (!is_resolved_reference()) { -- _f2 = 0; -+ // _f2 = 0; - } - // FIXME: (DCEVM) we want to clear flags, but parameter size is actually used - // after we return from the method, before entry is re-initialized. So let's --- -2.23.0 - diff --git a/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch b/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch deleted file mode 100644 index 0fb5efa03e18..000000000000 --- a/jb/project/tools/patches/dcevm/0034-dcevm15-fix-Universe-root_oops_do.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 1f13b20ab5553182680045b7d7324ff92da7e7f0 Mon Sep 17 00:00:00 2001 -From: Vladimir Dvorak -Date: Sun, 29 Nov 2020 21:28:06 +0100 -Subject: [PATCH 34/34] dcevm15 - fix Universe::root_oops_do - -Removed ClassLoaderDataGraph::cld_do was cause of crashes due multiple -oop patching. ClassLoaderDataGraph::cld_do replaced in dcevm15 -previously used and removed SystemDictionary:oops_do ---- - src/hotspot/share/memory/universe.cpp | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp -index 8dad437bd51..0199962a684 100644 ---- a/src/hotspot/share/memory/universe.cpp -+++ b/src/hotspot/share/memory/universe.cpp -@@ -190,21 +190,26 @@ void Universe::root_oops_do(OopClosure *oopClosure) { - // (DCEVM) TODO: Check if this is correct? - Management::oops_do(oopClosure); - OopStorageSet::vm_global()->oops_do(oopClosure); -- CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); -- ClassLoaderDataGraph::cld_do(&cld_closure); -+ // CLDToOopClosure cld_closure(oopClosure, ClassLoaderData::_claim_none); -+ // ClassLoaderDataGraph::cld_do(&cld_closure); - - // Now adjust pointers in remaining weak roots. (All of which should - // have been cleared if they pointed to non-surviving objects.) - // Global (weak) JNI handles - WeakProcessor::oops_do(oopClosure); - -+ JvmtiExport::oops_do(oopClosure); -+ - CodeBlobToOopClosure blobClosure(oopClosure, CodeBlobToOopClosure::FixRelocations); - CodeCache::blobs_do(&blobClosure); -+ - AOT_ONLY(AOTLoader::oops_do(oopClosure);) -+ - // StringTable::oops_do was removed in j15 - // StringTable::oops_do(oopClosure); - -- // PSScavenge::reference_processor()->weak_oops_do(oopClosure); -+ // OopStorageSet::vm_global()->oops_do(oopClosure); -+ - } - - void Universe::oops_do(OopClosure* f) { --- -2.23.0 - diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index 40647cc80a23..ba49f1421892 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -70,12 +70,6 @@ case "$bundle_type" in do_reset_changes=0 do_maketest=1 ;; - "dcevm") - HEAD_REVISION=$(git rev-parse HEAD) - git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=0 - do_reset_changes=0 - ;; "nomod" | "") bundle_type="" ;; @@ -111,7 +105,7 @@ if [ $? -eq 0 ]; then JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" fi -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $? update_jsdk_mods "$BOOT_JDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not unchanged @@ -126,7 +120,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index c152bf138a98..3f45b93c0593 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -68,12 +68,6 @@ case "$bundle_type" in do_reset_changes=0 do_maketest=1 ;; - "dcevm") - HEAD_REVISION=$(git rev-parse HEAD) - git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=0 - do_reset_changes=0 - ;; "nomod" | "") bundle_type="" ;; @@ -109,7 +103,7 @@ if [ $? -eq 0 ]; then JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" fi -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged @@ -124,7 +118,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? From 294e85ba0f9814f2c73a6b3dd9925b4f271019a5 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 2 Mar 2022 15:25:25 +0700 Subject: [PATCH 073/976] JBR-4272 generate and save debug symbols for JBR on macos/linux --- jb/project/docker/Dockerfile.aarch64 | 1 + jb/project/docker/Dockerfile.musl_aarch64 | 2 +- jb/project/docker/Dockerfile.musl_x64 | 2 +- jb/project/tools/common/scripts/common.sh | 12 ++++++++++++ jb/project/tools/linux/scripts/mkimages_aarch64.sh | 12 ++++-------- jb/project/tools/linux/scripts/mkimages_x64.sh | 2 ++ jb/project/tools/mac/scripts/mkimages.sh | 3 +++ 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/jb/project/docker/Dockerfile.aarch64 b/jb/project/docker/Dockerfile.aarch64 index 47e49de26ff8..645ab3bfe93a 100644 --- a/jb/project/docker/Dockerfile.aarch64 +++ b/jb/project/docker/Dockerfile.aarch64 @@ -31,6 +31,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \ libxt-dev \ libxtst-dev \ make \ + rsync \ tar \ unzip \ zip && \ diff --git a/jb/project/docker/Dockerfile.musl_aarch64 b/jb/project/docker/Dockerfile.musl_aarch64 index 108f63451ea9..0a803fe91a8d 100644 --- a/jb/project/docker/Dockerfile.musl_aarch64 +++ b/jb/project/docker/Dockerfile.musl_aarch64 @@ -8,7 +8,7 @@ FROM arm64v8/alpine:3.12 # Install the necessary build tools -RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \ +RUN apk --no-cache add --update bash grep tar zip bzip2 rsync fontconfig build-base \ git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \ libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \ fontconfig fontconfig-dev linux-headers diff --git a/jb/project/docker/Dockerfile.musl_x64 b/jb/project/docker/Dockerfile.musl_x64 index b8cea877d351..4c9523343950 100644 --- a/jb/project/docker/Dockerfile.musl_x64 +++ b/jb/project/docker/Dockerfile.musl_x64 @@ -8,7 +8,7 @@ FROM alpine:3.5 # Install the necessary build tools -RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \ +RUN apk --no-cache add --update bash grep tar zip bzip2 rsync fontconfig build-base \ git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \ libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \ fontconfig fontconfig-dev linux-headers diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index e634cc0d01b4..c8b9dafe866e 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -78,6 +78,8 @@ case "$OS_NAME" in ;; esac +WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS="--with-native-debug-symbols=zipped" + REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build --with-source-date=$SOURCE_DATE_EPOCH --with-hotspot-build-time=$BUILD_TIME @@ -85,6 +87,16 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build --disable-absolute-paths-in-output --with-build-user=builduser" +function zip_native_debug_symbols() { + image_bundle_path=$(echo $1 | cut -d"/" -f-4) + jbr_diz_name=$2 + + (cd $image_bundle_path && find . -name '*.diz' -exec rsync -R {} ../../../../dizfiles \; ) + + (cd dizfiles && find . -print0 | COPYFILE_DISABLE=1 \ + tar --no-recursion --null -T - -czf ../"$jbr_diz_name".tar.gz) || do_exit $? +} + function do_exit() { exit_code=$1 [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 4300e5ce80a7..7e48a8ad1b91 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -34,6 +34,7 @@ function do_configure { --enable-cds=yes \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ || do_exit $? } @@ -71,6 +72,7 @@ function create_image_bundle { mv release "$IMAGES_DIR"/"$__arch_name"/release cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" fi # jmod does not preserve file permissions (JDK-8173610) @@ -97,12 +99,6 @@ case "$bundle_type" in do_reset_changes=1 do_maketest=1 ;; - "dcevm") - HEAD_REVISION=$(git rev-parse HEAD) - git am jb/project/tools/patches/dcevm/*.patch || do_exit $? - do_reset_dcevm=0 - do_reset_changes=0 - ;; "nomod" | "") bundle_type="" ;; @@ -127,7 +123,7 @@ JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $? update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed @@ -141,7 +137,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || # create sdk image bundle modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? -if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) fi create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 36f12ace3a35..c1af65b88dca 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -34,6 +34,7 @@ function do_configure { --enable-cds=yes \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ || do_exit $? } @@ -71,6 +72,7 @@ function create_image_bundle { mv release "$IMAGES_DIR"/"$__arch_name"/release cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" fi # jmod does not preserve file permissions (JDK-8173610) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index aeff541dff30..6efc38a0af92 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -43,6 +43,7 @@ function do_configure { --with-extra-ldflags="-F$(pwd)/Frameworks" \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ || do_exit $? else sh configure \ @@ -59,6 +60,7 @@ function do_configure { --enable-cds=yes \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ || do_exit $? fi } @@ -89,6 +91,7 @@ function create_image_bundle { mv release $JRE_CONTENTS/Home/release cp $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home/lib/src.zip $JRE_CONTENTS/Home/lib copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods + zip_native_debug_symbols $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk "${JBR}_diz" fi cp -R "$JSDK"/../MacOS "$JRE_CONTENTS" From f24284a98aa915b8b11db548752148c3223ca7a8 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 20 May 2022 07:15:58 +0700 Subject: [PATCH 074/976] JBR-4458 enable JBR17 windows 32 bit builds --- .../tools/windows/scripts/mkimages_x64.sh | 2 +- .../tools/windows/scripts/mkimages_x86.sh | 145 ++++++++++++------ jb/project/tools/windows/scripts/pack_x86.sh | 62 ++++---- test/jdk/jb/build/check_for_artifacts.sh | 3 + 4 files changed, 135 insertions(+), 77 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 3f45b93c0593..299ab36bc82e 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -111,7 +111,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" fi -# create runtime image bundlef +# create runtime image bundle modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $? modules+=",jdk.crypto.mscapi" create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 97c7b51be1d2..2ec50d58db17 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -1,12 +1,11 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # # $ ./java --version # openjdk 11.0.6 2020-01-14 @@ -14,51 +13,105 @@ # OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) # -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') - source jb/project/tools/common/scripts/common.sh -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} WORK_DIR=$(pwd) -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - -PATH="/usr/local/bin:/usr/bin:${PATH}" -./configure \ - --with-target-bits=32 \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-version-pre= \ - --with-version-build=${JDK_BUILD_NUMBER} \ - --with-version-opt=b${build_number} \ - --with-toolchain-version=${TOOLCHAIN_VERSION} \ - --with-boot-jdk=${BOOT_JDK} \ - --disable-ccache \ - $STATIC_CONF_ARGS \ - --enable-cds=yes || exit 1 -make clean CONF=windows-x86-server-release || exit 1 -make LOG=info images CONF=windows-x86-server-release test-image || exit 1 - -JBSDK=${JBRSDK_BASE_NAME}-windows-x86-b${build_number} -BASE_DIR=build/windows-x86-server-release/images -JSDK=${BASE_DIR}/jdk +function do_configure { + sh ./configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build=$JDK_BUILD_NUMBER \ + --with-version-opt=b${build_number} \ + --with-toolchain-version=$TOOLCHAIN_VERSION \ + --with-boot-jdk=$BOOT_JDK \ + --disable-ccache \ + $STATIC_CONF_ARGS \ + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? +} + +function create_image_bundle { + __bundle_name=$1 + __arch_name=$2 + __modules_path=$3 + __modules=$4 + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + + echo Running jlink ... + ${JSDK}/bin/jlink \ + --module-path $__modules_path --no-man-pages --compress=2 \ + --add-modules $__modules --output $__arch_name || do_exit $? + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $__arch_name/release > release + mv release $__arch_name/release + cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib + copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods + fi +} + +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=windows-x86_64-server-release + +case "$bundle_type" in + "jcef") + echo "not implemented" && do_exit 1 + ;; + "nomod" | "") + bundle_type="" + ;; + "fd") + do_reset_changes=0 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=windows-x86_64-server-fastdebug + ;; +esac + +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + if [ $do_maketest -eq 1 ]; then + make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME clean images || do_exit $? + fi +else + if [ $do_maketest -eq 1 ]; then + make LOG=info CONF=$RELEASE_NAME images test-image || do_exit $? + else + make LOG=info CONF=$RELEASE_NAME images || do_exit $? + fi +fi + +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1 -sed 's/JBR/JBRSDK/g' ${JSDK}/release > release -mv release ${JBRSDK_BUNDLE}/release +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $? + update_jsdk_mods "$JSDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? + cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged + + jbr_name_postfix="_${bundle_type}" +fi + +# create runtime image bundle +modules=$(grep -v "jdk.internal.vm" jb/project/tools/common/modules.list | xargs | sed s/" "//g) || do_exit $? +modules+=",jdk.crypto.mscapi" +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? -JBR_BUNDLE=jbr -rm -rf ${JBR_BUNDLE} -grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 -echo ",jdk.crypto.mscapi" >> modules.list.x86 -${JSDK}/bin/jlink \ - --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $? +# create sdk image bundle +modules=$(cat ${JSDK}/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\r//g | sed s/\\n//g) +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then + modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods) +fi +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $? -echo Modifying release info ... -#grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release +do_exit 0 diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index 8ce91b09347e..9e780ab65962 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -1,42 +1,44 @@ #!/bin/bash -x # The following parameters must be specified: -# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6 -# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure -# build_number - specifies the number of JetBrainsRuntime build -# -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) +# build_number - specifies the number of JetBrainsRuntime build +# bundle_type - specifies bundle to be built;possible values: +# or nomod - the release bundles without any additional modules (jcef) +# fd - the fastdebug bundles which also include the jcef module # -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 +source jb/project/tools/common/scripts/common.sh -JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION -JBR_BASE_NAME=jbr-$JBSDK_VERSION +[ "$bundle_type" == "jcef" ] && echo "not implemented" && do_exit 1 -IMAGES_DIR=build/windows-x86-server-release/images -JSDK=$IMAGES_DIR/jdk -JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number -BASE_DIR=. +function pack_jbr { + __bundle_name=$1 + __arch_name=$2 + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} + + echo Creating $JBR.tar.gz ... + + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? +} + +[ "$bundle_type" == "nomod" ] && bundle_type="" JBRSDK_BUNDLE=jbrsdk -echo Creating $JBSDK.tar.gz ... -/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1 +RELEASE_NAME=windows-x86-server-release +IMAGES_DIR=build/$RELEASE_NAME/images +BASE_DIR=. -JBR_BUNDLE=jbr -JBR_BASE_NAME=jbr-${JBSDK_VERSION} +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then + jbr_name_postfix="_${bundle_type}" +fi -JBR=$JBR_BASE_NAME-windows-x86-b$build_number -echo Creating $JBR.tar.gz ... -/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR ${JBR_BUNDLE} || exit 1 +pack_jbr jbr${jbr_name_postfix} jbr +pack_jbr jbrsdk${jbr_name_postfix} jbrsdk -JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x86-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1 +if [ $do_maketest -eq 1 ]; then + JBRSDK_TEST=$JBRSDK_BUNDLE-$JBSDK_VERSION-windows-test-x86-b$build_number + echo Creating $JBRSDK_TEST.tar.gz ... + /usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $BASE_DIR --exclude='test/jdk/demos' test || do_exit $? +fi \ No newline at end of file diff --git a/test/jdk/jb/build/check_for_artifacts.sh b/test/jdk/jb/build/check_for_artifacts.sh index 7d6d7964ef90..a4bff61aa778 100755 --- a/test/jdk/jb/build/check_for_artifacts.sh +++ b/test/jdk/jb/build/check_for_artifacts.sh @@ -38,6 +38,7 @@ jbr-${jbsdk_version}-linux-x64-b${build_number}.tar.gz jbr-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz jbr-${jbsdk_version}-osx-x64-b${build_number}.tar.gz jbr-${jbsdk_version}-windows-x64-b${build_number}.tar.gz +jbr-${jbsdk_version}-windows-x86-b${build_number}.tar.gz jbr_fd-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz jbr_fd-${jbsdk_version}-linux-x64-b${build_number}.tar.gz @@ -65,6 +66,7 @@ jbrsdk-${jbsdk_version}-linux-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-windows-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-windows-x86-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-test-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-musl-test-aarch64-b${build_number}.tar.gz @@ -73,6 +75,7 @@ jbrsdk-${jbsdk_version}-linux-test-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-test-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-test-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-windows-test-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-windows-test-x86-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-aarch64-fastdebug-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-x64-fastdebug-b${build_number}.tar.gz From 6e338489ce0770da741f581d9bbb28da5a12de01 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 20 May 2022 07:17:31 +0700 Subject: [PATCH 075/976] JBR-4487 enable Linux 32 builds --- jb/project/docker/Dockerfile.x86 | 60 +++++- jb/project/docker/mkdocker_x86.sh | 26 +++ .../tools/linux/scripts/mkimages_x86.sh | 193 +++++++++++------- test/jdk/jb/build/check_for_artifacts.sh | 4 + 4 files changed, 208 insertions(+), 75 deletions(-) create mode 100755 jb/project/docker/mkdocker_x86.sh diff --git a/jb/project/docker/Dockerfile.x86 b/jb/project/docker/Dockerfile.x86 index 146da91e7983..d5111ac4dcd5 100644 --- a/jb/project/docker/Dockerfile.x86 +++ b/jb/project/docker/Dockerfile.x86 @@ -1,7 +1,55 @@ -FROM i386/ubuntu:xenial +# NOTE: This Dockerfile is meant to be used from the mkdocker_x86.sh script. -RUN linux32 apt-get update && apt-get install -y --no-install-recommends apt-utils -COPY jbrsdk-11.0.5-b1 /jbrsdk-11.0.5-b1 -RUN linux32 apt-get -y install file build-essential zip unzip curl libx11-dev libxext-dev \ - libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libasound2-data \ - libpng12-0 libasound2 libfreetype6 libfontconfig1-dev libasound2-dev autoconf +# Pull a concrete version of Linux that does NOT receive updates after it's +# been created. This is so that the image is as stable as possible to make +# image creation reproducible. +# NB: this also means there may be no security-related fixes there, need to +# move the version to the next manually. +#FROM i386/ubuntu:xenial +#FROM i386/ubuntu:bionic +FROM i386/ubuntu:focal + +RUN linux32 \ + apt-get update && apt-get install -y --no-install-recommends apt-utils +RUN export DEBIAN_FRONTEND=noninteractive \ + export DEBCONF_NONINTERACTIVE_SEEN=true && \ + echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \ + echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \ + linux32 \ + apt-get -y install \ + autoconf \ + build-essential \ + curl \ + file \ + git \ + libx11-dev \ + libxext-dev \ + libxrender-dev \ + libxrandr-dev \ + libxtst-dev \ + libxt-dev \ + libcups2-dev \ + libasound2-data \ +# libpng12-0 \ + libasound2 \ + libfreetype6 \ + libfontconfig1-dev \ + libasound2-dev \ + rsync \ + unzip \ + zip +RUN linux32 \ + apt-get -y install \ + g++-10 \ + gcc-10 && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 && \ + apt-get clean -qy && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Set up boot JDK for building +COPY boot_jdk_x86.tar.gz /jdk17/ +RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_x86.tar.gz && rm /jdk17/boot_jdk_x86.tar.gz +ENV BOOT_JDK=/jdk17 + +RUN git config --global user.email "teamcity@jetbrains.com" && \ + git config --global user.name "builduser" diff --git a/jb/project/docker/mkdocker_x86.sh b/jb/project/docker/mkdocker_x86.sh new file mode 100755 index 000000000000..57fdd550466b --- /dev/null +++ b/jb/project/docker/mkdocker_x86.sh @@ -0,0 +1,26 @@ +#!/bin/bash -x + +# This script creates a Docker image suitable for building x86 variant +# of the JetBrains Runtime version 17. + +BOOT_JDK_REMOTE_FILE=zulu17.34.19-ca-jdk17.0.3-linux_i686.tar.gz +BOOT_JDK_SHA=1c35c374ba0001e675d6e80819d5be900c4e141636d5e484992a8c550be14481 +BOOT_JDK_LOCAL_FILE=boot_jdk_x86.tar.gz + +if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then + # Obtain "boot JDK" from outside of the container. + wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE +else + echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download" +fi + +# Verify that what we've downloaded can be trusted. +sha256sum -c - < or nomod - the release bundles without any additional modules (jcef) +# jcef - the release bundles with jcef +# fd - the fastdebug bundles which also include the jcef module # -# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz -# -# $ ./java --version -# openjdk 11.0.6 2020-01-14 -# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}) -# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode) -# - -JBSDK_VERSION=$1 -JDK_BUILD_NUMBER=$2 -build_number=$3 - -JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g') source jb/project/tools/common/scripts/common.sh -JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION} - -[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?) - -linux32 bash configure \ - --with-debug-level=release \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-version-pre= \ - --with-version-build=$JDK_BUILD_NUMBER \ - --with-version-opt=b${build_number} \ - --with-boot-jdk=${BOOT_JDK} \ - $STATIC_CONF_ARGS \ - --enable-cds=yes || exit $? -make clean CONF=linux-x86-server-release || exit $? -make images CONF=linux-x86-server-release test-image || exit $? - -JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number} -BASE_DIR=build/linux-x86-server-release/images -JSDK=${BASE_DIR}/jdk +function do_configure { + linux32 bash configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + $STATIC_CONF_ARGS \ + --enable-cds=yes \ + $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ + || do_exit $? +} + +function is_musl { + libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1) + if [ -z $libc ]; then + # This is not Musl, return 1 == false + return 1 + fi + return 0 +} + +function create_image_bundle { + __bundle_name=$1 + __arch_name=$2 + __modules_path=$3 + __modules=$4 + + libc_type_suffix='' + + if is_musl; then libc_type_suffix='musl-' ; fi + + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix}b${build_number} + + echo Running jlink.... + [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + $JSDK/bin/jlink \ + --module-path "$__modules_path" --no-man-pages --compress=2 \ + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release + mv release "$IMAGES_DIR"/"$__arch_name"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" + fi + + # jmod does not preserve file permissions (JDK-8173610) + [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + + echo Creating "$JBR".tar.gz ... + + (cd "$IMAGES_DIR" && + find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + tar $REPRODUCIBLE_TAR_OPTS \ + --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? + mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar + [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" + touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar + gzip "$JBR".tar || do_exit $? + rm -rf "${IMAGES_DIR:?}"/"$__arch_name" +} + +WITH_DEBUG_LEVEL="--with-debug-level=release" +RELEASE_NAME=linux-x86-server-release + +case "$bundle_type" in + "jcef") + echo "not implemented" && do_exit 1 + ;; + "nomod" | "") + bundle_type="" + ;; + "fd") + do_reset_changes=1 + WITH_DEBUG_LEVEL="--with-debug-level=fastdebug" + RELEASE_NAME=linux-x86-server-fastdebug + ;; +esac + +if [ -z "$INC_BUILD" ]; then + do_configure || do_exit $? + make clean CONF=$RELEASE_NAME || do_exit $? +fi +make images CONF=$RELEASE_NAME || do_exit $? + +IMAGES_DIR=build/$RELEASE_NAME/images +JSDK=$IMAGES_DIR/jdk +JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk echo Fixing permissions chmod -R a+r $JSDK -rm -rf $BASE_DIR/$JBRSDK_BUNDLE -cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $? - -echo Creating $JBSDK.tar.gz ... -sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release -mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release - -tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $? -gzip $JBSDK.tar || exit $? - -JBR_BUNDLE=jbr -JBR_BASE_NAME=jbr-$JBSDK_VERSION -rm -rf $BASE_DIR/$JBR_BUNDLE - -JBR=$JBR_BASE_NAME-linux-x86-b$build_number -grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86 -echo Running jlink.... -${JSDK}/bin/jlink \ - --module-path ${JSDK}/jmods --no-man-pages --compress=2 \ - --add-modules $(xargs < modules.list.x86 | sed s/" "//g | sed s/,$//g) --output ${BASE_DIR}/${JBR_BUNDLE} || exit $? - -echo Modifying release info ... -grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release - -echo Creating $JBR.tar.gz ... -tar -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $? -gzip $JBR.tar || exit $? - -JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number -echo Creating $JBRSDK_TEST.tar.gz ... -tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $? -gzip $JBRSDK_TEST.tar || exit $? +if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then + jbr_name_postfix="_${bundle_type}" +fi + +# create runtime image bundle +modules=$(grep -v "jdk.internal.vm" jb/project/tools/common/modules.list | xargs | sed s/" "//g) || do_exit $? +create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $? + +# create sdk image bundle +modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $? +create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $? + +if [ $do_maketest -eq 1 ]; then + JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-x86-b${build_number} + echo Creating "$JBRSDK_TEST" ... + [ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java + make test-image CONF=$RELEASE_NAME || do_exit $? + tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $? + [ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz" + gzip "$JBRSDK_TEST".tar || do_exit $? +fi + +do_exit 0 diff --git a/test/jdk/jb/build/check_for_artifacts.sh b/test/jdk/jb/build/check_for_artifacts.sh index a4bff61aa778..1d201acc53c5 100755 --- a/test/jdk/jb/build/check_for_artifacts.sh +++ b/test/jdk/jb/build/check_for_artifacts.sh @@ -35,6 +35,7 @@ jbr-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz jbr-${jbsdk_version}-linux-musl-aarch64-b${build_number}.tar.gz jbr-${jbsdk_version}-linux-musl-x64-b${build_number}.tar.gz jbr-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbr-${jbsdk_version}-linux-x86-b${build_number}.tar.gz jbr-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz jbr-${jbsdk_version}-osx-x64-b${build_number}.tar.gz jbr-${jbsdk_version}-windows-x64-b${build_number}.tar.gz @@ -63,6 +64,7 @@ jbrsdk-${jbsdk_version}-linux-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-musl-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-musl-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-x86-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-windows-x64-b${build_number}.tar.gz @@ -72,6 +74,7 @@ jbrsdk-${jbsdk_version}-linux-test-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-musl-test-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-musl-test-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-linux-test-x64-b${build_number}.tar.gz +jbrsdk-${jbsdk_version}-linux-test-x86-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-test-aarch64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-osx-test-x64-b${build_number}.tar.gz jbrsdk-${jbsdk_version}-windows-test-x64-b${build_number}.tar.gz @@ -88,6 +91,7 @@ jbrsdk-${jbsdk_version}-linux-musl-aarch64-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-linux-musl-x64-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-linux-x64-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-linux-x64-fastdebug-b${build_number}_diz.tar.gz +jbrsdk-${jbsdk_version}-linux-x86-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-osx-aarch64-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-osx-aarch64-fastdebug-b${build_number}_diz.tar.gz jbrsdk-${jbsdk_version}-osx-x64-b${build_number}_diz.tar.gz From c8d174547f464a008fb11e048ed2434535ae47d3 Mon Sep 17 00:00:00 2001 From: Vladislav Rassokhin Date: Wed, 18 May 2022 02:24:51 +0700 Subject: [PATCH 076/976] JBR-4451 Make bash scripts safer --- jb/project/docker/mkdocker_aarch64.sh | 5 +- jb/project/docker/mkdocker_musl_aarch64.sh | 5 +- jb/project/docker/mkdocker_musl_x64.sh | 5 +- jb/project/tools/common/scripts/common.sh | 36 +++-- .../tools/linux/scripts/mkimages_aarch64.sh | 10 +- .../tools/linux/scripts/mkimages_x64.sh | 10 +- .../tools/linux/scripts/mkimages_x86.sh | 10 +- jb/project/tools/mac/scripts/mkimages.sh | 14 +- jb/project/tools/mac/scripts/notarize.sh | 5 +- jb/project/tools/mac/scripts/sign.sh | 5 +- jb/project/tools/mac/scripts/signapp.sh | 3 +- jb/project/tools/test/check_jbr_size.sh | 153 ++++++++++++++++++ jb/project/tools/test/perfcmp.sh | 5 +- .../tools/windows/scripts/mkimages_aarch64.sh | 11 +- .../tools/windows/scripts/mkimages_x64.sh | 11 +- .../tools/windows/scripts/mkimages_x86.sh | 13 +- .../tools/windows/scripts/pack_aarch64.sh | 9 +- jb/project/tools/windows/scripts/pack_x64.sh | 9 +- jb/project/tools/windows/scripts/pack_x86.sh | 9 +- 19 files changed, 288 insertions(+), 40 deletions(-) create mode 100644 jb/project/tools/test/check_jbr_size.sh diff --git a/jb/project/docker/mkdocker_aarch64.sh b/jb/project/docker/mkdocker_aarch64.sh index bcaeaa076f81..9299b27425de 100755 --- a/jb/project/docker/mkdocker_aarch64.sh +++ b/jb/project/docker/mkdocker_aarch64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # This script creates a Docker image suitable for building AArch64 variant # of the JetBrains Runtime "dev" version. diff --git a/jb/project/docker/mkdocker_musl_aarch64.sh b/jb/project/docker/mkdocker_musl_aarch64.sh index b0c292d2c762..9804f9be79a1 100755 --- a/jb/project/docker/mkdocker_musl_aarch64.sh +++ b/jb/project/docker/mkdocker_musl_aarch64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # This script creates a Docker image suitable for building musl AArch64 variant # of the JetBrains Runtime version 17. diff --git a/jb/project/docker/mkdocker_musl_x64.sh b/jb/project/docker/mkdocker_musl_x64.sh index 5bec8bbfbc97..0c6970e9380d 100755 --- a/jb/project/docker/mkdocker_musl_x64.sh +++ b/jb/project/docker/mkdocker_musl_x64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # This script creates a Docker image suitable for building musl-x64 variant # of the JetBrains Runtime version 17. diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index c8b9dafe866e..6bfc993b5920 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -1,12 +1,15 @@ -#!/bin/bash -x +#!/bin/bash -function do_maketest() { +set -euo pipefail +set -x + +function check_bundle_type_maketest() { + # check whether last char is 't', if so remove it if [ "${bundle_type: -1}" == "t" ]; then - echo ${bundle_type%?} - return 1 + bundle_type="${bundle_type%?}" + do_maketest=1 else - echo ${bundle_type} - return 0 + do_maketest=0 fi } @@ -16,20 +19,23 @@ function getVersionProp() { while getopts ":i?" o; do case "${o}" in - i) - i="incremental build" - INC_BUILD=1 - ;; + i) INC_BUILD=1 ;; esac done shift $((OPTIND-1)) +if [[ $# -lt 2 ]]; then + echo "Required at least two arguments: build_number bundle_type" + exit 1 +fi + build_number=$1 bundle_type=$2 -architecture=$3 # aarch64 or x64 +# shellcheck disable=SC2034 +architecture=${3:-x64} # aarch64 or x64 + +check_bundle_type_maketest -bundle_type=$(do_maketest) -do_maketest=$? tag_prefix="jdk-" OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | tr -d ',' | sort -t "-" -k 2 -g | tail -n 1) VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE") @@ -61,6 +67,10 @@ export TZ SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)" export SOURCE_DATE_EPOCH +COPYRIGHT_YEAR="" +BUILD_TIME="" +TOUCH_TIME="" +REPRODUCIBLE_TAR_OPTS="" case "$OS_NAME" in Linux) COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)" diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 7e48a8ad1b91..7bbd19daeded 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -54,6 +57,7 @@ function create_image_bundle { __modules=$4 libc_type_suffix='' + fastdebug_infix='' if is_musl; then libc_type_suffix='musl-' ; fi @@ -109,7 +113,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? make clean CONF=$RELEASE_NAME || do_exit $? fi @@ -129,6 +133,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index c1af65b88dca..e0fdaa7c18b2 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -54,6 +57,7 @@ function create_image_bundle { __modules=$4 libc_type_suffix='' + fastdebug_infix='' if is_musl; then libc_type_suffix='musl-' ; fi @@ -109,7 +113,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? make clean CONF=$RELEASE_NAME || do_exit $? fi @@ -130,6 +134,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" [ "$bundle_type" != "fd" ] && jbrsdk_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index b29860760c88..16b9786839c9 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -43,6 +46,7 @@ function create_image_bundle { __modules=$4 libc_type_suffix='' + fastdebug_infix='' if is_musl; then libc_type_suffix='musl-' ; fi @@ -97,7 +101,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? make clean CONF=$RELEASE_NAME || do_exit $? fi @@ -113,6 +117,8 @@ chmod -R a+r $JSDK if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 6efc38a0af92..f7270a85265a 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -20,7 +23,6 @@ source jb/project/tools/common/scripts/common.sh JCEF_PATH=${JCEF_PATH:=./jcef_mac} -architecture=${architecture:=x64} BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 17)} function do_configure { @@ -71,11 +73,13 @@ function create_image_bundle { __modules_path=$3 __modules=$4 + fastdebug_infix='' + tmp=.bundle.$$.tmp mkdir "$tmp" || do_exit $? [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" - JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix}b${build_number} + JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix:-}b${build_number} JRE_CONTENTS=$tmp/$__arch_name/Contents mkdir -p "$JRE_CONTENTS" || do_exit $? @@ -134,7 +138,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? make clean CONF=$RELEASE_NAME || do_exit $? fi @@ -152,6 +156,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/mac/scripts/notarize.sh b/jb/project/tools/mac/scripts/notarize.sh index 488205e85cf2..e5d7bfe963e0 100755 --- a/jb/project/tools/mac/scripts/notarize.sh +++ b/jb/project/tools/mac/scripts/notarize.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x APP_DIRECTORY=$1 APPL_USER=$2 diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index 59e1d104bd66..16c1394d1653 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x APPLICATION_PATH=$1 APP_NAME=$2 diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index 6f3a17b88b7d..f10393d01210 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -1,7 +1,8 @@ -#!/bin/bash -x +#!/bin/bash #immediately exit script with an error if a command fails set -euo pipefail +set -x export COPY_EXTENDED_ATTRIBUTES_DISABLE=true export COPYFILE_DISABLE=true diff --git a/jb/project/tools/test/check_jbr_size.sh b/jb/project/tools/test/check_jbr_size.sh new file mode 100644 index 000000000000..7fd25c677eb3 --- /dev/null +++ b/jb/project/tools/test/check_jbr_size.sh @@ -0,0 +1,153 @@ +#!/bin/bash + +set -euo pipefail + +while getopts ":t" o; do + case "${o}" in + t) + t="With Teamcity tests info" + TC_PRINT=1 + ;; + esac +done +shift $((OPTIND-1)) + +NEWFILEPATH=$1 +CONFIGID=$2 +BUILDID=$3 +TOKEN=$4 +# +# Get the size of new artifact +# + +unameOut="$(uname -s)" +case "${unameOut}" in + Linux*) + NEWFILESIZE=$(stat -c%s "$NEWFILEPATH") + ;; + Darwin*) + NEWFILESIZE=$(stat -f%z "$NEWFILEPATH") + ;; + CYGWIN*) + NEWFILESIZE=$(stat -c%s$4 +# +# Get the size of new artifact +# + "$NEWFILEPATH") + ;; + MINGW*) + NEWFILESIZE=$(stat -c%s "$NEWFILEPATH") + ;; + *) + echo "Unknown machine: ${unameOut}" + exit 1 +esac +FILENAME=$(basename ${NEWFILEPATH}) + +# +# Get pattern of artifact name +# Base filename pattern: ----b.tar.gz: jbr_dcevm-17.0.2-osx-x64-b1234.tar.gz +# BUNDLE_TYPE: jbr, jbrsdk, jbr_dcevm, jbrsdk_jcef etc. +# OS_ARCH_PATTERN - : osx-x64, linux-aarch64, windows-x64 etc. + +BUNDLE_TYPE=jbrsdk +OS_ARCH_PATTERN="" +FILE_EXTENSION=tar.gz + +re='(jbr[a-z_]*).*-[0-9_\.]+-(.+)-b[0-9]+(.+)' +if [[ $FILENAME =~ $re ]]; then + BUNDLE_TYPE=${BASH_REMATCH[1]} + OS_ARCH_PATTERN=${BASH_REMATCH[2]} + FILE_EXTENSION=${BASH_REMATCH[3]} +fi + +if [ $TC_PRINT -eq 1 ]; then + testname_file_ext=`echo $FILE_EXTENSION | sed 's/\./_/g'` + testname=$BUNDLE_TYPE"_"$OS_ARCH_PATTERN$testname_file_ext + echo \#\#teamcity[testStarted name=\'$testname\'] +fi + + +echo "BUNDLE_TYPE: " $BUNDLE_TYPE +echo "OS_ARCH_PATTERN: " $OS_ARCH_PATTERN +echo "FILE_EXTENSION: " $FILE_EXTENSION +echo "New size of $FILENAME = $NEWFILESIZE bytes." + + +function test_failed_msg() { + if [ $3 -eq 1 ]; then + echo \#\#teamcity[testFailed name=\'$1\' message=\'$2\'] + fi +} + +function test_finished_msg() { + if [ $2 -eq 1 ]; then + echo \#\#teamcity[testFinished name=\'$1\'] + fi +} + +# +# Get previous successful build ID +# Example: +# CONFIGID=IntellijCustomJdk_Jdk17_Master_LinuxX64jcef +# BUILDID=12345678 +# +# expected return value +# id="123".number="567" +# +CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/?locator=buildType:(id:$CONFIGID),status:success,count:1,finishDate:(build:$BUILDID,condition:before)") +re='id=\"([0-9]+)\".+number=\"([0-9\.]+)\"' + +# ID: Previous successful build id +ID=0 +if [[ $CURL_RESPONSE =~ $re ]]; then + ID=${BASH_REMATCH[1]} + echo "BUILD Number: ${BASH_REMATCH[2]}" +else + msg="ERROR: can't find previous build" + echo $msg + echo $CURL_RESPONSE + test_failed_msg $testname $msg $TC_PRINT + test_finished_msg $testname $TC_PRINT + exit 1 +fi + +# +# Get artifacts from previous successful build +# +# expected return value +# name="jbrsdk_jcef*.tar.gz size="123' +# +CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/$ID?fields=id,number,artifacts(file(name,size))") +echo "Atrifacts of previous build of $CONFIGID :" +echo $CURL_RESPONSE + +# Find binary size (in response) with reg exp +re='name=\"('$BUNDLE_TYPE'[^\"]+'${OS_ARCH_PATTERN}'[^\"]+'${FILE_EXTENSION}')\" size=\"([0-9]+)\"' + +if [[ $CURL_RESPONSE =~ $re ]]; then + OLDFILENAME=${BASH_REMATCH[1]} + echo "Prev artifact name: $OLDFILENAME" + OLDFILESIZE=${BASH_REMATCH[2]} + echo "Prev artifact size = $OLDFILESIZE" + + let allowedSize=OLDFILESIZE+OLDFILESIZE/20 # use 5% threshold + echo "Allowed size = $allowedSize" + if [[ "$NEWFILESIZE" -gt "$allowedSize" ]]; then + msg="ERROR: new size is significally greater than prev size (need to investigate)" + echo $msg + test_failed_msg $testname $msg $TC_PRINT + test_finished_msg $testname $TC_PRINT + exit 1 + else + echo "PASSED" + test_finished_msg $testname $TC_PRINT + fi +else + msg="ERROR: can't find string with size in xml response:" + echo $msg + echo $CURL_RESPONSE + test_failed_msg $testname $msg $TC_PRINT + test_finished_msg $testname $TC_PRINT + exit 1 +fi diff --git a/jb/project/tools/test/perfcmp.sh b/jb/project/tools/test/perfcmp.sh index 45d7d05baeeb..8e04daf300b0 100755 --- a/jb/project/tools/test/perfcmp.sh +++ b/jb/project/tools/test/perfcmp.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x usage () { diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index ba49f1421892..5e0d300e2b76 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -46,6 +49,8 @@ function create_image_bundle { __modules_path=$3 __modules=$4 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" echo Running jlink ... @@ -80,7 +85,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? if [ $do_maketest -eq 1 ]; then make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? @@ -111,6 +116,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not unchanged jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 299ab36bc82e..6340baeff2e7 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -44,6 +47,8 @@ function create_image_bundle { __modules_path=$3 __modules=$4 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" echo Running jlink ... @@ -78,7 +83,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? if [ $do_maketest -eq 1 ]; then make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? @@ -109,6 +114,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 2ec50d58db17..8d398c5da7a6 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -29,8 +32,8 @@ function do_configure { --with-toolchain-version=$TOOLCHAIN_VERSION \ --with-boot-jdk=$BOOT_JDK \ --disable-ccache \ - $STATIC_CONF_ARGS \ --enable-cds=yes \ + $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ || do_exit $? } @@ -41,6 +44,8 @@ function create_image_bundle { __modules_path=$3 __modules=$4 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" echo Running jlink ... @@ -74,7 +79,7 @@ case "$bundle_type" in ;; esac -if [ -z "$INC_BUILD" ]; then +if [ -z "${INC_BUILD:-}" ]; then do_configure || do_exit $? if [ $do_maketest -eq 1 ]; then make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $? @@ -100,6 +105,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then cp $JCEF_PATH/jmods/* ${JSDK_MODS_DIR} # $JSDK/jmods is not unchanged jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi # create runtime image bundle diff --git a/jb/project/tools/windows/scripts/pack_aarch64.sh b/jb/project/tools/windows/scripts/pack_aarch64.sh index 2732a87a704f..39bccd9f7f1d 100644 --- a/jb/project/tools/windows/scripts/pack_aarch64.sh +++ b/jb/project/tools/windows/scripts/pack_aarch64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -19,6 +22,8 @@ function pack_jbr { __bundle_name=$1 __arch_name=$2 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} @@ -36,6 +41,8 @@ BASE_DIR=. if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi pack_jbr jbr${jbr_name_postfix} jbr diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 2079b0e338cc..7027acb57be8 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -19,6 +22,8 @@ function pack_jbr { __bundle_name=$1 __arch_name=$2 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} @@ -36,6 +41,8 @@ BASE_DIR=. if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi pack_jbr jbr${jbr_name_postfix} jbr diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index 9e780ab65962..50185fc09ed9 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -1,4 +1,7 @@ -#!/bin/bash -x +#!/bin/bash + +set -euo pipefail +set -x # The following parameters must be specified: # build_number - specifies the number of JetBrainsRuntime build @@ -15,6 +18,8 @@ function pack_jbr { __bundle_name=$1 __arch_name=$2 + fastdebug_infix='' + [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} @@ -32,6 +37,8 @@ BASE_DIR=. if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then jbr_name_postfix="_${bundle_type}" +else + jbr_name_postfix="" fi pack_jbr jbr${jbr_name_postfix} jbr From 8181144eed1d502b0e8570a6543af019f50d4b78 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Wed, 2 Feb 2022 10:15:26 +0300 Subject: [PATCH 077/976] JBR-4064 Windows: update build scripts to produce more deterministic output Passed the configure script options necessary to enable reproducible builds on Windows. With this options, the resulting jars are reproducible, but native executables and libraries aren't. --- jb/project/tools/common/scripts/common.sh | 8 +++++--- jb/project/tools/windows/scripts/mkimages_aarch64.sh | 1 + jb/project/tools/windows/scripts/mkimages_x64.sh | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 6bfc993b5920..803167b43907 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -77,15 +77,17 @@ case "$OS_NAME" in BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)" REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" ;; + CYGWIN*) + COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)" + BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)" + REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" + ;; Darwin) COPYRIGHT_YEAR="$(date -u -r $SOURCE_DATE_EPOCH +%Y)" BUILD_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%F)" TOUCH_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%Y%m%d%H%M.%S)" REPRODUCIBLE_TAR_OPTS="--uid 0 --gid 0 --numeric-owner" ;; - *) - # TODO: Windows - ;; esac WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS="--with-native-debug-symbols=zipped" diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index 5e0d300e2b76..f245c89af46a 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -40,6 +40,7 @@ function do_configure { --with-build-jdk=$BOOT_JDK \ --disable-ccache \ $STATIC_CONF_ARGS \ + $REPRODUCIBLE_BUILD_OPTS \ --enable-cds=yes || do_exit $? } diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 6340baeff2e7..0ad7ca75daf7 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -37,8 +37,10 @@ function do_configure { --with-toolchain-version=$TOOLCHAIN_VERSION \ --with-boot-jdk=$BOOT_JDK \ --disable-ccache \ + --enable-cds=yes \ $STATIC_CONF_ARGS \ - --enable-cds=yes || do_exit $? + $REPRODUCIBLE_BUILD_OPTS \ + || do_exit $? } function create_image_bundle { From 6536d96ce5e0626d8cfd6e702b208dd82c7a806a Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 27 May 2022 05:42:38 +0700 Subject: [PATCH 078/976] JBR-4511 remove --disable options from configure mac-aarch64 builds & unify configure for x64 and aarch64 --- jb/project/tools/mac/scripts/mkimages.sh | 55 +++++++----------------- 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index f7270a85265a..e4708cbbfbe8 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -26,45 +26,22 @@ JCEF_PATH=${JCEF_PATH:=./jcef_mac} BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 17)} function do_configure { - if [[ "${architecture}" == *aarch64* ]]; then - sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="${VENDOR_NAME}" \ - --with-vendor-version-string="${VENDOR_VERSION_STRING}" \ - --with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \ - --with-macosx-bundle-id-base="com.jetbrains.jbr" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="${JDK_BUILD_NUMBER}" \ - --with-version-opt=b"${build_number}" \ - --with-boot-jdk="$BOOT_JDK" \ - --disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \ - --enable-cds=no \ - --with-extra-cflags="-F$(pwd)/Frameworks" \ - --with-extra-cxxflags="-F$(pwd)/Frameworks" \ - --with-extra-ldflags="-F$(pwd)/Frameworks" \ - $STATIC_CONF_ARGS \ - $REPRODUCIBLE_BUILD_OPTS \ - $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ - || do_exit $? - else - sh configure \ - $WITH_DEBUG_LEVEL \ - --with-vendor-name="$VENDOR_NAME" \ - --with-vendor-version-string="$VENDOR_VERSION_STRING" \ - --with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \ - --with-macosx-bundle-id-base="com.jetbrains.jbr" \ - --with-jvm-features=shenandoahgc \ - --with-version-pre= \ - --with-version-build="$JDK_BUILD_NUMBER" \ - --with-version-opt=b"$build_number" \ - --with-boot-jdk="$BOOT_JDK" \ - --enable-cds=yes \ - $STATIC_CONF_ARGS \ - $REPRODUCIBLE_BUILD_OPTS \ - $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ - || do_exit $? - fi + sh configure \ + $WITH_DEBUG_LEVEL \ + --with-vendor-name="$VENDOR_NAME" \ + --with-vendor-version-string="$VENDOR_VERSION_STRING" \ + --with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \ + --with-macosx-bundle-id-base="com.jetbrains.jbr" \ + --with-jvm-features=shenandoahgc \ + --with-version-pre= \ + --with-version-build="$JDK_BUILD_NUMBER" \ + --with-version-opt=b"$build_number" \ + --with-boot-jdk="$BOOT_JDK" \ + --enable-cds=yes \ + $STATIC_CONF_ARGS \ + $REPRODUCIBLE_BUILD_OPTS \ + $WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \ + || do_exit $? } function create_image_bundle { From ce2bcb4b7ec615a00f5f98a6d35892425a80edb9 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 27 May 2022 15:19:26 +0700 Subject: [PATCH 079/976] JBR-4087 add version info into the name of root directory in JBR tar.gz-distributions --- .../tools/linux/scripts/mkimages_aarch64.sh | 22 ++++++++++--------- .../tools/linux/scripts/mkimages_x64.sh | 21 +++++++++--------- .../tools/linux/scripts/mkimages_x86.sh | 21 +++++++++--------- jb/project/tools/mac/scripts/mkimages.sh | 7 +++--- jb/project/tools/mac/scripts/sign.sh | 7 ++++-- jb/project/tools/mac/scripts/signapp.sh | 3 +-- .../tools/windows/scripts/mkimages_aarch64.sh | 11 +++++----- .../tools/windows/scripts/mkimages_x64.sh | 17 +++++++------- .../tools/windows/scripts/mkimages_x86.sh | 13 ++++++----- .../tools/windows/scripts/pack_aarch64.sh | 3 ++- jb/project/tools/windows/scripts/pack_x64.sh | 3 ++- jb/project/tools/windows/scripts/pack_x86.sh | 5 ++--- 12 files changed, 72 insertions(+), 61 deletions(-) diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 7bbd19daeded..2d83704c0ac8 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -63,36 +63,38 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}aarch64-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-${libc_type_suffix}aarch64-${fastdebug_infix:-}b${build_number%%.*} + echo Running jlink.... - [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + [ -d "$IMAGES_DIR"/"$__root_dir" ] && rm -rf "${IMAGES_DIR:?}"/"$__root_dir" $JSDK/bin/jlink \ --module-path "$__modules_path" --no-man-pages --compress=2 \ - --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__root_dir" - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__root_dir"/release if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release - mv release "$IMAGES_DIR"/"$__arch_name"/release - cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib - copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release + mv release "$IMAGES_DIR"/"$__root_dir"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" fi # jmod does not preserve file permissions (JDK-8173610) - [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + [ -f "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper echo Creating "$JBR".tar.gz ... (cd "$IMAGES_DIR" && - find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + find "$__root_dir" -print0 | LC_ALL=C sort -z | \ tar $REPRODUCIBLE_TAR_OPTS \ --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar gzip "$JBR".tar || do_exit $? - rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + rm -rf "${IMAGES_DIR:?}"/"$__root_dir" } WITH_DEBUG_LEVEL="--with-debug-level=release" diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index e0fdaa7c18b2..9e3b9da1fcd9 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -63,36 +63,37 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink.... - [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + [ -d "$IMAGES_DIR"/"$__root_dir" ] && rm -rf "${IMAGES_DIR:?}"/"$__root_dir" $JSDK/bin/jlink \ --module-path "$__modules_path" --no-man-pages --compress=2 \ - --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__root_dir" - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__root_dir"/release if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release - mv release "$IMAGES_DIR"/"$__arch_name"/release - cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib - copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release + mv release "$IMAGES_DIR"/"$__root_dir"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" fi # jmod does not preserve file permissions (JDK-8173610) - [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + [ -f "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper echo Creating "$JBR".tar.gz ... (cd "$IMAGES_DIR" && - find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + find "$__root_dir" -print0 | LC_ALL=C sort -z | \ tar $REPRODUCIBLE_TAR_OPTS \ --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar gzip "$JBR".tar || do_exit $? - rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + rm -rf "${IMAGES_DIR:?}"/"$__root_dir" } WITH_DEBUG_LEVEL="--with-debug-level=release" diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index 16b9786839c9..aae9a2cff70d 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -52,36 +52,37 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-${libc_type_suffix}x86-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink.... - [ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + [ -d "$IMAGES_DIR"/"$__root_dir" ] && rm -rf "${IMAGES_DIR:?}"/"$__root_dir" $JSDK/bin/jlink \ --module-path "$__modules_path" --no-man-pages --compress=2 \ - --add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name" + --add-modules "$__modules" --output "$IMAGES_DIR"/"$__root_dir" - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__root_dir"/release if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release - mv release "$IMAGES_DIR"/"$__arch_name"/release - cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__arch_name"/lib - copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods + sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release + mv release "$IMAGES_DIR"/"$__root_dir"/release + cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib + copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz" fi # jmod does not preserve file permissions (JDK-8173610) - [ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper + [ -f "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper echo Creating "$JBR".tar.gz ... (cd "$IMAGES_DIR" && - find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + find "$__root_dir" -print0 | LC_ALL=C sort -z | \ tar $REPRODUCIBLE_TAR_OPTS \ --no-recursion --null -T - -cf "$JBR".tar) || do_exit $? mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar [ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz" touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar gzip "$JBR".tar || do_exit $? - rm -rf "${IMAGES_DIR:?}"/"$__arch_name" + rm -rf "${IMAGES_DIR:?}"/"$__root_dir" } WITH_DEBUG_LEVEL="--with-debug-level=release" diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index e4708cbbfbe8..5d20d3d589fb 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -57,8 +57,9 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix:-}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-${architecture}-${fastdebug_infix:-}b${build_number%%.*} - JRE_CONTENTS=$tmp/$__arch_name/Contents + JRE_CONTENTS=$tmp/$__root_dir/Contents mkdir -p "$JRE_CONTENTS" || do_exit $? echo Running jlink... @@ -82,10 +83,10 @@ function create_image_bundle { echo Creating "$JBR".tar.gz ... # Normalize timestamp - find "$tmp"/"$__arch_name" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME" + find "$tmp"/"$__root_dir" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME" (cd "$tmp" && - find "$__arch_name" -print0 | LC_ALL=C sort -z | \ + find "$__root_dir" -print0 | LC_ALL=C sort -z | \ COPYFILE_DISABLE=1 tar $REPRODUCIBLE_TAR_OPTS --no-recursion --null -T - \ -czf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man') || do_exit $? mv "$tmp"/"$JBR".tar.gz "$JBR".tar.gz diff --git a/jb/project/tools/mac/scripts/sign.sh b/jb/project/tools/mac/scripts/sign.sh index 16c1394d1653..e9fd95def3a6 100755 --- a/jb/project/tools/mac/scripts/sign.sh +++ b/jb/project/tools/mac/scripts/sign.sh @@ -100,8 +100,11 @@ BUILD_NAME=$(echo $APPLICATION_PATH | awk -F"/" '{ print $2 }') log "Creating $APP_NAME.pkg..." rm -rf "$APP_NAME.pkg" -pkgbuild --identifier $BUNDLE_ID --sign "$JB_INSTALLER_CERT" --root $APPLICATION_PATH \ - --install-location /Library/Java/JavaVirtualMachines/${BUILD_NAME} ${APP_NAME}.pkg + +mkdir -p unsigned +pkgbuild --identifier $BUNDLE_ID --root $APPLICATION_PATH \ + --install-location /Library/Java/JavaVirtualMachines/${BUILD_NAME} unsigned/${APP_NAME}.pkg +productsign --timestamp --sign "$JB_INSTALLER_CERT" unsigned/${APP_NAME}.pkg ${APP_NAME}.pkg #log "Signing whole app..." #codesign --timestamp \ diff --git a/jb/project/tools/mac/scripts/signapp.sh b/jb/project/tools/mac/scripts/signapp.sh index f10393d01210..8b820103d2f1 100755 --- a/jb/project/tools/mac/scripts/signapp.sh +++ b/jb/project/tools/mac/scripts/signapp.sh @@ -45,8 +45,7 @@ fi log "$INPUT_FILE extracted and removed" APP_NAME=$(echo ${INPUT_FILE} | awk -F".tar" '{ print $1 }') -APPLICATION_PATH=$(sed "s/osx-//" <<< "$EXPLODED/$APP_NAME") -mv $EXPLODED/$BUILD_NAME $APPLICATION_PATH +APPLICATION_PATH=$EXPLODED/$(ls $EXPLODED) find "$APPLICATION_PATH/Contents/Home/bin" \ -maxdepth 1 -type f -name '*.jnilib' -print0 | diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index f245c89af46a..c551bbdc2ed3 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -53,18 +53,19 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink ... ${BOOT_JDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ - --add-modules $__modules --output $__arch_name || do_exit $? + --add-modules $__modules --output $__root_dir || do_exit $? grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' $__arch_name/release > release - mv release $__arch_name/release - cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib - copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods + sed 's/JBR/JBRSDK/g' $__root_dir/release > release + mv release $__root_dir/release + cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index 0ad7ca75daf7..c3c4b1d1c624 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -52,18 +52,19 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink ... ${JSDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ - --add-modules $__modules --output $__arch_name || do_exit $? - - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release - if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' $__arch_name/release > release - mv release $__arch_name/release - cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib - copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods + --add-modules $__modules --output $__root_dir || do_exit $? + + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__root_dir/release + if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then + sed 's/JBR/JBRSDK/g' $__root_dir/release > release + mv release $__root_dir/release + cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 8d398c5da7a6..3f88f26d21f5 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -47,18 +47,19 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x86-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink ... ${JSDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ - --add-modules $__modules --output $__arch_name || do_exit $? + --add-modules $__modules --output $__root_dir || do_exit $? - grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__arch_name/release + grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> $__root_dir/release if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then - sed 's/JBR/JBRSDK/g' $__arch_name/release > release - mv release $__arch_name/release - cp $IMAGES_DIR/jdk/lib/src.zip $__arch_name/lib - copy_jmods "$__modules" "$__modules_path" "$__arch_name"/jmods + sed 's/JBR/JBRSDK/g' $__root_dir/release > release + mv release $__root_dir/release + cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } diff --git a/jb/project/tools/windows/scripts/pack_aarch64.sh b/jb/project/tools/windows/scripts/pack_aarch64.sh index 39bccd9f7f1d..717c14390638 100644 --- a/jb/project/tools/windows/scripts/pack_aarch64.sh +++ b/jb/project/tools/windows/scripts/pack_aarch64.sh @@ -26,10 +26,11 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-aarch64-${fastdebug_infix:-}b${build_number%%.*} echo Creating $JBR.tar.gz ... - /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__root_dir || do_exit $? } [ "$bundle_type" == "nomod" ] && bundle_type="" diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 7027acb57be8..6184513409e5 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -26,10 +26,11 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} echo Creating $JBR.tar.gz ... - /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__root_dir || do_exit $? } [ "$bundle_type" == "nomod" ] && bundle_type="" diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index 50185fc09ed9..6fa5461dcadc 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -22,17 +22,16 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-x86-${fastdebug_infix:-}b${build_number%%.*} echo Creating $JBR.tar.gz ... - /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__arch_name || do_exit $? + /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__root_dir || do_exit $? } [ "$bundle_type" == "nomod" ] && bundle_type="" JBRSDK_BUNDLE=jbrsdk -RELEASE_NAME=windows-x86-server-release -IMAGES_DIR=build/$RELEASE_NAME/images BASE_DIR=. if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "dcevm" ] || [ "$bundle_type" == "fd" ]; then From 073c4557c2c8b8ae0946d52d9ded8bec3d4ed955 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 27 May 2022 15:38:17 +0700 Subject: [PATCH 080/976] JBR-4512 windows: include pdb-files into jbrsdk --- jb/project/tools/windows/scripts/mkimages_aarch64.sh | 4 +++- jb/project/tools/windows/scripts/mkimages_x64.sh | 4 +++- jb/project/tools/windows/scripts/mkimages_x86.sh | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index c551bbdc2ed3..eb77eaeb62bb 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -64,7 +64,9 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $__root_dir/release > release mv release $__root_dir/release - cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + for dir in $(ls -d $IMAGES_DIR/jdk/*); do + rsync -a --exclude demo --exclude sample $dir $__root_dir + done copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index c3c4b1d1c624..e340621119e5 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -63,7 +63,9 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $__root_dir/release > release mv release $__root_dir/release - cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + for dir in $(ls -d $IMAGES_DIR/jdk/*); do + rsync -a --exclude demo --exclude sample $dir $__root_dir + done copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 3f88f26d21f5..922b2577d2a2 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -58,7 +58,9 @@ function create_image_bundle { if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then sed 's/JBR/JBRSDK/g' $__root_dir/release > release mv release $__root_dir/release - cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib + for dir in $(ls -d $IMAGES_DIR/jdk/*); do + rsync -a --exclude demo --exclude sample $dir $__root_dir + done copy_jmods "$__modules" "$__modules_path" "$__root_dir"/jmods fi } From 2a6b63e78175e8c3c7f80276104302f8ee0515a7 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Sun, 29 May 2022 13:23:46 +0700 Subject: [PATCH 081/976] JBR-4520 set file permissions after signing --- jb/project/tools/windows/scripts/pack_x64.sh | 2 +- jb/project/tools/windows/scripts/pack_x86.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 6184513409e5..50ae73078041 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -29,7 +29,7 @@ function pack_jbr { __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} echo Creating $JBR.tar.gz ... - + chmod -R ug+rwx,o+rx ${BASE_DIR}/$__root_dir /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__root_dir || do_exit $? } diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index 6fa5461dcadc..4816c2e363fd 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -25,7 +25,7 @@ function pack_jbr { __root_dir=${__bundle_name}-${JBSDK_VERSION}-x86-${fastdebug_infix:-}b${build_number%%.*} echo Creating $JBR.tar.gz ... - + chmod -R ug+rwx,o+rx ${BASE_DIR}/$__root_dir /usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR $__root_dir || do_exit $? } From 3c00b0fe8ee047f368b2edbaebee36bef51104d8 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Mon, 13 Jun 2022 06:11:58 +0700 Subject: [PATCH 082/976] JBR-4567 replace comma with point in RenderPerf scores --- jb/project/tools/test/perfcmp.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/jb/project/tools/test/perfcmp.sh b/jb/project/tools/test/perfcmp.sh index 8e04daf300b0..f8c0970c6b3e 100755 --- a/jb/project/tools/test/perfcmp.sh +++ b/jb/project/tools/test/perfcmp.sh @@ -60,7 +60,13 @@ else testContent=`paste -d '\t' $refFile <(echo "$curValues") | tail -n +1` fi -testContent=`echo "$testContent" | awk -F'\t' '{ if ($3>$2+$2*0.1) {print "* "$1"\t"$2"\t"$3"\t"(($2==0)?"-":$3/$2)} else {print " "$1"\t"$2"\t"$3"\t"(($2==0)?"-":$3/$2)} }'` +testContent=`echo "$testContent" | tr "," "." | awk -F'\t' '{ + if ($3>$2+$2*0.1) { + print "* "$1"\t"$2"\t"$3"\t"(($2>0)?$3/$2:"-") + } else { + print " "$1"\t"$2"\t"$3"\t"(($2>0)?$3/$2:"-") + } +}'` if [ -z $noHeaders ]; then echo "$header" > $resFile fi @@ -71,11 +77,12 @@ if [ -z $tc ]; then exit 0 fi +failed=0 echo "$testContent" 2>&1 | ( while read -r s; do testname=`echo "$s" | cut -f 1 | tr -d "[:space:]" | tr -d "*"` duration=`echo "$s" | cut -f 3` - failed=`echo "$s" | cut -c1 | grep -c "*"` + echo "$s" | cut -c1 | grep -c "*" && failed=1 echo \#\#teamcity[testStarted name=\'$testNamePrefix$testname\'] echo "===>$s" echo \#\#teamcity[buildStatisticValue key=\'$testNamePrefix$testname\' value=\'$duration\'] From 922772c88665e9a4645694eadb9f608a543ed0f0 Mon Sep 17 00:00:00 2001 From: Nikita Provotorov Date: Wed, 15 Jun 2022 04:03:21 +0700 Subject: [PATCH 083/976] JBR-2074 Windows 10 AArch64 support: build fixes. --- jb/project/tools/common/scripts/common.sh | 2 +- jb/project/tools/windows/scripts/mkimages_aarch64.sh | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 803167b43907..e8df1f704c33 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -140,7 +140,7 @@ function update_jsdk_mods() { # re-create java.base.jmod with updated hashes tmp=.java.base.$$.tmp mkdir "$tmp" || exit $? - hash_modules=$("$JSDK"/bin/jmod describe "$__orig_jsdk_mods"/java.base.jmod | grep hashes | awk '{print $2}' | tr '\n' '|' | sed s/\|$//) || exit $? + hash_modules=$("$__jsdk"/bin/jmod describe "$__orig_jsdk_mods"/java.base.jmod | grep hashes | awk '{print $2}' | tr '\n' '|' | sed s/\|$//) || exit $? "$__jsdk"/bin/jmod extract --dir "$tmp" "$__orig_jsdk_mods"/java.base.jmod || exit $? rm "$__updated_jsdk_mods"/java.base.jmod || exit $? # temp exclude from path "$__jsdk"/bin/jmod \ diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index eb77eaeb62bb..f0d402afff44 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -37,7 +37,6 @@ function do_configure { --with-version-opt=b${build_number} \ --with-toolchain-version=$TOOLCHAIN_VERSION \ --with-boot-jdk=$BOOT_JDK \ - --with-build-jdk=$BOOT_JDK \ --disable-ccache \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ @@ -53,10 +52,10 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-aarch64-${fastdebug_infix:-}b${build_number%%.*} echo Running jlink ... - ${BOOT_JDK}/bin/jlink \ + ${BUILD_JDK}/bin/jlink \ --module-path $__modules_path --no-man-pages --compress=2 \ --add-modules $__modules --output $__root_dir || do_exit $? @@ -109,6 +108,8 @@ JSDK=$IMAGES_DIR/jdk JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk +BUILD_JDK=build/$RELEASE_NAME/buildjdk/jdk + where cygpath if [ $? -eq 0 ]; then JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" @@ -116,7 +117,7 @@ fi if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $? - update_jsdk_mods "$BOOT_JDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? + update_jsdk_mods "$BUILD_JDK" "$JCEF_PATH"/jmods "$JSDK"/jmods "$JSDK_MODS_DIR" || do_exit $? cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not unchanged jbr_name_postfix="_${bundle_type}" From c3a15711c4e9914183142b47a318dfc8d7caae9b Mon Sep 17 00:00:00 2001 From: Nikita Provotorov Date: Wed, 15 Jun 2022 12:52:00 +0700 Subject: [PATCH 084/976] JBR-2074 Windows 10 AArch64 support: make the build scripts use custom build-jdk. --- jb/project/tools/windows/scripts/mkimages_aarch64.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index f0d402afff44..c70be45841a6 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -20,6 +20,12 @@ set -x # JCEF_PATH - specifies the path to the directory with JCEF binaries. # By default JCEF binaries should be located in ./jcef_win_aarch64 +if [ -z "$BUILD_JDK" ]; then + echo "BUILD_JDK environment variable must be specified and point to a JDK built from the current sources" \ + " and is able to run on the build system. See OpenJDK documentation for --with-build-jdk for more info." + exit 1 +fi + source jb/project/tools/common/scripts/common.sh WORK_DIR=$(pwd) @@ -37,6 +43,7 @@ function do_configure { --with-version-opt=b${build_number} \ --with-toolchain-version=$TOOLCHAIN_VERSION \ --with-boot-jdk=$BOOT_JDK \ + --with-build-jdk=$BUILD_JDK \ --disable-ccache \ $STATIC_CONF_ARGS \ $REPRODUCIBLE_BUILD_OPTS \ @@ -108,8 +115,6 @@ JSDK=$IMAGES_DIR/jdk JSDK_MODS_DIR=$IMAGES_DIR/jmods JBRSDK_BUNDLE=jbrsdk -BUILD_JDK=build/$RELEASE_NAME/buildjdk/jdk - where cygpath if [ $? -eq 0 ]; then JCEF_PATH="$(cygpath -w $JCEF_PATH | sed 's/\\/\//g')" From 23a64a4d82c32cc1fbc793c37a0d4a9e136f46b9 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 23 Aug 2022 08:52:23 +0700 Subject: [PATCH 085/976] JBR-4754 make root directory with the same name as archive name --- jb/project/tools/common/scripts/common.sh | 11 +++++++++-- jb/project/tools/linux/scripts/mkimages_aarch64.sh | 2 +- jb/project/tools/linux/scripts/mkimages_x64.sh | 2 +- jb/project/tools/linux/scripts/mkimages_x86.sh | 2 +- jb/project/tools/mac/scripts/mkimages.sh | 2 +- jb/project/tools/windows/scripts/mkimages_aarch64.sh | 2 +- jb/project/tools/windows/scripts/mkimages_x64.sh | 2 +- jb/project/tools/windows/scripts/mkimages_x86.sh | 2 +- jb/project/tools/windows/scripts/pack_aarch64.sh | 2 +- jb/project/tools/windows/scripts/pack_x64.sh | 2 +- jb/project/tools/windows/scripts/pack_x86.sh | 2 +- 11 files changed, 19 insertions(+), 12 deletions(-) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index e8df1f704c33..841a1d9adc61 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -101,11 +101,18 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build function zip_native_debug_symbols() { image_bundle_path=$(echo $1 | cut -d"/" -f-4) + jdk_name=$(echo $1 | cut -d"/" -f5) jbr_diz_name=$2 - (cd $image_bundle_path && find . -name '*.diz' -exec rsync -R {} ../../../../dizfiles \; ) + [ -d "dizfiles" ] && rm -rf dizfiles + mkdir dizfiles - (cd dizfiles && find . -print0 | COPYFILE_DISABLE=1 \ + rsync_target="../../../../dizfiles" + [ -z "$jdk_name" ] && rsync_target=$rsync_target"/"$jbr_diz_name + (cd $image_bundle_path && find . -name '*.diz' -exec rsync -R {} $rsync_target \;) + [ ! -z "$jdk_name" ] && mv dizfiles/$jdk_name dizfiles/$jbr_diz_name + + (cd dizfiles && find $jbr_diz_name -print0 | COPYFILE_DISABLE=1 \ tar --no-recursion --null -T - -czf ../"$jbr_diz_name".tar.gz) || do_exit $? } diff --git a/jb/project/tools/linux/scripts/mkimages_aarch64.sh b/jb/project/tools/linux/scripts/mkimages_aarch64.sh index 2d83704c0ac8..ba647a5c3a7a 100755 --- a/jb/project/tools/linux/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/linux/scripts/mkimages_aarch64.sh @@ -63,7 +63,7 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}aarch64-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-${libc_type_suffix}aarch64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}aarch64-${fastdebug_infix:-}b${build_number} echo Running jlink.... diff --git a/jb/project/tools/linux/scripts/mkimages_x64.sh b/jb/project/tools/linux/scripts/mkimages_x64.sh index 9e3b9da1fcd9..bed2b50e1ccd 100755 --- a/jb/project/tools/linux/scripts/mkimages_x64.sh +++ b/jb/project/tools/linux/scripts/mkimages_x64.sh @@ -63,7 +63,7 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix:-}b${build_number} echo Running jlink.... [ -d "$IMAGES_DIR"/"$__root_dir" ] && rm -rf "${IMAGES_DIR:?}"/"$__root_dir" diff --git a/jb/project/tools/linux/scripts/mkimages_x86.sh b/jb/project/tools/linux/scripts/mkimages_x86.sh index aae9a2cff70d..e7de577a8b9f 100755 --- a/jb/project/tools/linux/scripts/mkimages_x86.sh +++ b/jb/project/tools/linux/scripts/mkimages_x86.sh @@ -52,7 +52,7 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-${libc_type_suffix}x86-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix:-}b${build_number} echo Running jlink.... [ -d "$IMAGES_DIR"/"$__root_dir" ] && rm -rf "${IMAGES_DIR:?}"/"$__root_dir" diff --git a/jb/project/tools/mac/scripts/mkimages.sh b/jb/project/tools/mac/scripts/mkimages.sh index 5d20d3d589fb..b506ad8424d1 100755 --- a/jb/project/tools/mac/scripts/mkimages.sh +++ b/jb/project/tools/mac/scripts/mkimages.sh @@ -57,7 +57,7 @@ function create_image_bundle { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix:-}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-${architecture}-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-osx-${architecture}-${fastdebug_infix:-}b${build_number} JRE_CONTENTS=$tmp/$__root_dir/Contents mkdir -p "$JRE_CONTENTS" || do_exit $? diff --git a/jb/project/tools/windows/scripts/mkimages_aarch64.sh b/jb/project/tools/windows/scripts/mkimages_aarch64.sh index c70be45841a6..889ad88a052d 100644 --- a/jb/project/tools/windows/scripts/mkimages_aarch64.sh +++ b/jb/project/tools/windows/scripts/mkimages_aarch64.sh @@ -59,7 +59,7 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" - __root_dir=${__bundle_name}-${JBSDK_VERSION}-aarch64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} echo Running jlink ... ${BUILD_JDK}/bin/jlink \ diff --git a/jb/project/tools/windows/scripts/mkimages_x64.sh b/jb/project/tools/windows/scripts/mkimages_x64.sh index e340621119e5..657aa04d5f2a 100755 --- a/jb/project/tools/windows/scripts/mkimages_x64.sh +++ b/jb/project/tools/windows/scripts/mkimages_x64.sh @@ -52,7 +52,7 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} echo Running jlink ... ${JSDK}/bin/jlink \ diff --git a/jb/project/tools/windows/scripts/mkimages_x86.sh b/jb/project/tools/windows/scripts/mkimages_x86.sh index 922b2577d2a2..6ba98947959d 100755 --- a/jb/project/tools/windows/scripts/mkimages_x86.sh +++ b/jb/project/tools/windows/scripts/mkimages_x86.sh @@ -47,7 +47,7 @@ function create_image_bundle { fastdebug_infix='' [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x86-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} echo Running jlink ... ${JSDK}/bin/jlink \ diff --git a/jb/project/tools/windows/scripts/pack_aarch64.sh b/jb/project/tools/windows/scripts/pack_aarch64.sh index 717c14390638..c31979e0cfe7 100644 --- a/jb/project/tools/windows/scripts/pack_aarch64.sh +++ b/jb/project/tools/windows/scripts/pack_aarch64.sh @@ -26,7 +26,7 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-aarch64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-aarch64-${fastdebug_infix}b${build_number} echo Creating $JBR.tar.gz ... diff --git a/jb/project/tools/windows/scripts/pack_x64.sh b/jb/project/tools/windows/scripts/pack_x64.sh index 50ae73078041..9e269df05868 100755 --- a/jb/project/tools/windows/scripts/pack_x64.sh +++ b/jb/project/tools/windows/scripts/pack_x64.sh @@ -26,7 +26,7 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x64-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-x64-${fastdebug_infix}b${build_number} echo Creating $JBR.tar.gz ... chmod -R ug+rwx,o+rx ${BASE_DIR}/$__root_dir diff --git a/jb/project/tools/windows/scripts/pack_x86.sh b/jb/project/tools/windows/scripts/pack_x86.sh index 4816c2e363fd..feda61df9e27 100755 --- a/jb/project/tools/windows/scripts/pack_x86.sh +++ b/jb/project/tools/windows/scripts/pack_x86.sh @@ -22,7 +22,7 @@ function pack_jbr { [ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-" JBR=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} - __root_dir=${__bundle_name}-${JBSDK_VERSION}-x86-${fastdebug_infix:-}b${build_number%%.*} + __root_dir=${__bundle_name}-${JBSDK_VERSION}-windows-x86-${fastdebug_infix}b${build_number} echo Creating $JBR.tar.gz ... chmod -R ug+rwx,o+rx ${BASE_DIR}/$__root_dir From 1bfdb430a4ef8f2f891cd61b4b00b76ca99dc33e Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Fri, 9 Sep 2022 16:46:07 +0700 Subject: [PATCH 086/976] JBR-4810 add VERSION_PATCH into version number string --- jb/project/tools/common/scripts/common.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jb/project/tools/common/scripts/common.sh b/jb/project/tools/common/scripts/common.sh index 841a1d9adc61..a922b3aa1b3f 100644 --- a/jb/project/tools/common/scripts/common.sh +++ b/jb/project/tools/common/scripts/common.sh @@ -41,7 +41,9 @@ OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE") VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM") VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE") +VERSION_PATCH=$(getVersionProp "DEFAULT_VERSION_PATCH") [[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}" +[[ $VERSION_PATCH = 0 ]] || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}.${VERSION_PATCH}" echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']" JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')} [ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1 From 7bee9bb195a53373540d056e0a7d633c43c50e47 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Wed, 10 Feb 2021 11:27:05 +0700 Subject: [PATCH 087/976] JBR-2130 remove module jdk.pack --- jb/project/tools/common/modules.list | 1 - 1 file changed, 1 deletion(-) diff --git a/jb/project/tools/common/modules.list b/jb/project/tools/common/modules.list index 33375b527c49..9f81ee727418 100644 --- a/jb/project/tools/common/modules.list +++ b/jb/project/tools/common/modules.list @@ -45,7 +45,6 @@ jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.net, -jdk.pack, jdk.scripting.nashorn, jdk.scripting.nashorn.shell, jdk.sctp, From 56a20415f62b37168269c234cee081c52c48f6f0 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Tue, 20 Oct 2020 17:05:47 +0300 Subject: [PATCH 088/976] JBR-2807: JDK15: update modules.list to resolve jbr build failure removed nashorn modules --- jb/project/tools/common/modules.list | 2 -- 1 file changed, 2 deletions(-) diff --git a/jb/project/tools/common/modules.list b/jb/project/tools/common/modules.list index 9f81ee727418..994422d4936b 100644 --- a/jb/project/tools/common/modules.list +++ b/jb/project/tools/common/modules.list @@ -45,8 +45,6 @@ jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.net, -jdk.scripting.nashorn, -jdk.scripting.nashorn.shell, jdk.sctp, jdk.security.auth, jdk.security.jgss, From d57f4657183ec630387f9d6b958edd37685d27e2 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 29 Apr 2021 14:13:51 +0700 Subject: [PATCH 089/976] JBR-3398 remove the Experimental AOT and JIT Compiler (JEP 410) --- jb/project/tools/common/modules.list | 3 --- 1 file changed, 3 deletions(-) diff --git a/jb/project/tools/common/modules.list b/jb/project/tools/common/modules.list index 994422d4936b..054f21d1ee00 100644 --- a/jb/project/tools/common/modules.list +++ b/jb/project/tools/common/modules.list @@ -21,7 +21,6 @@ java.transaction.xa, java.xml, java.xml.crypto, jdk.accessibility, -jdk.aot, jdk.attach, jdk.charsets, jdk.compiler, @@ -32,8 +31,6 @@ jdk.httpserver, jdk.internal.ed, jdk.internal.le, jdk.internal.vm.ci, -jdk.internal.vm.compiler, -jdk.internal.vm.compiler.management, jdk.jdi, jdk.jdwp.agent, jdk.jfr, From 0d5512e0892a50b0c9be0808b33f81ba3a8ad16e Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Mon, 21 Sep 2015 16:19:19 +0300 Subject: [PATCH 090/976] IDEA-57233, IDEA-152816, IDEA-152454 Editor font antialising/appearance problems on Linux Used desktop DPI instead of hard-coded 72 Compensated increased glyph bitmap size by adjusting font size Added LCD filter for sub-pixel rendering Use fontconfig library to provide right rendering options for fonts Corrected sizes passed to fontconfig library and hinting disabling policy Added logging and versioned fontconfig lib loading Resolved font rendering problem in lenses fix text rendering issues (text cutoff and incorrect rendering in editor fragment components) FcMatchFont-type pattern substitutions shouldn't be invoked before specific font is selected - it can apply unrelated rules port commit e21cd635 from JBR 9 partially rollback JBR-363 fix, to apply corresponding change from OpenJDK 12 (cherry picked from commit 5d704a963b2c1b0b18fa40719e3c5ea1803621b8) (cherry picked from commit 3d7ac30072538ba4f09242fd98366a3efcf7f531) (cherry picked from commit 0456745afbddf162152aa45cd85b2687c2304ad4) (cherry picked from commit 3d7ac30072538ba4f09242fd98366a3efcf7f531) (cherry picked from commit 4c8351fecfce7560d52a148468dd48f2c3276d3c) (cherry picked from commit 5faebc73d57d14e8541eb88ea7b757038e10c26f) (cherry picked from commit d1ed8ab118c3c22b235e1a519aa4a90bcdcab42d) --- .../classes/sun/font/FreetypeFontScaler.java | 5 +- .../share/native/libfontmanager/fontconfig.h | 1010 +++++++++++++++++ .../native/libfontmanager/freetypeScaler.c | 398 ++++++- 3 files changed, 1390 insertions(+), 23 deletions(-) create mode 100644 src/java.desktop/share/native/libfontmanager/fontconfig.h diff --git a/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java b/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java index 6d8d5512bae4..27f779860094 100644 --- a/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java +++ b/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java @@ -25,6 +25,7 @@ package sun.font; +import java.awt.*; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; @@ -47,10 +48,10 @@ class FreetypeFontScaler extends FontScaler { /* At the moment fontmanager library depends on freetype library and therefore no need to load it explicitly here */ FontManagerNativeLibrary.load(); - initIDs(FreetypeFontScaler.class); + initIDs(FreetypeFontScaler.class, Toolkit.class, PhysicalFont.class); } - private static native void initIDs(Class FFS); + private static native void initIDs(Class FFS, Class toolkitClass, Class pfClass); private void invalidateScaler() throws FontScalerException { nativeScaler = 0; diff --git a/src/java.desktop/share/native/libfontmanager/fontconfig.h b/src/java.desktop/share/native/libfontmanager/fontconfig.h new file mode 100644 index 000000000000..225825127fb6 --- /dev/null +++ b/src/java.desktop/share/native/libfontmanager/fontconfig.h @@ -0,0 +1,1010 @@ +/* + * fontconfig/fontconfig/fontconfig.h + * + * Copyright © 2001 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the author(s) not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FONTCONFIG_H_ +#define _FONTCONFIG_H_ + +#include +#include +#include + +#if defined(__GNUC__) && (__GNUC__ >= 4) +#define FC_ATTRIBUTE_SENTINEL(x) __attribute__((__sentinel__(0))) +#else +#define FC_ATTRIBUTE_SENTINEL(x) +#endif + +#ifndef FcPublic +#define FcPublic +#endif + +typedef unsigned char FcChar8; +typedef unsigned short FcChar16; +typedef unsigned int FcChar32; +typedef int FcBool; + +/* + * Current Fontconfig version number. This same number + * must appear in the fontconfig configure.in file. Yes, + * it'a a pain to synchronize version numbers like this. + */ + +#define FC_MAJOR 2 +#define FC_MINOR 11 +#define FC_REVISION 1 + +#define FC_VERSION ((FC_MAJOR * 10000) + (FC_MINOR * 100) + (FC_REVISION)) + +/* + * Current font cache file format version + * This is appended to the cache files so that multiple + * versions of the library will peacefully coexist + * + * Change this value whenever the disk format for the cache file + * changes in any non-compatible way. Try to avoid such changes as + * it means multiple copies of the font information. + */ + +#define FC_CACHE_VERSION "4" + +#define FcTrue 1 +#define FcFalse 0 + +#define FC_FAMILY "family" /* String */ +#define FC_STYLE "style" /* String */ +#define FC_SLANT "slant" /* Int */ +#define FC_WEIGHT "weight" /* Int */ +#define FC_SIZE "size" /* Double */ +#define FC_ASPECT "aspect" /* Double */ +#define FC_PIXEL_SIZE "pixelsize" /* Double */ +#define FC_SPACING "spacing" /* Int */ +#define FC_FOUNDRY "foundry" /* String */ +#define FC_ANTIALIAS "antialias" /* Bool (depends) */ +#define FC_HINTING "hinting" /* Bool (true) */ +#define FC_HINT_STYLE "hintstyle" /* Int */ +#define FC_VERTICAL_LAYOUT "verticallayout" /* Bool (false) */ +#define FC_AUTOHINT "autohint" /* Bool (false) */ +/* FC_GLOBAL_ADVANCE is deprecated. this is simply ignored on freetype 2.4.5 or later */ +#define FC_GLOBAL_ADVANCE "globaladvance" /* Bool (true) */ +#define FC_WIDTH "width" /* Int */ +#define FC_FILE "file" /* String */ +#define FC_INDEX "index" /* Int */ +#define FC_FT_FACE "ftface" /* FT_Face */ +#define FC_RASTERIZER "rasterizer" /* String (deprecated) */ +#define FC_OUTLINE "outline" /* Bool */ +#define FC_SCALABLE "scalable" /* Bool */ +#define FC_SCALE "scale" /* double */ +#define FC_DPI "dpi" /* double */ +#define FC_RGBA "rgba" /* Int */ +#define FC_MINSPACE "minspace" /* Bool use minimum line spacing */ +#define FC_SOURCE "source" /* String (deprecated) */ +#define FC_CHARSET "charset" /* CharSet */ +#define FC_LANG "lang" /* String RFC 3066 langs */ +#define FC_FONTVERSION "fontversion" /* Int from 'head' table */ +#define FC_FULLNAME "fullname" /* String */ +#define FC_FAMILYLANG "familylang" /* String RFC 3066 langs */ +#define FC_STYLELANG "stylelang" /* String RFC 3066 langs */ +#define FC_FULLNAMELANG "fullnamelang" /* String RFC 3066 langs */ +#define FC_CAPABILITY "capability" /* String */ +#define FC_FONTFORMAT "fontformat" /* String */ +#define FC_EMBOLDEN "embolden" /* Bool - true if emboldening needed*/ +#define FC_EMBEDDED_BITMAP "embeddedbitmap" /* Bool - true to enable embedded bitmaps */ +#define FC_DECORATIVE "decorative" /* Bool - true if style is a decorative variant */ +#define FC_LCD_FILTER "lcdfilter" /* Int */ +#define FC_FONT_FEATURES "fontfeatures" /* String */ +#define FC_NAMELANG "namelang" /* String RFC 3866 langs */ +#define FC_PRGNAME "prgname" /* String */ +#define FC_HASH "hash" /* String */ +#define FC_POSTSCRIPT_NAME "postscriptname" /* String */ + +#define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION +#define FC_DIR_CACHE_FILE "fonts.cache-" FC_CACHE_VERSION +#define FC_USER_CACHE_FILE ".fonts.cache-" FC_CACHE_VERSION + +/* Adjust outline rasterizer */ +#define FC_CHAR_WIDTH "charwidth" /* Int */ +#define FC_CHAR_HEIGHT "charheight"/* Int */ +#define FC_MATRIX "matrix" /* FcMatrix */ + +#define FC_WEIGHT_THIN 0 +#define FC_WEIGHT_EXTRALIGHT 40 +#define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT +#define FC_WEIGHT_LIGHT 50 +#define FC_WEIGHT_BOOK 75 +#define FC_WEIGHT_REGULAR 80 +#define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR +#define FC_WEIGHT_MEDIUM 100 +#define FC_WEIGHT_DEMIBOLD 180 +#define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD +#define FC_WEIGHT_BOLD 200 +#define FC_WEIGHT_EXTRABOLD 205 +#define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD +#define FC_WEIGHT_BLACK 210 +#define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK +#define FC_WEIGHT_EXTRABLACK 215 +#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_EXTRABLACK + +#define FC_SLANT_ROMAN 0 +#define FC_SLANT_ITALIC 100 +#define FC_SLANT_OBLIQUE 110 + +#define FC_WIDTH_ULTRACONDENSED 50 +#define FC_WIDTH_EXTRACONDENSED 63 +#define FC_WIDTH_CONDENSED 75 +#define FC_WIDTH_SEMICONDENSED 87 +#define FC_WIDTH_NORMAL 100 +#define FC_WIDTH_SEMIEXPANDED 113 +#define FC_WIDTH_EXPANDED 125 +#define FC_WIDTH_EXTRAEXPANDED 150 +#define FC_WIDTH_ULTRAEXPANDED 200 + +#define FC_PROPORTIONAL 0 +#define FC_DUAL 90 +#define FC_MONO 100 +#define FC_CHARCELL 110 + +/* sub-pixel order */ +#define FC_RGBA_UNKNOWN 0 +#define FC_RGBA_RGB 1 +#define FC_RGBA_BGR 2 +#define FC_RGBA_VRGB 3 +#define FC_RGBA_VBGR 4 +#define FC_RGBA_NONE 5 + +/* hinting style */ +#define FC_HINT_NONE 0 +#define FC_HINT_SLIGHT 1 +#define FC_HINT_MEDIUM 2 +#define FC_HINT_FULL 3 + +/* LCD filter */ +#define FC_LCD_NONE 0 +#define FC_LCD_DEFAULT 1 +#define FC_LCD_LIGHT 2 +#define FC_LCD_LEGACY 3 + +typedef enum _FcType { + FcTypeUnknown = -1, + FcTypeVoid, + FcTypeInteger, + FcTypeDouble, + FcTypeString, + FcTypeBool, + FcTypeMatrix, + FcTypeCharSet, + FcTypeFTFace, + FcTypeLangSet +} FcType; + +typedef struct _FcMatrix { + double xx, xy, yx, yy; +} FcMatrix; + +#define FcMatrixInit(m) ((m)->xx = (m)->yy = 1, \ + (m)->xy = (m)->yx = 0) + +/* + * A data structure to represent the available glyphs in a font. + * This is represented as a sparse boolean btree. + */ + +typedef struct _FcCharSet FcCharSet; + +typedef struct _FcObjectType { + const char *object; + FcType type; +} FcObjectType; + +typedef struct _FcConstant { + const FcChar8 *name; + const char *object; + int value; +} FcConstant; + +typedef enum _FcResult { + FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId, + FcResultOutOfMemory +} FcResult; + +typedef struct _FcPattern FcPattern; + +typedef struct _FcLangSet FcLangSet; + +typedef struct _FcValue { + FcType type; + union { + const FcChar8 *s; + int i; + FcBool b; + double d; + const FcMatrix *m; + const FcCharSet *c; + void *f; + const FcLangSet *l; + } u; +} FcValue; + +typedef struct _FcFontSet { + int nfont; + int sfont; + FcPattern **fonts; +} FcFontSet; + +typedef struct _FcObjectSet { + int nobject; + int sobject; + const char **objects; +} FcObjectSet; + +typedef enum _FcMatchKind { + FcMatchPattern, FcMatchFont, FcMatchScan +} FcMatchKind; + +typedef enum _FcLangResult { + FcLangEqual = 0, + FcLangDifferentCountry = 1, + FcLangDifferentTerritory = 1, + FcLangDifferentLang = 2 +} FcLangResult; + +typedef enum _FcSetName { + FcSetSystem = 0, + FcSetApplication = 1 +} FcSetName; + +typedef struct _FcAtomic FcAtomic; + +#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */ +#define _FCFUNCPROTOBEGIN extern "C" { /* do not leave open across includes */ +#define _FCFUNCPROTOEND } +#else +#define _FCFUNCPROTOBEGIN +#define _FCFUNCPROTOEND +#endif + +typedef enum { FcEndianBig, FcEndianLittle } FcEndian; + +typedef struct _FcConfig FcConfig; + +typedef struct _FcGlobalCache FcFileCache; + +typedef struct _FcBlanks FcBlanks; + +typedef struct _FcStrList FcStrList; + +typedef struct _FcStrSet FcStrSet; + +typedef struct _FcCache FcCache; + +_FCFUNCPROTOBEGIN + +/* fcblanks.c */ +FcPublic FcBlanks * +FcBlanksCreate (void); + +FcPublic void +FcBlanksDestroy (FcBlanks *b); + +FcPublic FcBool +FcBlanksAdd (FcBlanks *b, FcChar32 ucs4); + +FcPublic FcBool +FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4); + +/* fccache.c */ + +FcPublic const FcChar8 * +FcCacheDir(const FcCache *c); + +FcPublic FcFontSet * +FcCacheCopySet(const FcCache *c); + +FcPublic const FcChar8 * +FcCacheSubdir (const FcCache *c, int i); + +FcPublic int +FcCacheNumSubdir (const FcCache *c); + +FcPublic int +FcCacheNumFont (const FcCache *c); + +FcPublic FcBool +FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config); + +FcPublic FcBool +FcDirCacheValid (const FcChar8 *cache_file); + +FcPublic FcBool +FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose); + +FcPublic void +FcCacheCreateTagFile (const FcConfig *config); + +/* fccfg.c */ +FcPublic FcChar8 * +FcConfigHome (void); + +FcPublic FcBool +FcConfigEnableHome (FcBool enable); + +FcPublic FcChar8 * +FcConfigFilename (const FcChar8 *url); + +FcPublic FcConfig * +FcConfigCreate (void); + +FcPublic FcConfig * +FcConfigReference (FcConfig *config); + +FcPublic void +FcConfigDestroy (FcConfig *config); + +FcPublic FcBool +FcConfigSetCurrent (FcConfig *config); + +FcPublic FcConfig * +FcConfigGetCurrent (void); + +FcPublic FcBool +FcConfigUptoDate (FcConfig *config); + +FcPublic FcBool +FcConfigBuildFonts (FcConfig *config); + +FcPublic FcStrList * +FcConfigGetFontDirs (FcConfig *config); + +FcPublic FcStrList * +FcConfigGetConfigDirs (FcConfig *config); + +FcPublic FcStrList * +FcConfigGetConfigFiles (FcConfig *config); + +FcPublic FcChar8 * +FcConfigGetCache (FcConfig *config); + +FcPublic FcBlanks * +FcConfigGetBlanks (FcConfig *config); + +FcPublic FcStrList * +FcConfigGetCacheDirs (const FcConfig *config); + +FcPublic int +FcConfigGetRescanInterval (FcConfig *config); + +FcPublic FcBool +FcConfigSetRescanInterval (FcConfig *config, int rescanInterval); + +FcPublic FcFontSet * +FcConfigGetFonts (FcConfig *config, + FcSetName set); + +FcPublic FcBool +FcConfigAppFontAddFile (FcConfig *config, + const FcChar8 *file); + +FcPublic FcBool +FcConfigAppFontAddDir (FcConfig *config, + const FcChar8 *dir); + +FcPublic void +FcConfigAppFontClear (FcConfig *config); + +FcPublic FcBool +FcConfigSubstituteWithPat (FcConfig *config, + FcPattern *p, + FcPattern *p_pat, + FcMatchKind kind); + +FcPublic FcBool +FcConfigSubstitute (FcConfig *config, + FcPattern *p, + FcMatchKind kind); + +FcPublic const FcChar8 * +FcConfigGetSysRoot (const FcConfig *config); + +FcPublic void +FcConfigSetSysRoot (FcConfig *config, + const FcChar8 *sysroot); + +/* fccharset.c */ +FcPublic FcCharSet* +FcCharSetCreate (void); + +/* deprecated alias for FcCharSetCreate */ +FcPublic FcCharSet * +FcCharSetNew (void); + +FcPublic void +FcCharSetDestroy (FcCharSet *fcs); + +FcPublic FcBool +FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4); + +FcPublic FcBool +FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4); + +FcPublic FcCharSet* +FcCharSetCopy (FcCharSet *src); + +FcPublic FcBool +FcCharSetEqual (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcCharSet* +FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcCharSet* +FcCharSetUnion (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcCharSet* +FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcBool +FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed); + +FcPublic FcBool +FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4); + +FcPublic FcChar32 +FcCharSetCount (const FcCharSet *a); + +FcPublic FcChar32 +FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcChar32 +FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b); + +FcPublic FcBool +FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b); + +#define FC_CHARSET_MAP_SIZE (256/32) +#define FC_CHARSET_DONE ((FcChar32) -1) + +FcPublic FcChar32 +FcCharSetFirstPage (const FcCharSet *a, + FcChar32 map[FC_CHARSET_MAP_SIZE], + FcChar32 *next); + +FcPublic FcChar32 +FcCharSetNextPage (const FcCharSet *a, + FcChar32 map[FC_CHARSET_MAP_SIZE], + FcChar32 *next); + +/* + * old coverage API, rather hard to use correctly + */ + +FcPublic FcChar32 +FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result); + +/* fcdbg.c */ +FcPublic void +FcValuePrint (const FcValue v); + +FcPublic void +FcPatternPrint (const FcPattern *p); + +FcPublic void +FcFontSetPrint (const FcFontSet *s); + +/* fcdefault.c */ +FcPublic FcStrSet * +FcGetDefaultLangs (void); + +FcPublic void +FcDefaultSubstitute (FcPattern *pattern); + +/* fcdir.c */ +FcPublic FcBool +FcFileIsDir (const FcChar8 *file); + +FcPublic FcBool +FcFileScan (FcFontSet *set, + FcStrSet *dirs, + FcFileCache *cache, + FcBlanks *blanks, + const FcChar8 *file, + FcBool force); + +FcPublic FcBool +FcDirScan (FcFontSet *set, + FcStrSet *dirs, + FcFileCache *cache, + FcBlanks *blanks, + const FcChar8 *dir, + FcBool force); + +FcPublic FcBool +FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir); + +FcPublic FcCache * +FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file); + +FcPublic FcCache * +FcDirCacheRescan (const FcChar8 *dir, FcConfig *config); + +FcPublic FcCache * +FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config); + +FcPublic FcCache * +FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat); + +FcPublic void +FcDirCacheUnload (FcCache *cache); + +/* fcfreetype.c */ +FcPublic FcPattern * +FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count); + +/* fcfs.c */ + +FcPublic FcFontSet * +FcFontSetCreate (void); + +FcPublic void +FcFontSetDestroy (FcFontSet *s); + +FcPublic FcBool +FcFontSetAdd (FcFontSet *s, FcPattern *font); + +/* fcinit.c */ +FcPublic FcConfig * +FcInitLoadConfig (void); + +FcPublic FcConfig * +FcInitLoadConfigAndFonts (void); + +FcPublic FcBool +FcInit (void); + +FcPublic void +FcFini (void); + +FcPublic int +FcGetVersion (void); + +FcPublic FcBool +FcInitReinitialize (void); + +FcPublic FcBool +FcInitBringUptoDate (void); + +/* fclang.c */ +FcPublic FcStrSet * +FcGetLangs (void); + +FcPublic FcChar8 * +FcLangNormalize (const FcChar8 *lang); + +FcPublic const FcCharSet * +FcLangGetCharSet (const FcChar8 *lang); + +FcPublic FcLangSet* +FcLangSetCreate (void); + +FcPublic void +FcLangSetDestroy (FcLangSet *ls); + +FcPublic FcLangSet* +FcLangSetCopy (const FcLangSet *ls); + +FcPublic FcBool +FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang); + +FcPublic FcBool +FcLangSetDel (FcLangSet *ls, const FcChar8 *lang); + +FcPublic FcLangResult +FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang); + +FcPublic FcLangResult +FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb); + +FcPublic FcBool +FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb); + +FcPublic FcBool +FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb); + +FcPublic FcChar32 +FcLangSetHash (const FcLangSet *ls); + +FcPublic FcStrSet * +FcLangSetGetLangs (const FcLangSet *ls); + +FcPublic FcLangSet * +FcLangSetUnion (const FcLangSet *a, const FcLangSet *b); + +FcPublic FcLangSet * +FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b); + +/* fclist.c */ +FcPublic FcObjectSet * +FcObjectSetCreate (void); + +FcPublic FcBool +FcObjectSetAdd (FcObjectSet *os, const char *object); + +FcPublic void +FcObjectSetDestroy (FcObjectSet *os); + +FcPublic FcObjectSet * +FcObjectSetVaBuild (const char *first, va_list va); + +FcPublic FcObjectSet * +FcObjectSetBuild (const char *first, ...) FC_ATTRIBUTE_SENTINEL(0); + +FcPublic FcFontSet * +FcFontSetList (FcConfig *config, + FcFontSet **sets, + int nsets, + FcPattern *p, + FcObjectSet *os); + +FcPublic FcFontSet * +FcFontList (FcConfig *config, + FcPattern *p, + FcObjectSet *os); + +/* fcatomic.c */ + +FcPublic FcAtomic * +FcAtomicCreate (const FcChar8 *file); + +FcPublic FcBool +FcAtomicLock (FcAtomic *atomic); + +FcPublic FcChar8 * +FcAtomicNewFile (FcAtomic *atomic); + +FcPublic FcChar8 * +FcAtomicOrigFile (FcAtomic *atomic); + +FcPublic FcBool +FcAtomicReplaceOrig (FcAtomic *atomic); + +FcPublic void +FcAtomicDeleteNew (FcAtomic *atomic); + +FcPublic void +FcAtomicUnlock (FcAtomic *atomic); + +FcPublic void +FcAtomicDestroy (FcAtomic *atomic); + +/* fcmatch.c */ +FcPublic FcPattern * +FcFontSetMatch (FcConfig *config, + FcFontSet **sets, + int nsets, + FcPattern *p, + FcResult *result); + +FcPublic FcPattern * +FcFontMatch (FcConfig *config, + FcPattern *p, + FcResult *result); + +FcPublic FcPattern * +FcFontRenderPrepare (FcConfig *config, + FcPattern *pat, + FcPattern *font); + +FcPublic FcFontSet * +FcFontSetSort (FcConfig *config, + FcFontSet **sets, + int nsets, + FcPattern *p, + FcBool trim, + FcCharSet **csp, + FcResult *result); + +FcPublic FcFontSet * +FcFontSort (FcConfig *config, + FcPattern *p, + FcBool trim, + FcCharSet **csp, + FcResult *result); + +FcPublic void +FcFontSetSortDestroy (FcFontSet *fs); + +/* fcmatrix.c */ +FcPublic FcMatrix * +FcMatrixCopy (const FcMatrix *mat); + +FcPublic FcBool +FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2); + +FcPublic void +FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b); + +FcPublic void +FcMatrixRotate (FcMatrix *m, double c, double s); + +FcPublic void +FcMatrixScale (FcMatrix *m, double sx, double sy); + +FcPublic void +FcMatrixShear (FcMatrix *m, double sh, double sv); + +/* fcname.c */ + +/* Deprecated. Does nothing. Returns FcFalse. */ +FcPublic FcBool +FcNameRegisterObjectTypes (const FcObjectType *types, int ntype); + +/* Deprecated. Does nothing. Returns FcFalse. */ +FcPublic FcBool +FcNameUnregisterObjectTypes (const FcObjectType *types, int ntype); + +FcPublic const FcObjectType * +FcNameGetObjectType (const char *object); + +/* Deprecated. Does nothing. Returns FcFalse. */ +FcPublic FcBool +FcNameRegisterConstants (const FcConstant *consts, int nconsts); + +/* Deprecated. Does nothing. Returns FcFalse. */ +FcPublic FcBool +FcNameUnregisterConstants (const FcConstant *consts, int nconsts); + +FcPublic const FcConstant * +FcNameGetConstant (const FcChar8 *string); + +FcPublic FcBool +FcNameConstant (const FcChar8 *string, int *result); + +FcPublic FcPattern * +FcNameParse (const FcChar8 *name); + +FcPublic FcChar8 * +FcNameUnparse (FcPattern *pat); + +/* fcpat.c */ +FcPublic FcPattern * +FcPatternCreate (void); + +FcPublic FcPattern * +FcPatternDuplicate (const FcPattern *p); + +FcPublic void +FcPatternReference (FcPattern *p); + +FcPublic FcPattern * +FcPatternFilter (FcPattern *p, const FcObjectSet *os); + +FcPublic void +FcValueDestroy (FcValue v); + +FcPublic FcBool +FcValueEqual (FcValue va, FcValue vb); + +FcPublic FcValue +FcValueSave (FcValue v); + +FcPublic void +FcPatternDestroy (FcPattern *p); + +FcPublic FcBool +FcPatternEqual (const FcPattern *pa, const FcPattern *pb); + +FcPublic FcBool +FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os); + +FcPublic FcChar32 +FcPatternHash (const FcPattern *p); + +FcPublic FcBool +FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append); + +FcPublic FcBool +FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append); + +FcPublic FcResult +FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v); + +FcPublic FcBool +FcPatternDel (FcPattern *p, const char *object); + +FcPublic FcBool +FcPatternRemove (FcPattern *p, const char *object, int id); + +FcPublic FcBool +FcPatternAddInteger (FcPattern *p, const char *object, int i); + +FcPublic FcBool +FcPatternAddDouble (FcPattern *p, const char *object, double d); + +FcPublic FcBool +FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s); + +FcPublic FcBool +FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s); + +FcPublic FcBool +FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c); + +FcPublic FcBool +FcPatternAddBool (FcPattern *p, const char *object, FcBool b); + +FcPublic FcBool +FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls); + +FcPublic FcResult +FcPatternGetInteger (const FcPattern *p, const char *object, int n, int *i); + +FcPublic FcResult +FcPatternGetDouble (const FcPattern *p, const char *object, int n, double *d); + +FcPublic FcResult +FcPatternGetString (const FcPattern *p, const char *object, int n, FcChar8 ** s); + +FcPublic FcResult +FcPatternGetMatrix (const FcPattern *p, const char *object, int n, FcMatrix **s); + +FcPublic FcResult +FcPatternGetCharSet (const FcPattern *p, const char *object, int n, FcCharSet **c); + +FcPublic FcResult +FcPatternGetBool (const FcPattern *p, const char *object, int n, FcBool *b); + +FcPublic FcResult +FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **ls); + +FcPublic FcPattern * +FcPatternVaBuild (FcPattern *p, va_list va); + +FcPublic FcPattern * +FcPatternBuild (FcPattern *p, ...) FC_ATTRIBUTE_SENTINEL(0); + +FcPublic FcChar8 * +FcPatternFormat (FcPattern *pat, const FcChar8 *format); + +/* fcstr.c */ + +FcPublic FcChar8 * +FcStrCopy (const FcChar8 *s); + +FcPublic FcChar8 * +FcStrCopyFilename (const FcChar8 *s); + +FcPublic FcChar8 * +FcStrPlus (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic void +FcStrFree (FcChar8 *s); + +/* These are ASCII only, suitable only for pattern element names */ +#define FcIsUpper(c) ((0101 <= (c) && (c) <= 0132)) +#define FcIsLower(c) ((0141 <= (c) && (c) <= 0172)) +#define FcToLower(c) (FcIsUpper(c) ? (c) - 0101 + 0141 : (c)) + +FcPublic FcChar8 * +FcStrDowncase (const FcChar8 *s); + +FcPublic int +FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic int +FcStrCmp (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic const FcChar8 * +FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic const FcChar8 * +FcStrStr (const FcChar8 *s1, const FcChar8 *s2); + +FcPublic int +FcUtf8ToUcs4 (const FcChar8 *src_orig, + FcChar32 *dst, + int len); + +FcPublic FcBool +FcUtf8Len (const FcChar8 *string, + int len, + int *nchar, + int *wchar); + +#define FC_UTF8_MAX_LEN 6 + +FcPublic int +FcUcs4ToUtf8 (FcChar32 ucs4, + FcChar8 dest[FC_UTF8_MAX_LEN]); + +FcPublic int +FcUtf16ToUcs4 (const FcChar8 *src_orig, + FcEndian endian, + FcChar32 *dst, + int len); /* in bytes */ + +FcPublic FcBool +FcUtf16Len (const FcChar8 *string, + FcEndian endian, + int len, /* in bytes */ + int *nchar, + int *wchar); + +FcPublic FcChar8 * +FcStrDirname (const FcChar8 *file); + +FcPublic FcChar8 * +FcStrBasename (const FcChar8 *file); + +FcPublic FcStrSet * +FcStrSetCreate (void); + +FcPublic FcBool +FcStrSetMember (FcStrSet *set, const FcChar8 *s); + +FcPublic FcBool +FcStrSetEqual (FcStrSet *sa, FcStrSet *sb); + +FcPublic FcBool +FcStrSetAdd (FcStrSet *set, const FcChar8 *s); + +FcPublic FcBool +FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s); + +FcPublic FcBool +FcStrSetDel (FcStrSet *set, const FcChar8 *s); + +FcPublic void +FcStrSetDestroy (FcStrSet *set); + +FcPublic FcStrList * +FcStrListCreate (FcStrSet *set); + +FcPublic void +FcStrListFirst (FcStrList *list); + +FcPublic FcChar8 * +FcStrListNext (FcStrList *list); + +FcPublic void +FcStrListDone (FcStrList *list); + +/* fcxml.c */ +FcPublic FcBool +FcConfigParseAndLoad (FcConfig *config, const FcChar8 *file, FcBool complain); + +_FCFUNCPROTOEND + +#undef FC_ATTRIBUTE_SENTINEL + + +#ifndef _FCINT_H_ + +/* + * Deprecated functions are placed here to help users fix their code without + * digging through documentation + */ + +#define FcConfigGetRescanInverval FcConfigGetRescanInverval_REPLACE_BY_FcConfigGetRescanInterval +#define FcConfigSetRescanInverval FcConfigSetRescanInverval_REPLACE_BY_FcConfigSetRescanInterval + +#endif + +#endif /* _FONTCONFIG_H_ */ diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 21ac280f0fb0..f272eabd1fe1 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -25,7 +25,7 @@ #include "jni.h" #include "jni_util.h" -#include "jlong.h" +#include "jvm_md.h" #include "sunfontids.h" #include "sun_font_FreetypeFontScaler.h" @@ -33,8 +33,10 @@ #if !defined(_WIN32) && !defined(__APPLE_) #include #endif +#include #include #include "ft2build.h" +#include FT_LCD_FILTER_H #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_BBOX_H @@ -43,6 +45,12 @@ #include FT_SYNTHESIS_H #include FT_LCD_FILTER_H #include FT_MODULE_H +#include FT_LCD_FILTER_H + +#ifndef _WIN32 +/* Use bundled fontconfig.h for now */ +#include "fontconfig.h" +#endif #include "fontscaler.h" @@ -56,6 +64,23 @@ #define FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1)) #define FTFixedToFloat(x) ((x) / (float)(ftFixed1)) #define FT26Dot6ToFloat(x) ((x) / ((float) (1<<6))) +#define ROUND(x) ((int) ((x<0) ? (x-0.5) : (x+0.5))) +#define FT26Dot6ToDouble(x) ((x) / ((double) (1<<6))) +#define FT26Dot6ToInt(x) (((int)(x)) >> 6) +#define DEFAULT_DPI 72 +#define ADJUST_FONT_SIZE(X, DPI) (((X)*DEFAULT_DPI + ((DPI)>>1))/(DPI)) + +#ifndef _WIN32 +#define FONTCONFIG_DLL JNI_LIB_NAME("fontconfig") +#define FONTCONFIG_DLL_VERSIONED VERSIONED_JNI_LIB_NAME("fontconfig", "1") +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif typedef struct { /* Important note: @@ -87,7 +112,12 @@ typedef struct FTScalerContext { jint fmType; /* fractional metrics - on/off */ jboolean doBold; /* perform algorithmic bolding? */ jboolean doItalize; /* perform algorithmic italicizing? */ - int renderFlags; /* configuration specific to particular engine */ + + /* Fontconfig info */ + FT_Render_Mode renderFlags; + FT_Int32 loadFlags; + FT_LcdFilter lcdFilter; + int pathType; int ptsz; /* size in points */ } FTScalerContext; @@ -104,10 +134,70 @@ void z_error(char *s) {} static jmethodID invalidateScalerMID; static jboolean debugFonts; // Stores the value of FontUtilities.debugFonts() +static jmethodID getDefaultToolkitMID; +static jclass tkClass; +static jmethodID getScreenResolutionMID; +static jfieldID platNameFID; + +#ifndef _WIN32 +typedef FcBool (*FcPatternAddPtrType) (FcPattern *p, const char *object, FcValue value, FcBool append); +typedef FcBool (*FcPatternAddBoolPtrType) (FcPattern *p, const char *object, FcBool b); +typedef FcBool (*FcPatternAddDoublePtrType) (FcPattern *p, const char *object, double d); +typedef FcBool (*FcConfigSubstitutePtrType) (FcConfig *config, FcPattern *p, FcMatchKind kind); +typedef void (*FcDefaultSubstitutePtrType) (FcPattern *pattern); +typedef FcPattern* (*FcPatternCreatePtrType) (); +typedef FcPattern* (*FcFontMatchPtrType) (FcConfig *config, FcPattern *p, FcResult *result); +typedef void (*FcPatternDestroyPtrType) (FcPattern *p); +typedef FcResult (*FcPatternGetBoolPtrType) (const FcPattern *p, const char *object, int n, FcBool *b); +typedef FcResult (*FcPatternGetIntegerPtrType) (const FcPattern *p, const char *object, int n, int *i); +#endif + +static void *libFontConfig = NULL; +static jboolean logFC = JNI_FALSE; + +#ifndef _WIN32 +static FcPatternAddPtrType FcPatternAddPtr; +static FcPatternAddBoolPtrType FcPatternAddBoolPtr; +static FcPatternAddDoublePtrType FcPatternAddDoublePtr; +static FcConfigSubstitutePtrType FcConfigSubstitutePtr; +static FcDefaultSubstitutePtrType FcDefaultSubstitutePtr; +static FcPatternCreatePtrType FcPatternCreatePtr; +static FcFontMatchPtrType FcFontMatchPtr; +static FcPatternDestroyPtrType FcPatternDestroyPtr; +static FcPatternGetBoolPtrType FcPatternGetBoolPtr; +static FcPatternGetIntegerPtrType FcPatternGetIntegerPtr; +#endif + +static void* openFontConfig() { + void* libfontconfig = NULL; +#ifndef _WIN32 + char *fcLogEnabled = getenv("OPENJDK_FFS_LOG_FC"); + + if (fcLogEnabled != NULL && !strcmp(fcLogEnabled, "yes")) { + logFC = JNI_TRUE; + } + + char *useFC = getenv("OPENJDK_FFS_USE_FC"); + if (useFC != NULL && !strcmp(useFC, "no")) { + if (logFC) fprintf(stderr, "FC_LOG: fontconfig disabled in freetypescaler\n"); + return NULL; + } + + libfontconfig = dlopen(FONTCONFIG_DLL_VERSIONED, RTLD_LOCAL | RTLD_LAZY); + if (libfontconfig == NULL) { + libfontconfig = dlopen(FONTCONFIG_DLL, RTLD_LOCAL | RTLD_LAZY); + if (libfontconfig == NULL) { + if (logFC) fprintf(stderr, "FC_LOG: cannot open %s\n", FONTCONFIG_DLL); + return NULL; + } + } +#endif + return libfontconfig; +} JNIEXPORT void JNICALL Java_sun_font_FreetypeFontScaler_initIDs( - JNIEnv *env, jobject scaler, jclass FFSClass) { + JNIEnv *env, jobject scaler, jclass FFSClass, jclass TKClass, jclass PFClass) { invalidateScalerMID = (*env)->GetMethodID(env, FFSClass, "invalidateScaler", "()V"); @@ -115,6 +205,51 @@ Java_sun_font_FreetypeFontScaler_initIDs( debugFonts = JNU_CallStaticMethodByName(env, &ignoreException, "sun/font/FontUtilities", "debugFonts", "()Z").z; + getDefaultToolkitMID = + (*env)->GetStaticMethodID(env, TKClass, "getDefaultToolkit", + "()Ljava/awt/Toolkit;"); + getScreenResolutionMID = + (*env)->GetMethodID(env, TKClass, "getScreenResolution", "()I"); + tkClass = (*env)->NewGlobalRef(env, TKClass); + platNameFID = (*env)->GetFieldID(env, PFClass, "platName", "Ljava/lang/String;"); + libFontConfig = openFontConfig(); +#ifndef _WIN32 + if (libFontConfig) { + FcPatternAddPtr = (FcPatternAddPtrType) dlsym(libFontConfig, "FcPatternAdd"); + FcPatternAddBoolPtr = (FcPatternAddBoolPtrType) dlsym(libFontConfig, "FcPatternAddBool"); + FcPatternAddDoublePtr = (FcPatternAddDoublePtrType) dlsym(libFontConfig, "FcPatternAddDouble"); + FcConfigSubstitutePtr = (FcConfigSubstitutePtrType) dlsym(libFontConfig, "FcConfigSubstitute"); + FcDefaultSubstitutePtr = (FcDefaultSubstitutePtrType) dlsym(libFontConfig, "FcDefaultSubstitute"); + FcPatternCreatePtr = (FcPatternCreatePtrType) dlsym(libFontConfig, "FcPatternCreate"); + FcFontMatchPtr = (FcFontMatchPtrType) dlsym(libFontConfig, "FcFontMatch"); + FcPatternDestroyPtr = (FcPatternDestroyPtrType) dlsym(libFontConfig, "FcPatternDestroy"); + FcPatternGetBoolPtr = (FcPatternGetBoolPtrType) dlsym(libFontConfig, "FcPatternGetBool"); + FcPatternGetIntegerPtr = (FcPatternGetIntegerPtrType) dlsym(libFontConfig, "FcPatternGetInteger"); + } +#endif +} + +static char* getPhysFontName(JNIEnv *env, jobject font2d) { + jstring jstr; + jstr = (*env)->GetObjectField(env, font2d, platNameFID); + return (char*)(*env)->GetStringUTFChars(env, jstr, NULL); +} + +static int getScreenResolution(JNIEnv *env) { + jthrowable exc; + jclass tk = (*env)->CallStaticObjectMethod( + env, tkClass, getDefaultToolkitMID); + int dpi = (*env)->CallIntMethod(env, tk, getScreenResolutionMID); + + /* Test if there is no exception here (can get java.awt.HeadlessException) + * Fallback to default DPI otherwise + */ + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionClear(env); + return DEFAULT_DPI; + } + return dpi; } static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) { @@ -581,27 +716,236 @@ static void setupTransform(FT_Matrix* target, FTScalerContext *context) { static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, - FTScalerContext *context) { + FTScalerContext *context, + FT_Bool configureFont) { FT_Matrix matrix; int errCode = 0; - scalerInfo->env = env; scalerInfo->font2D = font2D; if (context != NULL) { setupTransform(&matrix, context); FT_Set_Transform(scalerInfo->face, &matrix, NULL); + FT_UInt dpi = (FT_UInt) getScreenResolution(env); + + errCode = FT_Set_Char_Size(scalerInfo->face, 0, ADJUST_FONT_SIZE(context->ptsz, dpi), dpi, dpi); + if (errCode) return errCode; + + errCode = FT_Activate_Size(scalerInfo->face->size); + if (errCode) return errCode; + if (configureFont) { + context->renderFlags = FT_RENDER_MODE_NORMAL; + context->lcdFilter = FT_LCD_FILTER_NONE; + context->loadFlags = FT_LOAD_DEFAULT; + + if (libFontConfig == NULL) { + if (context->aaType == TEXT_AA_OFF) { + context->loadFlags = FT_LOAD_TARGET_MONO; + } else if (context->aaType == TEXT_AA_ON) { + context->loadFlags = FT_LOAD_TARGET_LIGHT; + } else { + context->lcdFilter = FT_LCD_FILTER_LIGHT; + if (context->aaType == TEXT_AA_LCD_HRGB || + context->aaType == TEXT_AA_LCD_HBGR) { + context->loadFlags = FT_LOAD_TARGET_LCD; + } else { + context->loadFlags = FT_LOAD_TARGET_LCD_V; + } + } + context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); + return 0; + } +#ifndef _WIN32 + FcPattern *fcPattern = 0; + fcPattern = (*FcPatternCreatePtr)(); + FcValue fcValue; + fcValue.type = FcTypeString; + char *fontName = getPhysFontName(env, font2D); + + if (logFC) fprintf(stderr, "FC_LOG: %s ", fontName); + + fcValue.u.s = (const FcChar8*)fontName; + (*FcPatternAddPtr)(fcPattern, FC_FILE, fcValue, FcTrue); + (*FcPatternAddBoolPtr)(fcPattern, FC_SCALABLE, FcTrue); + double fcSize = FT26Dot6ToDouble(ADJUST_FONT_SIZE(context->ptsz, dpi)); + (*FcPatternAddDoublePtr)(fcPattern, FC_SIZE, fcSize); + + if (logFC) fprintf(stderr, " size=%f", fcSize); + + (*FcConfigSubstitutePtr)(0, fcPattern, FcMatchPattern); + (*FcDefaultSubstitutePtr)(fcPattern); + FcResult matchResult = FcResultNoMatch; + FcPattern *resultPattern = 0; + resultPattern = (*FcFontMatchPtr)(0, fcPattern, &matchResult); + if (matchResult != FcResultMatch) { + (*FcPatternDestroyPtr)(fcPattern); + if (logFC) fprintf(stderr, " - NOT FOUND\n"); + return 1; + } + if (logFC) fprintf(stderr, "\nFC_LOG: "); + (*FcPatternDestroyPtr)(fcPattern); + FcPattern *pattern = resultPattern; + + FcBool fcHinting = FcFalse; + FcBool fcHintingSet = (*FcPatternGetBoolPtr)(pattern, FC_HINTING, 0, &fcHinting) == FcResultMatch; + + if (logFC && fcHintingSet) fprintf(stderr, "FC_HINTING(%d) ", fcHinting); + + int fcHintStyle = FC_HINT_NONE; + FcBool fcHintStyleSet = (*FcPatternGetIntegerPtr)(pattern, FC_HINT_STYLE, 0, &fcHintStyle) == FcResultMatch; + + if (logFC && fcHintStyleSet) { + switch (fcHintStyle) { + case FC_HINT_NONE: + fprintf(stderr, "FC_HINT_NONE "); + break; + case FC_HINT_SLIGHT: + fprintf(stderr, "FC_HINT_SLIGHT "); + break; + case FC_HINT_MEDIUM: + fprintf(stderr, "FC_HINT_MEDIUM "); + break; + case FC_HINT_FULL: + fprintf(stderr, "FC_HINT_FULL "); + break; + default: + fprintf(stderr, "FC_HINT_UNKNOWN "); + break; + } + } - errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72); + if (fcHintingSet && !fcHinting) { + fcHintStyleSet = FcTrue; + fcHintStyle = FC_HINT_NONE; + } + + if (fcHintStyleSet && fcHintStyle == FC_HINT_NONE) { + fcHintingSet = FcTrue; + fcHinting = FcFalse; + } - if (errCode == 0) { - errCode = FT_Activate_Size(scalerInfo->face->size); + FcBool fcAntialias = FcFalse; + FcBool fcAntialiasSet = (*FcPatternGetBoolPtr)(pattern, FC_ANTIALIAS, 0, &fcAntialias) == FcResultMatch; + + if (logFC) { + switch(context->aaType) { + case TEXT_AA_ON: + fprintf(stderr, "JDK_AA_ON "); + break; + case TEXT_AA_OFF: + fprintf(stderr, "JDK_AA_OFF "); + break; + case TEXT_AA_LCD_HRGB: + fprintf(stderr, "JDK_AA_LCD_HRGB "); + break; + case TEXT_AA_LCD_HBGR: + fprintf(stderr, "JDK_AA_LCD_HBGR "); + break; + default: + fprintf(stderr, "JDK_AA_UNKNOWN "); + break; + } + if (fcAntialiasSet) fprintf(stderr, "FC_ANTIALIAS(%d) ", fcAntialias); + } + + if (context->aaType == TEXT_AA_ON) { // Greyscale AA + context->renderFlags = FT_RENDER_MODE_NORMAL; + if (fcHintingSet) { + switch (fcHintStyle) { + case FC_HINT_NONE: + context->loadFlags = FT_LOAD_NO_HINTING; + break; + case FC_HINT_SLIGHT: + context->loadFlags = FT_LOAD_TARGET_LIGHT; + break; + case FC_HINT_MEDIUM: + case FC_HINT_FULL: + default: + break; + } + } + } + else if (context->aaType == TEXT_AA_OFF) { // No AA + context->renderFlags = FT_RENDER_MODE_MONO; + context->loadFlags = (!fcHintingSet || fcHinting) ? FT_LOAD_TARGET_MONO : FT_LOAD_NO_HINTING; + } else { + int fcRGBA = FC_RGBA_UNKNOWN; + if (fcAntialiasSet && fcAntialias) { + if ((*FcPatternGetIntegerPtr)(pattern, FC_RGBA, 0, &fcRGBA) == FcResultMatch) { + switch (fcRGBA) { + case FC_RGBA_RGB: + case FC_RGBA_BGR: + if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_RGB ? "FC_RGBA_RGB " : "FC_RGBA_BGR "); + context->loadFlags = FT_LOAD_TARGET_LCD; + context->renderFlags = FT_RENDER_MODE_LCD; + break; + case FC_RGBA_VRGB: + case FC_RGBA_VBGR: + if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_VRGB ? "FC_RGBA_VRGB " : "FC_RGBA_VBGR "); + context->loadFlags = FT_LOAD_TARGET_LCD_V; + context->renderFlags = FT_RENDER_MODE_LCD_V; + break; + default: + if (logFC) fprintf(stderr, "FC_RGBA_UNKNOWN "); + break; + } + } + } + if (fcRGBA == FC_RGBA_UNKNOWN) { + if (context->aaType == TEXT_AA_LCD_HRGB || + context->aaType == TEXT_AA_LCD_HBGR) { + context->loadFlags = FT_LOAD_TARGET_LCD; + context->renderFlags = FT_RENDER_MODE_LCD; + } else { + context->loadFlags = FT_LOAD_TARGET_LCD_V; + context->renderFlags = FT_RENDER_MODE_LCD_V; + } + } + } + + FcBool fcAutohint = FcFalse; + FcBool fcAutohintSet = (*FcPatternGetBoolPtr)(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch; + + if (logFC && fcAutohintSet) fprintf(stderr, "FC_AUTOHINT(%d) ", fcAutohint); + + if (fcAutohintSet && fcAutohint) { + context->loadFlags |= FT_LOAD_FORCE_AUTOHINT; + } + + FT_LcdFilter fcLCDFilter; + FcBool fcLCDFilterSet = (*FcPatternGetIntegerPtr)(pattern, FC_LCD_FILTER, 0, (int*) &fcLCDFilter) == FcResultMatch; + context->lcdFilter = FT_LCD_FILTER_DEFAULT; + if (fcLCDFilterSet) { + switch (fcLCDFilter) { + case FC_LCD_NONE: + if (logFC) fprintf(stderr, "FC_LCD_NONE"); + context->lcdFilter = FT_LCD_FILTER_NONE; + break; + case FC_LCD_LIGHT: + if (logFC) fprintf(stderr, "FC_LCD_LIGHT"); + context->lcdFilter = FT_LCD_FILTER_LIGHT; + break; + case FC_LCD_LEGACY: + if (logFC) fprintf(stderr, "FC_LCD_LEGACY"); + context->lcdFilter = FT_LCD_FILTER_LEGACY; + break; + case FC_LCD_DEFAULT: + if (logFC) fprintf(stderr, "FC_LCD_DEFAULT"); + break; + default: + if (logFC) fprintf(stderr, "FC_LCD_UNKNOWN"); + ; + } + } + (*FcPatternDestroyPtr)(pattern); + if (logFC) fprintf(stderr, "\n"); +#endif } FT_Library_SetLcdFilter(scalerInfo->library, FT_LCD_FILTER_DEFAULT); } - return errCode; + return 0; } // using same values as for the transformation matrix @@ -634,7 +978,7 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative( f0, f0, f0, f0, f0, f0, f0, f0, f0, f0); } - errCode = setupFTContext(env, font2D, scalerInfo, context); + errCode = setupFTContext(env, font2D, scalerInfo, context, FALSE); if (errCode) { metrics = (*env)->NewObject(env, @@ -917,8 +1261,10 @@ static jlong int error, imageSize; UInt16 width, height, rowBytes; GlyphInfo *glyphInfo; - int renderFlags = FT_LOAD_DEFAULT, target; + int target; FT_GlyphSlot ftglyph; + FT_LcdFilter lcdFilter = FT_LCD_FILTER_NONE; + FT_Library library; FTScalerContext* context = (FTScalerContext*) jlong_to_ptr(pScalerContext); @@ -929,7 +1275,7 @@ static jlong return ptr_to_jlong(getNullGlyphImage()); } - error = setupFTContext(env, font2D, scalerInfo, context); + error = setupFTContext(env, font2D, scalerInfo, context, TRUE); if (error) { invalidateJavaScaler(env, scaler, scalerInfo); return ptr_to_jlong(getNullGlyphImage()); @@ -943,11 +1289,11 @@ static jlong * which did not use freetype. */ if (context->aaType == TEXT_AA_ON && context->fmType == TEXT_FM_ON) { - renderFlags |= FT_LOAD_NO_HINTING; - } + context->loadFlags |= FT_LOAD_NO_HINTING; + } if (!context->useSbits) { - renderFlags |= FT_LOAD_NO_BITMAP; + context->loadFlags |= FT_LOAD_NO_BITMAP; } /* NB: in case of non identity transform @@ -966,9 +1312,9 @@ static jlong } else { target = FT_LOAD_TARGET_LCD_V; } - renderFlags |= target; + context->loadFlags |= target; - error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); + error = FT_Load_Glyph(scalerInfo->face, glyphCode, context->loadFlags); if (error) { //do not destroy scaler yet. //this can be problem of particular context (e.g. with bad transform) @@ -976,6 +1322,8 @@ static jlong } ftglyph = scalerInfo->face->glyph; + library = ftglyph->library; + FT_Library_SetLcdFilter (library, context->lcdFilter); /* apply styles */ if (context->doBold) { /* if bold style */ @@ -993,7 +1341,7 @@ static jlong glyphInfo = getNullGlyphImage(); return ptr_to_jlong(glyphInfo); } - error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); + error = FT_Render_Glyph(ftglyph, context->renderFlags); if (error != 0) { return ptr_to_jlong(getNullGlyphImage()); } @@ -1126,7 +1474,7 @@ Java_sun_font_FreetypeFontScaler_disposeNativeScaler( /* Freetype functions *may* cause callback to java that can use cached values. Make sure our cache is up to date. NB: scaler context is not important at this point, can use NULL. */ - int errCode = setupFTContext(env, font2D, scalerInfo, NULL); + int errCode = setupFTContext(env, font2D, scalerInfo, NULL, FALSE); if (errCode) { return; } @@ -1189,7 +1537,7 @@ Java_sun_font_FreetypeFontScaler_getGlyphCodeNative( /* Freetype functions *may* cause callback to java that can use cached values. Make sure our cache is up to date. Scaler context is not important here, can use NULL. */ - errCode = setupFTContext(env, font2D, scalerInfo, NULL); + errCode = setupFTContext(env, font2D, scalerInfo, NULL, FALSE); if (errCode) { return 0; } @@ -1212,7 +1560,7 @@ static FT_Outline* getFTOutline(JNIEnv* env, jobject font2D, return NULL; } - error = setupFTContext(env, font2D, scalerInfo, context); + error = setupFTContext(env, font2D, scalerInfo, context, TRUE); if (error) { return NULL; } @@ -1654,3 +2002,11 @@ Java_sun_font_FreetypeFontScaler_getGlyphPointNative( return (*env)->NewObject(env, sunFontIDs.pt2DFloatClass, sunFontIDs.pt2DFloatCtr, x, y); } + +void JNI_OnUnload(JavaVM *vm, void *reserved) { + if (libFontConfig != NULL) { +#ifndef _WIN32 + dlclose(libFontConfig); +#endif + } +} From ae6487961313541839cabddf4c1473cddad42b9a Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Thu, 18 Mar 2021 05:19:05 +0700 Subject: [PATCH 091/976] updated JTreg exclude list --- test/jdk/jbProblemList.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/jdk/jbProblemList.txt b/test/jdk/jbProblemList.txt index dc71ee886d3b..452cd8fddbcc 100644 --- a/test/jdk/jbProblemList.txt +++ b/test/jdk/jbProblemList.txt @@ -199,8 +199,8 @@ java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all java/awt/Focus/6378278/InputVerifierTest.java 8198616 macosx-all java/awt/Focus/6382144/EndlessLoopTest.java 8198617 macosx-all java/awt/Focus/6981400/Test1.java 8029675 windows-all,macosx-all -java/awt/Focus/8073453/AWTFocusTransitionTest.java 8136517 macosx-all -java/awt/Focus/8073453/SwingFocusTransitionTest.java 8136517 macosx-all +java/awt/Focus/8073453/AWTFocusTransitionTest.java 8136517 windows-all,macosx-all +java/awt/Focus/8073453/SwingFocusTransitionTest.java 8136517 windows-all,macosx-all java/awt/Focus/6981400/Test3.java 8173264 generic-all java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474,8224055 macosx-all,windows-all @@ -876,9 +876,23 @@ java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all ############################################################################ +# various Windows are created spontaneously during test execution + +javax/swing/JComboBox/6559152/bug6559152.java windows-all +javax/swing/JComboBox/6607130/bug6607130.java windows-all + +javax/swing/JComboBox/4199622/bug4199622.java windows-all +javax/swing/JComboBox/4515752/DefaultButtonTest.java windows-all + +javax/swing/JComboBox/8032878/bug8032878.java windows-all +javax/swing/JComboBox/8057893/bug8057893.java windows-all + # no printer found +java/awt/print/PrinterJob/CheckPrivilege.java generic-all java/awt/print/PrinterJob/ExceptionTest.java generic-all java/awt/print/PrinterJob/ImagePrinting/NullClipARGB.java generic-all +java/awt/print/PrinterJob/LandscapeStackOverflow.java generic-all +java/awt/print/PrinterJob/PaintText.java generic-all java/awt/print/PrinterJob/PrintCrashTest.java generic-all java/awt/print/PrinterJob/PrtException.java generic-all javax/print/attribute/ChromaticityValues.java generic-all From 57959a38df82c8b3e97d52a998d1ee056a6f1023 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 21 Jan 2016 12:33:08 +0300 Subject: [PATCH 092/976] IDEA-148854: AppCode crashes randomly every 15 mins or so (cherry picked from commit 02f9a5fbb4924ff67c8a04c15e490acfcc750003) (cherry picked from commit b8f4b4a9edaa12aaf2b8f11544e76ec4d3122368) --- .../macosx/classes/sun/lwawt/macosx/CAccessible.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java index 779423bc28fc..aaaf45e04b0a 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java @@ -99,7 +99,7 @@ protected synchronized void dispose() { @Override public AccessibleContext getAccessibleContext() { - return accessible.getAccessibleContext(); + return accessible != null ? accessible.getAccessibleContext() : null; } public void addNotificationListeners(Component c) { From d43710b57b863d2077e9ac780c7518ad756135e4 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 22 Mar 2016 21:55:51 +0300 Subject: [PATCH 093/976] IDEA-153474 let JDK detect Xft.dpi value on non-GTK Linux DEs Use the GTK method: https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-get to retrieve "gtk-xft-dpi" integer property of the X settings. Add the property to JDK's GtkEngine & gtk2-interface. Then read the property via GtkEngine from GTK LaF when "gnome.Xft/dpi" is undefined. It's assumed GTK LaF is forcedly installed. (cherry picked from commit e05fc391ae0a3cc389e836441f882c0cf6ab3b99) (cherry picked from commit fd615a5b456750f69fe06a579b38adcaf9a4946b) --- .../share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java | 1 + .../share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java | 4 ++++ src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c | 2 ++ src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h | 1 + 4 files changed, 8 insertions(+) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 1326cee14037..0804747a4263 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -94,6 +94,7 @@ static enum WidgetType { static enum Settings { GTK_FONT_NAME, GTK_ICON_SIZES, + GTK_XFT_DPI, GTK_CURSOR_BLINK, GTK_CURSOR_BLINK_TIME } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java index fa94a57f2e3c..cf81f7501e92 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java @@ -163,6 +163,10 @@ static Font lookupFont(String pangoName) { int dpi = 96; Object value = Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI"); + + if (!(value instanceof Integer)) { + value = GTKEngine.INSTANCE.getSetting(GTKEngine.Settings.GTK_XFT_DPI); + } if (value instanceof Integer) { dpi = ((Integer)value).intValue() / 1024; if (dpi == -1) { diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index 7dba83e9024d..90bc2388f8fe 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -2461,6 +2461,8 @@ static jobject gtk2_get_setting(JNIEnv *env, Setting property) return get_string_property(env, settings, "gtk-font-name"); case GTK_ICON_SIZES: return get_string_property(env, settings, "gtk-icon-sizes"); + case GTK_XFT_DPI: + return get_integer_property(env, settings, "gtk-xft-dpi"); case GTK_CURSOR_BLINK: return get_boolean_property(env, settings, "gtk-cursor-blink"); case GTK_CURSOR_BLINK_TIME: diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h index 33bd4a6cee83..c963d769a66a 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h @@ -403,6 +403,7 @@ typedef enum { GTK_FONT_NAME, GTK_ICON_SIZES, + GTK_XFT_DPI, GTK_CURSOR_BLINK, GTK_CURSOR_BLINK_TIME } Setting; From e508d3900295ae310d20f019fc3aa85191dd38b1 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 9 Sep 2016 19:30:46 +0300 Subject: [PATCH 094/976] JRE-119 [ask if ui scale is enabled natively] (cherry picked from commit 801f45875fd8699edcbda5896210cec191062261) (cherry picked from commit 20edebdefa512dd6d83b37798cc6e724e65c4e06) --- .../native/libawt/windows/awt_DesktopProperties.cpp | 6 ++++++ .../native/libawt/windows/awt_Win32GraphicsDevice.cpp | 8 ++++++++ .../native/libawt/windows/awt_Win32GraphicsDevice.h | 1 + 3 files changed, 15 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index 502433a13aa6..97bb74919401 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -29,6 +29,7 @@ #include "mmsystem.h" #include "jlong.h" #include "awt_DesktopProperties.h" +#include "awt_Win32GraphicsDevice.h" #include "awt_Toolkit.h" #include "sun_awt_windows_WDesktopProperties.h" #include "java_awt_Font.h" @@ -82,6 +83,11 @@ void AwtDesktopProperties::GetWindowsParameters() { } void getInvScale(float &invScaleX, float &invScaleY) { + if (!AwtWin32GraphicsDevice::IsUiScaleEnabled()) { + invScaleX = 1.0f; + invScaleY = 1.0f; + return; + } static int dpiX = -1; static int dpiY = -1; if (dpiX == -1 || dpiY == -1) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp index 74df808ee301..223d1a8d60c2 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp @@ -939,6 +939,14 @@ int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { * End of static deviceIndex-based methods */ +BOOL AwtWin32GraphicsDevice::IsUiScaleEnabled() +{ + return JNU_CallStaticMethodByName(AwtToolkit::GetEnv(), + NULL, + "sun/java2d/SunGraphicsEnvironment", + "isUIScaleEnabled", + "()Z").z; +} const DWORD REQUIRED_FLAGS = ( //Flags which must be set in PFD_SUPPORT_GDI | //in the PixelFormatDescriptor. diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h index 91d5bda76da8..31d700a79040 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h @@ -99,6 +99,7 @@ class AwtWin32GraphicsDevice { static void DisableOffscreenAccelerationForDevice(HMONITOR hMonitor); static HDC GetDCFromScreen(int screen); static int GetScreenFromHMONITOR(HMONITOR mon); + static BOOL IsUiScaleEnabled(); // if not, be dpi-unaware (backward compatible behaviour) static int primaryIndex; static BOOL primaryPalettized; From 7d7c5e0a0ef6cb7a2fbdb7ee96a385d1c9a09162 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 30 Nov 2016 12:32:13 +0300 Subject: [PATCH 095/976] JRE-119 [Dynamically set DPI-awareness level to enable backward compatible HiDPI behavior] Adopted: rely on java.manifest (cherry picked from commit d00cfa4dc62a14a4cf89df9d4c4899970c9fc9e8) Adopted (cherry picked from commit 60be76b7258affcad5450a9f9830c52a17488a10) --- .../sun/awt/Win32GraphicsEnvironment.java | 7 ++++ .../windows/native/libawt/windows/awt.h | 8 +++++ .../libawt/windows/awt_Win32GraphicsEnv.cpp | 33 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java index 04b3f7b77d73..ea006a39a173 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java @@ -51,6 +51,11 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { + // [tav] the values match the native ones + private final static int PROCESS_DPI_UNAWARE = 0; + private final static int PROCESS_SYSTEM_DPI_AWARE = 1; + private final static int PROCESS_PER_MONITOR_DPI_AWARE = 2; + static final float debugScaleX; static final float debugScaleY; @@ -92,6 +97,7 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { public static void initDisplayWrapper() { if (!displayInitialized) { displayInitialized = true; + if (!isUIScaleEnabled()) setProcessDPIAwareness(PROCESS_SYSTEM_DPI_AWARE); initDisplay(); } } @@ -99,6 +105,7 @@ public static void initDisplayWrapper() { public Win32GraphicsEnvironment() { } + private native static void setProcessDPIAwareness(int level); protected native int getNumScreens(); private native int getDefaultScreen(); diff --git a/src/java.desktop/windows/native/libawt/windows/awt.h b/src/java.desktop/windows/native/libawt/windows/awt.h index 708307fc51b5..0aa848ce644f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt.h +++ b/src/java.desktop/windows/native/libawt/windows/awt.h @@ -40,6 +40,14 @@ extern COLORREF DesktopColor2RGB(int colorIndex); +#ifndef PROCESS_DPI_AWARENESS //_WIN32_WINNT_WINBLUE +typedef enum _PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; +#endif + class AwtObject; typedef AwtObject* PDATA; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp index 6c949b564e96..64d602869c7f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp @@ -77,6 +77,28 @@ SetProcessDPIAwareProperty() } } +static void +SetProcessDPIAwareness(PROCESS_DPI_AWARENESS level) +{ + typedef HRESULT(WINAPI SetProcessDpiAwarenessFunc)(int); + static HMODULE hLibSHCoreDll = NULL; + static SetProcessDpiAwarenessFunc *lpSetProcessDpiAwareness = NULL; + + if (hLibSHCoreDll == NULL) { + hLibSHCoreDll = JDK_LoadSystemLibrary("shcore.dll"); + if (hLibSHCoreDll != NULL) { + lpSetProcessDpiAwareness = (SetProcessDpiAwarenessFunc*)GetProcAddress( + hLibSHCoreDll, "SetProcessDpiAwareness"); + } + ::FreeLibrary(hLibSHCoreDll); + hLibSHCoreDll = NULL; + } + + if (lpSetProcessDpiAwareness != NULL) { + lpSetProcessDpiAwareness(level); + } +} + #define DWM_COMP_UNDEFINED (~(TRUE|FALSE)) static int dwmIsCompositionEnabled = DWM_COMP_UNDEFINED; @@ -345,3 +367,14 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsEnvironment_isVistaOS { return IS_WINVISTA; } + +/* + * Class: sun_awt_Win32GraphicsEnvironment + * Method: setProcessDPIAwareness + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsEnvironment_setProcessDPIAwareness + (JNIEnv *env, jclass wgeclass, jint level) +{ + SetProcessDPIAwareness(static_cast(level)); +} \ No newline at end of file From 3a068e093ef7c81a21479c16f90507508c2cf488 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 2 Dec 2016 18:59:49 +0300 Subject: [PATCH 096/976] JRE-119 [use default "sun.java2d.dpiaware=true" to be dpi-aware on Window 7] This lets awt_Win32GraphicsEnv.cpp SetProcessDPIAwareProperty() call Win7 specific ::SetProcessDPIAware() API func. (cherry picked from commit 5e7a766090810d839f4352d06fc2812499d766f8) (cherry picked from commit 7d1d43bfa1a67eb30605e2a0e703404ffd4dc649) --- .../windows/classes/sun/java2d/windows/WindowsFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java index 3c18de432bb0..ca478ca108f6 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java @@ -213,7 +213,7 @@ public Object run() { } offscreenSharingEnabled = getBooleanProp("sun.java2d.offscreenSharing", false); - String dpiOverride = System.getProperty("sun.java2d.dpiaware"); + String dpiOverride = System.getProperty("sun.java2d.dpiaware", "true"); if (dpiOverride != null) { setHighDPIAware = dpiOverride.equalsIgnoreCase("true"); } else { From 493187ad6e8f0d92120a5a39ea308b51b6166cc0 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 6 Dec 2016 15:14:41 +0300 Subject: [PATCH 097/976] JRE-119 [suppress updateGC() for WFileDialogPeer/WPrintDialogPeer] updateGC() is called from WWindowPeer. though it's not applicable to the named dialogs as they don't have native AwtWindow peer required for the method. (cherry picked from commit 72ed9f653177e273b811cfe70c2dba102a8636e4) (cherry picked from commit cec49aaa3811f504f1e3ca3237e48db69928b69d) --- .../windows/classes/sun/awt/windows/WFileDialogPeer.java | 5 +++++ .../windows/classes/sun/awt/windows/WPrintDialogPeer.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java index 7502b667250f..e20951a81fbc 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -70,6 +70,11 @@ boolean checkFilenameFilter(String filename) { super(target); } + @Override + public void updateGC() { + // nop + } + @Override void create(WComponentPeer parent) { this.parent = parent; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java index f2a0042e9cfa..89555f3dc87c 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java @@ -47,6 +47,11 @@ class WPrintDialogPeer extends WWindowPeer implements DialogPeer { super(target); } + @Override + public void updateGC() { + // nop + } + @Override void create(WComponentPeer parent) { this.parent = parent; From f9e7068a96ddf9db7c37dd8f581636d1cb7c12e8 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 31 Jan 2017 20:26:52 +0300 Subject: [PATCH 098/976] JRE-210 JEditorPane may return wrong preferred size as it moves b/w monitors of different scale (cherry picked from commit 6c3087e6bda32ae9b095e069d8bea614502f5c03) (cherry picked from commit adb3a4be166090c2b1befcb2182b9f6f709cd895) with fix for JBR-5300 Change source code and test files to use GPL license --- .../share/classes/java/awt/Component.java | 9 + .../javax/swing/plaf/basic/BasicTextUI.java | 15 ++ .../classes/javax/swing/text/FlowView.java | 9 + .../javax/swing/text/GlyphPainter1.java | 12 ++ .../javax/swing/text/TextLayoutStrategy.java | 17 ++ .../classes/sun/swing/SwingUtilities2.java | 7 + .../JEditorPaneGCSwitchTest.html | 10 ++ .../JEditorPaneGCSwitchTest.java | 167 ++++++++++++++++++ .../JEditorPaneGCSwitchTest_i18n.java | 47 +++++ 9 files changed, 293 insertions(+) create mode 100644 test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.html create mode 100644 test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.java create mode 100644 test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest_i18n.java diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index ad0b87fd3fcb..5098ca9c26c9 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -25,6 +25,7 @@ package java.awt; +import java.awt.geom.AffineTransform; import java.applet.Applet; import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; @@ -1194,7 +1195,15 @@ private boolean updateSelfGraphicsData(GraphicsConfiguration gc) { if (graphicsConfig == gc) { return false; } + + AffineTransform tx = graphicsConfig != null ? graphicsConfig.getDefaultTransform() : new AffineTransform(); + AffineTransform newTx = gc != null ? gc.getDefaultTransform() : new AffineTransform(); graphicsConfig = gc; + if (tx.getScaleX() != newTx.getScaleX() || + tx.getScaleY() != newTx.getScaleY()) + { + firePropertyChange("graphicsContextScaleTransform", tx, newTx); + } ComponentPeer peer = this.peer; if (peer != null) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index ec0fbaf99288..954d9ee6edf8 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1920,9 +1920,24 @@ public final void propertyChange(PropertyChangeEvent evt) { updateCursor(); modelChanged(); } + if (propertyName.equals("graphicsContextScaleTransform")) { + // force re-layout of the document view + forwardPreferenceChangeToView(rootView); + } BasicTextUI.this.propertyChange(evt); } + private void forwardPreferenceChangeToView(View view) { + if (view.getViewCount() == 0) { + // propagate the change up the hierarchy of this leaf view + view.preferenceChanged(null, true, true); + return; + } + for (int i=0; i + + + + +A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + + \ No newline at end of file diff --git a/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.java b/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.java new file mode 100644 index 000000000000..0fd97a209874 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.java @@ -0,0 +1,167 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. + * 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. + */ + +import sun.awt.AWTAccessor; +import javax.swing.*; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.ColorModel; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +/* + * @test + * bug JRE-210 + * @summary JEditorPane's font metrics to honour switching to different GC scale + * @author anton.tarasov + * @requires (os.family == "windows") + * @run main JEditorPaneGCSwitchTest + */ +public class JEditorPaneGCSwitchTest { + static JEditorPane editorPane; + static JFrame frame; + volatile static CountDownLatch latch; + final static Map scale2size = new HashMap<>(2); + + static void initGUI() { + editorPane = new JEditorPane() { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + } + }; + try { + // This HTML text has different bounds when put into GC's with different scales + editorPane.setPage(JEditorPaneGCSwitchTest.class.getResource("JEditorPaneGCSwitchTest.html")); + } catch (IOException e) { + throw new RuntimeException(e); + } + editorPane.addPropertyChangeListener("page", (e) -> { + if (frame != null) frame.dispose(); + frame = new JFrame("frame"); + frame.add(editorPane); + frame.pack(); + frame.setVisible(true); + latch.countDown(); + }); + } + + static void testSize(final float scale) { + // Emulate showing on a device with the provided scale + AWTAccessor.getComponentAccessor().setGraphicsConfiguration(editorPane, new MyGraphicsConfiguration(scale)); + + EventQueue.invokeLater(() -> { + Dimension d = editorPane.getPreferredSize(); + System.out.println(scale + " : " + d); + scale2size.put(scale, d); + latch.countDown(); + }); + } + + static void runSync(Runnable r) { + try { + latch = new CountDownLatch(1); + SwingUtilities.invokeLater(() -> r.run()); + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + /* + * 1. Recreate the editor b/w device switch + */ + runSync(() -> initGUI()); + + runSync(() -> testSize(1f)); + + runSync(() -> initGUI()); + + runSync(() -> testSize(2f)); + + if (scale2size.get(1f).equals(scale2size.get(2f))) { + throw new RuntimeException("Test FAILED: [1] expected different editor size per scale!"); + } + + /* + * 2. Keep the editor shown b/w device switch + */ + scale2size.clear(); + + runSync(() -> initGUI()); + + runSync(() -> testSize(1f)); + + runSync(() -> testSize(2f)); + + frame.dispose(); + + if (scale2size.get(1f).equals(scale2size.get(2f))) { + throw new RuntimeException("Test FAILED: [2] expected different editor size per scale!"); + } + System.out.println("Test PASSED"); + } + + static class MyGraphicsConfiguration extends GraphicsConfiguration { + GraphicsConfiguration delegate; + float scale; + + public MyGraphicsConfiguration(float scale) { + this.delegate = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); + this.scale = scale; + } + + @Override + public GraphicsDevice getDevice() { + return delegate.getDevice(); + } + + @Override + public ColorModel getColorModel() { + return delegate.getColorModel(); + } + + @Override + public ColorModel getColorModel(int transparency) { + return delegate.getColorModel(transparency); + } + + @Override + public AffineTransform getDefaultTransform() { + return AffineTransform.getScaleInstance(scale, scale); + } + + @Override + public AffineTransform getNormalizingTransform() { + return delegate.getNormalizingTransform(); + } + + @Override + public Rectangle getBounds() { + return delegate.getBounds(); + } + } +} diff --git a/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest_i18n.java b/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest_i18n.java new file mode 100644 index 000000000000..1157414c7979 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest_i18n.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. + * 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. + */ + +import sun.awt.AWTAccessor; +import javax.swing.*; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.ColorModel; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +/* + * @test + * bug JRE-210 + * @summary JEditorPane's font metrics to honour switching to different GC scale + * @author anton.tarasov + * @requires (os.family == "windows") + * @run main/othervm -Dsun.font.layoutengine=icu -Di18n=true JEditorPaneGCSwitchTest_i18n + */ +// -Dsun.font.layoutengine=icu is used while Harfbuzz crashes with i18n +public class JEditorPaneGCSwitchTest_i18n extends JPanel { + public static void main(String[] args) throws InterruptedException { + JEditorPaneGCSwitchTest.main(null); + } +} \ No newline at end of file From ad348a12167b809c6498ca4154ba5a479492538b Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 13 Feb 2017 18:35:33 +0300 Subject: [PATCH 099/976] JRE-225 [macos] IDEA hangs on attempt to call getDefaultScreenDevice() from EDT (cherry picked from commit 76aba25) (cherry picked from commit df11dcc97bb5556ac5d0299b773a512b4f0bb5bb) (cherry picked from commit aeea6c1ca3f4a8ead1b34b1ce2e74a9e2e1e5cf9) --- src/java.desktop/share/classes/sun/swing/SwingUtilities2.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java index 92b6dddba279..c7e8213d6758 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java +++ b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java @@ -1251,7 +1251,8 @@ private static FontRenderContext getFRCProperty(JComponent c) { GraphicsConfiguration gc = c.getGraphicsConfiguration(); AffineTransform tx = (gc == null) ? null : gc.getDefaultTransform(); - if (tx == null && !GraphicsEnvironment.isHeadless()) { + // [tav] workaround deadlock on MacOSX until fixed, JRE-226 + if (!FontUtilities.isMacOSX && tx == null && !GraphicsEnvironment.isHeadless()) { tx = GraphicsEnvironment .getLocalGraphicsEnvironment() .getDefaultScreenDevice() From 596cb338f4b3a75859f86ed5f2c2c4fae4871e1f Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 23 Mar 2017 12:01:41 +0300 Subject: [PATCH 100/976] JRE-269 JLabel doesn't scale text HTML fragments. (cherry picked from commit 9ef72b6c3a477e4225f9b98e30fa9190613520e4) (cherry picked from commit c17bc728eefa467acbdcca4cbae1577e78d2c6eb) --- .../javax/swing/plaf/basic/BasicHTML.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java index 4c40dc2d278f..8acc75ee1769 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java @@ -27,6 +27,7 @@ import java.io.*; import java.awt.*; import java.net.URL; +import java.security.PrivilegedAction; import javax.accessibility.AccessibleContext; import javax.swing.*; @@ -46,6 +47,14 @@ * @since 1.3 */ public class BasicHTML { + // Rebase CSS size map to let relative font sizes scale properly. + private final static boolean REBASE_CSS_SIZE_MAP = + java.security.AccessController.doPrivileged( + (PrivilegedAction) + () -> Boolean.getBoolean( + "javax.swing.rebaseCssSizeMap")); + + private final static String JLABEL_USER_CSS_KEY = "javax.swing.JLabel.userStyleSheet"; /** * Constructs a {@code BasicHTML}. @@ -64,6 +73,12 @@ public static View createHTMLView(JComponent c, String html) { BasicEditorKit kit = getFactory(); Document doc = kit.createDefaultDocument(c.getFont(), c.getForeground()); + if (c instanceof JLabel) { + Object userCss = UIManager.getDefaults().get(JLABEL_USER_CSS_KEY); + if (userCss instanceof StyleSheet) { + ((HTMLDocument)doc).getStyleSheet().addStyleSheet((StyleSheet)userCss); + } + } Object base = c.getClientProperty(documentBaseKey); if (base instanceof URL) { ((HTMLDocument)doc).setBase((URL)base); @@ -433,6 +448,10 @@ static class BasicDocument extends HTMLDocument { private void setFontAndColor(Font font, Color fg) { getStyleSheet().addRule(sun.swing.SwingUtilities2. displayPropertiesToCSS(font,fg)); + if (REBASE_CSS_SIZE_MAP && font != null) { + // See: javax.swing.plaf.basic.BasicEditorPaneUI.updateCSS() + if (font != null) getStyleSheet().addRule("BASE_SIZE " + font.getSize()); + } } } From 16b8e7a3a946324899cdf465919487210109440b Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 16 Mar 2021 17:51:38 +0300 Subject: [PATCH 101/976] JRE-309 [windows] on-screen position of a component is not pixel-perfect in user space in JRE-HiDPI mode Adopted: moved to AwtWindow::Reshape (cherry picked from commit 985908cf1092df0cdf7ce4b7df72b05a6e2f71da) --- .../native/libawt/windows/awt_Window.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index fa692c177ea1..7323fcd09c9f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1221,6 +1221,30 @@ void AwtWindow::Reshape(int x, int y, int w, int h) { // monitor, so the WM_DPICHANGED will adjust it for the "target" monitor. int scaleUpAbsX = device == NULL ? x : device->ScaleUpAbsX(x); int scaleUpAbsY = device == NULL ? y : device->ScaleUpAbsY(y); + + // The on-screen location of a component is affected by its toplevel. The toplvel's location in user space + // is represented with some loss of precision - the result of device->ScaleDownXY is ceil'ed. For instance, + // say we have scale 2.0 and a toplevel displayed at [13, 7] in device space. This location is translated to + // [7, 4] in user space. Were the toplevel moved to [14, 8] its location would still be translated to [7, 4] + // in user space. One of the problems caused by this fact is the problem of positioning of an owned window + // relative to its owner (or to the owner's content). Until we have a floating point API for managing Component + // bounds the following workaround is suggested. When a window with non-empty owner is positioned on the device, + // the component of the owner's position coordinate which is lost (as the fractional component) on translation to + // user space should be used to adjust the owned window position. For the example above this would be: + // [13, 7] is translated to [7, 4], the lost component is [1, 1]. So if one wants to display an owned window at, + // say, [11, 9] in user space, which is translated to [22, 18] on the device, the windows' position should be + // adjusted by [1, 1] (the owner's position lost component). Thus the result would be: [22, 18] - [1, 1] = [21, 17]. + // The same formula works for fractional scale factors. + AwtComponent* parent = GetParent(); + if (parent != NULL && (device->GetScaleX() > 1 || device->GetScaleY() > 1)) { + RECT rect; + VERIFY(::GetWindowRect(parent->GetHWnd(), &rect)); + int xOffset = /*ceil'd*/device->ScaleUpAbsX(device->ScaleDownAbsX(rect.left)) - rect.left; + int yOffset = /*ceil'd*/device->ScaleUpAbsY(device->ScaleDownAbsY(rect.top)) - rect.top; + scaleUpAbsX -= xOffset; + scaleUpAbsY -= yOffset; + } + ReshapeNoScale(scaleUpAbsX, scaleUpAbsY, ScaleUpX(w), ScaleUpY(h)); // The window manager may tweak the size for different reasons, so try // to make sure our window has the correct size in the user's space. From 44a7d455494d7bb9b8b69d035566268892d2f8a7 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 16 Mar 2021 18:02:03 +0300 Subject: [PATCH 102/976] IDEA-172422 Popup at the wrong place on the second monitor (new hidpi) Adopted: moved to AwtWindow::Reshape (cherry picked from commit 11a0911d653444391ed79996d97d9448dbfd48ac) --- .../windows/native/libawt/windows/awt_Window.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 7323fcd09c9f..15d21f01572c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1241,8 +1241,16 @@ void AwtWindow::Reshape(int x, int y, int w, int h) { VERIFY(::GetWindowRect(parent->GetHWnd(), &rect)); int xOffset = /*ceil'd*/device->ScaleUpAbsX(device->ScaleDownAbsX(rect.left)) - rect.left; int yOffset = /*ceil'd*/device->ScaleUpAbsY(device->ScaleDownAbsY(rect.top)) - rect.top; - scaleUpAbsX -= xOffset; - scaleUpAbsY -= yOffset; + int newX = scaleUpAbsX - xOffset; + int newY = scaleUpAbsY - yOffset; + + // Check the toplevel is not going to be moved to another screen. + ::SetRect(&rect, newX, newY, newX + w, newY + h); + HMONITOR hmon = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); + if (hmon != NULL && AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hmon) == device->GetDeviceIndex()) { + scaleUpAbsX = newX; + scaleUpAbsY = newY; + } } ReshapeNoScale(scaleUpAbsX, scaleUpAbsY, ScaleUpX(w), ScaleUpY(h)); From 4878b99ad4789783cf4f72255ef0e47f54d3d9dd Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 23 May 2017 17:42:17 +0300 Subject: [PATCH 103/976] JRE-373 [macos] nativeCreateNSWindow deadlocks with a11y (cherry picked from commit 72c77a992bbf1b95b82ffc08cb2f4f3bc36b3657) (cherry picked from commit aa09fa2c858208afc14770f03f371d1702e61579) --- .../sun/lwawt/macosx/CPlatformWindow.java | 40 +++-- .../classes/sun/lwawt/macosx/LWCToolkit.java | 167 ++++++++++++++++-- 2 files changed, 174 insertions(+), 33 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 1be76db3acdf..1d4e80f8fb73 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -53,6 +53,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.Callable; import javax.swing.JRootPane; import javax.swing.RootPaneContainer; @@ -344,26 +345,29 @@ public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner } else { bounds = _peer.constrainBounds(_target.getBounds()); } - AtomicLong ref = new AtomicLong(); - contentView.execute(viewPtr -> { - boolean hasOwnerPtr = false; - - if (owner != null) { - hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> { - ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits, - bounds.x, bounds.y, - bounds.width, bounds.height)); - return 1; - }); - } + long nativeWindowPtr = LWCToolkit.SelectorPerformer.perform(() -> { + AtomicLong ref = new AtomicLong(); + contentView.execute(viewPtr -> { + boolean hasOwnerPtr = false; + + if (owner != null) { + hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> { + ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits, + bounds.x, bounds.y, + bounds.width, bounds.height)); + return 1; + }); + } - if (!hasOwnerPtr) { - ref.set(nativeCreateNSWindow(viewPtr, 0, - styleBits, bounds.x, bounds.y, - bounds.width, bounds.height)); - } + if (!hasOwnerPtr) { + ref.set(nativeCreateNSWindow(viewPtr, 0, + styleBits, bounds.x, bounds.y, + bounds.width, bounds.height)); + } + }); + return ref.get(); }); - setPtr(ref.get()); + setPtr(nativeWindowPtr); if (peer != null) { // Not applicable to CWarningWindow peer.setTextured(IS(TEXTURED, styleBits)); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index d430825bb856..8d95b563a2b5 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -87,16 +87,13 @@ import java.lang.reflect.UndeclaredThrowableException; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.concurrent.Callable; - +import java.security.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.net.MalformedURLException; import javax.swing.UIManager; import com.apple.laf.AquaMenuBarUI; @@ -710,6 +707,139 @@ public T getResult() throws Exception { } } + /** + * Performs a wrapped native selector on the main thread, waiting on EDT, preventing the threads from a deadlock. + */ + public static class SelectorPerformer { + private ExecutorService executor; + // every perform() pushes a queue of invocations + private Stack> invocations = new Stack<>(); + + // invocations should be dispatched on proper EDT (per AppContext) + private static final Map edt2performer = new ConcurrentHashMap<>(); + + private static final int WAIT_LIMIT_SECONDS = 5; + + private SelectorPerformer() {} + + /** + * Performs the selector wrapped in the callable. The selector should be executed via [JNFRunLoop performOnMainThreadWaiting:YES ...] + * on the native side so that the native doAWTRunLoop, which is run in [JNFRunLoop javaRunLoopMode], accepts it. + * The callable wrapper should not call any Java code which would normally be called on EDT. + *

+ * If the main thread posts invocation events caused by the selector, those events are intercepted and dispatched on EDT out of order. + *

+ * When called on non-EDT, the method performs the selector in place. The method is reentrant. + * + * @param selector the native selector wrapper + * @param the selector return type + * @return the selector result + */ + public static T perform(Callable selector) { + if (selector == null) return null; + + if (EventQueue.isDispatchThread()) { + SelectorPerformer performer = getInstance(Thread.currentThread()); + if (performer != null) { + return performer.performImpl(selector); + } + } + // fallback to default + try { + return selector.call(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private T performImpl(Callable selector) { + assert EventQueue.isDispatchThread(); + if (executor == null) { + // init on EDT + executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + Executors.privilegedThreadFactory()); + } + LinkedBlockingQueue currentQueue; + synchronized (invocations) { + invocations.push(currentQueue = new LinkedBlockingQueue<>()); + } + + FutureTask task = new FutureTask(selector) { + @Override + protected void done() { + synchronized (invocations) { + // Done with the current queue, wake it up. + invocations.pop().add(new InvocationEvent(executor, () -> {})); + } + } + }; + executor.execute(task); + + try { + while (!task.isDone() || !currentQueue.isEmpty()) { + InvocationEvent event = currentQueue.poll(WAIT_LIMIT_SECONDS, TimeUnit.SECONDS); + if (event == null) { + new RuntimeException("Waiting for the invocation event timed out").printStackTrace(); + break; + } + event.dispatch(); + } + return task.isDone() ? task.get() : null; + + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Checks if there's an active SelectorPerformer corresponding to the invocation's AppContext, + * adds the invocation to the SelectorPerformer's queue and returns true. + * Otherwise does nothing and returns false. + */ + public static boolean offer(InvocationEvent invocation) { + Object source = invocation.getSource(); + + SelectorPerformer performer = (source instanceof Component) ? + getInstance((Component)source) : + getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue()); + + if (performer == null) return false; + + synchronized (performer.invocations) { + if (!performer.invocations.isEmpty()) { + performer.invocations.peek().add(invocation); + return true; + } + } + return false; + } + + private static SelectorPerformer getInstance(Component comp) { + if (comp == null) return null; + + AppContext appContext = SunToolkit.targetToAppContext(comp); + if (appContext == null) return null; + + return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY)); + } + + private static SelectorPerformer getInstance(EventQueue eq) { + if (eq == null) return null; + + return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq)); + } + + private static SelectorPerformer getInstance(Thread edt) { + if (edt == null) return null; + + return edt2performer.computeIfAbsent(edt, key -> new SelectorPerformer()); + } + } + /** * Kicks an event over to the appropriate event queue and waits for it to * finish To avoid deadlocking, we manually run the NSRunLoop while waiting @@ -733,12 +863,19 @@ public static void invokeAndWait(Runnable runnable, Component component) }, true); - AppContext appContext = SunToolkit.targetToAppContext(component); - SunToolkit.postEvent(appContext, invocationEvent); - // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock - SunToolkit.flushPendingEvents(appContext); - doAWTRunLoop(mediator, false); + if (!SelectorPerformer.offer(invocationEvent)) { + if (component != null) { + AppContext appContext = SunToolkit.targetToAppContext(component); + SunToolkit.postEvent(appContext, invocationEvent); + // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock + SunToolkit.flushPendingEvents(appContext); + } else { + // This should be the equivalent to EventQueue.invokeAndWait + ((LWCToolkit) Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); + } + } + doAWTRunLoop(mediator, false); checkException(invocationEvent); } From b2d795866344e4b0f0c8838b6f19af1bb0ddfaeb Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 31 May 2017 12:12:35 +0300 Subject: [PATCH 104/976] JRE-382 Three AWT-tests become hanging starting since master-875 (cherry picked from commit 7d492101db8fcbb3d285fd8e9669f74b0e0fce8f) (cherry picked from commit b965f85c1b08513bbcd1480f044e6f75b5b8d9e1) --- .../macosx/classes/sun/lwawt/macosx/LWCToolkit.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 8d95b563a2b5..d4ffba2a85e1 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -760,7 +760,16 @@ private T performImpl(Callable selector) { executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), - Executors.privilegedThreadFactory()); + new ThreadFactory() { + private ThreadFactory factory = Executors.privilegedThreadFactory(); + @Override + public Thread newThread(Runnable r) { + Thread t = factory.newThread(r); + t.setDaemon(true); + t.setName("AWT-SelectorPerformer " + t.getName()); + return t; + } + }); } LinkedBlockingQueue currentQueue; synchronized (invocations) { From 4231f575370450ce515fc2c26369db28661228e3 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 10 Nov 2017 20:23:13 +0300 Subject: [PATCH 105/976] JRE-573 [windows] window client area bounds mismatch Apply only WmEraseBkgnd (cherry picked from commit afa68f7ad6440303c6417be3f675b1c4644b6014) (cherry picked from commit 0651b45e13da6ee92e6c10cd6ace28f32c70e1bc) --- .../windows/native/libawt/windows/awt_Window.cpp | 14 ++++++++++++++ .../windows/native/libawt/windows/awt_Window.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 15d21f01572c..95772b3a4388 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1836,6 +1836,20 @@ void AwtWindow::WmDPIChanged(const LPARAM &lParam) { CheckIfOnNewScreen(true); } +MsgRouting AwtWindow::WmEraseBkgnd(HDC hDC, BOOL& didErase) +{ + if (!IsUndecorated()) { + // [tav] When an undecorated window is shown nothing is actually displayed + // until something is drawn in it. In order to prevent blinking, the background + // is not erased for such windows. + RECT rc; + ::GetClipBox(hDC, &rc); + ::FillRect(hDC, &rc, this->GetBackgroundBrush()); + } + didErase = TRUE; + return mrConsume; +} + /* * Override AwtComponent's move handling to first update the * java AWT target's position fields directly, since Windows diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.h b/src/java.desktop/windows/native/libawt/windows/awt_Window.h index 5b0b8ba2ae49..90f7e0386bef 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h @@ -168,6 +168,7 @@ class AwtWindow : public AwtCanvas { virtual MsgRouting WmClose(); virtual MsgRouting WmDestroy(); virtual MsgRouting WmShowWindow(BOOL show, UINT status); + virtual MsgRouting WmEraseBkgnd(HDC hDC, BOOL& didErase); virtual MsgRouting WmGetMinMaxInfo(LPMINMAXINFO lpmmi); virtual MsgRouting WmMove(int x, int y); virtual MsgRouting WmSize(UINT type, int w, int h); From a9758532754feff1cf383ea8b2da310fade5d4ee Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 30 Nov 2017 13:37:01 +0300 Subject: [PATCH 106/976] JRE-577 Goland 18 displays out of memory (cherry picked from commit 2daaf21e420d4af15d3b1bfeb3f896074bea1e61) (cherry picked from commit 9ea20119485db6abe1340323bb513de87894e3b2) with fix for JBR-5300 Change source code and test files to use GPL license --- .../classes/sun/awt/SunDisplayChanger.java | 80 ++++------- .../SunDisplayChangerLeakTest.java | 124 ++++++++++++++++++ 2 files changed, 149 insertions(+), 55 deletions(-) create mode 100644 test/jdk/java/awt/Toolkit/SunDisplayChangerLeakTest/SunDisplayChangerLeakTest.java diff --git a/src/java.desktop/share/classes/sun/awt/SunDisplayChanger.java b/src/java.desktop/share/classes/sun/awt/SunDisplayChanger.java index 8cab1acfb723..ef65c10c87f8 100644 --- a/src/java.desktop/share/classes/sun/awt/SunDisplayChanger.java +++ b/src/java.desktop/share/classes/sun/awt/SunDisplayChanger.java @@ -26,13 +26,8 @@ package sun.awt; import java.awt.IllegalComponentStateException; -import java.util.Collections; -import java.util.Iterator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; +import java.util.*; +import java.util.function.Consumer; import sun.util.logging.PlatformLogger; @@ -105,38 +100,7 @@ public void notifyListeners() { if (log.isLoggable(PlatformLogger.Level.FINEST)) { log.finest("notifyListeners"); } - // This method is implemented by making a clone of the set of listeners, - // and then iterating over the clone. This is because during the course - // of responding to a display change, it may be appropriate for a - // DisplayChangedListener to add or remove itself from a SunDisplayChanger. - // If the set itself were iterated over, rather than a clone, it is - // trivial to get a ConcurrentModificationException by having a - // DisplayChangedListener remove itself from its list. - // Because all display change handling is done on the event thread, - // synchronization provides no protection against modifying the listener - // list while in the middle of iterating over it. -bchristi 7/10/2001 - - Set cloneSet; - - synchronized(listeners) { - cloneSet = new HashSet(listeners.keySet()); - } - - for (DisplayChangedListener current : cloneSet) { - try { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("displayChanged for listener: " + current); - } - current.displayChanged(); - } catch (IllegalComponentStateException e) { - // This DisplayChangeListener is no longer valid. Most - // likely, a top-level window was dispose()d, but its - // Java objects have not yet been garbage collected. In any - // case, we no longer need to track this listener, though we - // do need to remove it from the original list, not the clone. - listeners.remove(current); - } - } + notifyChanged(DisplayChangedListener::displayChanged, "displayChanged"); } /* @@ -147,28 +111,34 @@ public void notifyPaletteChanged() { if (log.isLoggable(PlatformLogger.Level.FINEST)) { log.finest("notifyPaletteChanged"); } - // This method is implemented by making a clone of the set of listeners, - // and then iterating over the clone. This is because during the course - // of responding to a display change, it may be appropriate for a - // DisplayChangedListener to add or remove itself from a SunDisplayChanger. - // If the set itself were iterated over, rather than a clone, it is - // trivial to get a ConcurrentModificationException by having a - // DisplayChangedListener remove itself from its list. - // Because all display change handling is done on the event thread, - // synchronization provides no protection against modifying the listener - // list while in the middle of iterating over it. -bchristi 7/10/2001 + notifyChanged(DisplayChangedListener::paletteChanged, "paletteChanged"); + } - Set cloneSet; + private void notifyChanged(Consumer callback, String callbackName) { + // This method is implemented by making a clone of the set of listeners, + // and then iterating over the clone. This is because during the course + // of responding to a display change, it may be appropriate for a + // DisplayChangedListener to add or remove itself from a SunDisplayChanger. + // If the set itself were iterated over, rather than a clone, it is + // trivial to get a ConcurrentModificationException by having a + // DisplayChangedListener remove itself from its list. + // Because all display change handling is done on the event thread, + // synchronization provides no protection against modifying the listener + // list while in the middle of iterating over it. -bchristi 7/10/2001 + + // Preserve "weakness" of the original map to avoid OOME. + WeakHashMap cloneMap; - synchronized (listeners) { - cloneSet = new HashSet(listeners.keySet()); + synchronized(listeners) { + cloneMap = new WeakHashMap<>(listeners); } - for (DisplayChangedListener current : cloneSet) { + + for (DisplayChangedListener current : cloneMap.keySet()) { try { if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("paletteChanged for listener: " + current); + log.finest(callbackName + " for listener: " + current); } - current.paletteChanged(); + callback.accept(current); } catch (IllegalComponentStateException e) { // This DisplayChangeListener is no longer valid. Most // likely, a top-level window was dispose()d, but its diff --git a/test/jdk/java/awt/Toolkit/SunDisplayChangerLeakTest/SunDisplayChangerLeakTest.java b/test/jdk/java/awt/Toolkit/SunDisplayChangerLeakTest/SunDisplayChangerLeakTest.java new file mode 100644 index 000000000000..0910eb9de540 --- /dev/null +++ b/test/jdk/java/awt/Toolkit/SunDisplayChangerLeakTest/SunDisplayChangerLeakTest.java @@ -0,0 +1,124 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. + * 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. + */ +import sun.awt.DisplayChangedListener; +import sun.awt.image.BufferedImageGraphicsConfig; +import sun.awt.image.SunVolatileImage; +import sun.java2d.SunGraphicsEnvironment; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; +import java.util.*; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +/* + https://youtrack.jetbrains.com/issue/JRE-577 + @test + @summary SunDisplayChanger should not prevent listeners from gc'ing + @author anton.tarasov + @run main/othervm -Xmx64m -Dswing.bufferPerWindow=true SunDisplayChangerLeakTest +*/ +public class SunDisplayChangerLeakTest { + static int frameCountDown = 20; + static final Map STRONG_MAP = new HashMap<>(); + static final GraphicsConfiguration BI_GC = BufferedImageGraphicsConfig.getConfig(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)); + + static volatile boolean passed; + + /** + * Shows a frame, then refs its back buffer. + */ + static void showFrame(CountDownLatch latch) { + JFrame frame = new JFrame("frame") { + @Override + public VolatileImage createVolatileImage(int w, int h) { + // Back the frame buffer by BufferedImage so that it's allocated in RAM + VolatileImage img = new SunVolatileImage(BI_GC, w, h, Transparency.TRANSLUCENT, new ImageCapabilities(false)); + STRONG_MAP.put(img, null); + + EventQueue.invokeLater(() -> { + dispose(); // release the frame buffer + latch.countDown(); + }); + return img; + } + }; + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws InterruptedException { + while(--frameCountDown >= 0) { + CountDownLatch latch = new CountDownLatch(1); + EventQueue.invokeLater(() -> showFrame(latch)); + latch.await(); + } + + SunGraphicsEnvironment env = (SunGraphicsEnvironment)SunGraphicsEnvironment.getLocalGraphicsEnvironment(); + DisplayChangedListener strongRef; + env.addDisplayChangedListener(strongRef = new DisplayChangedListener() { + @Override + public void displayChanged() { + // Now we're in the process of iterating over a local copy of the DisplayChangedListener's internal map. + // Let's force OOME and make sure the local copy doesn't prevent the listeners from gc'ing. + + int strongSize = STRONG_MAP.size(); + System.out.println("strong size: " + strongSize); + + // Release the images + Map weakMap = new WeakHashMap<>(STRONG_MAP); + STRONG_MAP.clear(); + + List garbage = new ArrayList<>(); + try { + while (true) { + garbage.add(new int[1000000]); + } + } catch (OutOfMemoryError e) { + garbage.clear(); + System.out.println("OutOfMemoryError"); + } + int weakSize = weakMap.size(); + System.out.println("weak size: " + weakSize); + + passed = weakSize < strongSize; + } + + @Override + public void paletteChanged() { + System.out.println(new int[1000]); + } + }); + assert strongRef != null; // make it "used" to please javac + + // call the above listener + env.displayChanged(); + + if (!passed) throw new RuntimeException("Test FAILED"); + + System.out.println("Test PASSED"); + } +} From 04f5bf9b5ffeb0351ff0ad5154bf71ff413f38de Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 16 Mar 2021 19:53:13 +0300 Subject: [PATCH 107/976] JRE-596 [windows] popup positioning is broken with JRE-573 Adopted: moved to AwtWindow::Reshape (cherry picked from commit c5cc28d85d6f3284cac1144d4c08beea51a381b0) --- .../native/libawt/windows/awt_Window.cpp | 99 ++++++++++++++----- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 95772b3a4388..129b34a8d07e 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1222,34 +1222,45 @@ void AwtWindow::Reshape(int x, int y, int w, int h) { int scaleUpAbsX = device == NULL ? x : device->ScaleUpAbsX(x); int scaleUpAbsY = device == NULL ? y : device->ScaleUpAbsY(y); - // The on-screen location of a component is affected by its toplevel. The toplvel's location in user space - // is represented with some loss of precision - the result of device->ScaleDownXY is ceil'ed. For instance, - // say we have scale 2.0 and a toplevel displayed at [13, 7] in device space. This location is translated to - // [7, 4] in user space. Were the toplevel moved to [14, 8] its location would still be translated to [7, 4] - // in user space. One of the problems caused by this fact is the problem of positioning of an owned window - // relative to its owner (or to the owner's content). Until we have a floating point API for managing Component - // bounds the following workaround is suggested. When a window with non-empty owner is positioned on the device, - // the component of the owner's position coordinate which is lost (as the fractional component) on translation to - // user space should be used to adjust the owned window position. For the example above this would be: - // [13, 7] is translated to [7, 4], the lost component is [1, 1]. So if one wants to display an owned window at, - // say, [11, 9] in user space, which is translated to [22, 18] on the device, the windows' position should be - // adjusted by [1, 1] (the owner's position lost component). Thus the result would be: [22, 18] - [1, 1] = [21, 17]. - // The same formula works for fractional scale factors. + int usrX = x; + int usrY = y; + + // [tav] Handle the fact that an owned window is most likely positioned relative to its owner, and it may + // require pixel-perfect alignment. For that, compensate rounding errors (caused by converting from the device + // space to the integer user space and back) for the owner's origin and for the owner's client area origin + // (see Window::GetAlignedInsets). AwtComponent* parent = GetParent(); if (parent != NULL && (device->GetScaleX() > 1 || device->GetScaleY() > 1)) { - RECT rect; - VERIFY(::GetWindowRect(parent->GetHWnd(), &rect)); - int xOffset = /*ceil'd*/device->ScaleUpAbsX(device->ScaleDownAbsX(rect.left)) - rect.left; - int yOffset = /*ceil'd*/device->ScaleUpAbsY(device->ScaleDownAbsY(rect.top)) - rect.top; - int newX = scaleUpAbsX - xOffset; - int newY = scaleUpAbsY - yOffset; + RECT parentInsets; + parent->GetInsets(&parentInsets); + // Convert the owner's client area origin to user space + int parentInsetsUsrX = device->ScaleDownX(parentInsets.left); + int parentInsetsUsrY = device->ScaleDownY(parentInsets.top); + + RECT parentRect; + VERIFY(::GetWindowRect(parent->GetHWnd(), &parentRect)); + // Convert the owner's origin to user space + int parentUsrX = device->ScaleDownAbsX(parentRect.left); + int parentUsrY = device->ScaleDownAbsY(parentRect.top); + + // Calc the offset from the owner's client area in user space + int offsetUsrX = usrX - parentUsrX - parentInsetsUsrX; + int offsetUsrY = usrY - parentUsrY - parentInsetsUsrY; + + // Convert the offset to device space + int offsetDevX = device->ScaleUpX(offsetUsrX); + int offsetDevY = device->ScaleUpY(offsetUsrY); + + // Finally calc the window's location based on the frame's and its insets system numbers. + int devX = parentRect.left + parentInsets.left + offsetDevX; + int devY = parentRect.top + parentInsets.top + offsetDevY; // Check the toplevel is not going to be moved to another screen. - ::SetRect(&rect, newX, newY, newX + w, newY + h); - HMONITOR hmon = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); + ::SetRect(&parentRect, devX, devY, devX + w, devY + h); + HMONITOR hmon = ::MonitorFromRect(&parentRect, MONITOR_DEFAULTTONEAREST); if (hmon != NULL && AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hmon) == device->GetDeviceIndex()) { - scaleUpAbsX = newX; - scaleUpAbsY = newY; + scaleUpAbsX = devX; + scaleUpAbsY = devY; } } @@ -1878,8 +1889,46 @@ MsgRouting AwtWindow::WmMove(int x, int y) RECT rect; ::GetWindowRect(GetHWnd(), &rect); - (env)->SetIntField(target, AwtComponent::xID, ScaleDownAbsX(rect.left)); - (env)->SetIntField(target, AwtComponent::yID, ScaleDownAbsY(rect.top)); + // [tav] Convert x/y to user space, asymmetrically to AwtWindow::Reshape() + POINT pt = {rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2}; + Devices::InstanceAccess devices; + HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); + AwtWin32GraphicsDevice *device = devices->GetDevice(screen); + + int usrX = ScaleDownAbsX(rect.left); + int usrY = ScaleDownAbsY(rect.top); + + AwtComponent* parent = GetParent(); + if (parent != NULL && (device->GetScaleX() > 1 || device->GetScaleY() > 1)) { + + RECT parentInsets; + parent->GetInsets(&parentInsets); + // Convert the owner's client area origin to user space + int parentInsetsUsrX = device->ScaleDownX(parentInsets.left); + int parentInsetsUsrY = device->ScaleDownY(parentInsets.top); + + RECT parentRect; + VERIFY(::GetWindowRect(parent->GetHWnd(), &parentRect)); + // Convert the owner's origin to user space + int parentUsrX = device->ScaleDownAbsX(parentRect.left); + int parentUsrY = device->ScaleDownAbsY(parentRect.top); + + // Calc the offset from the owner's client area in device space + int offsetDevX = rect.left - parentRect.left - parentInsets.left; + int offsetDevY = rect.top - parentRect.top - parentInsets.top; + + // Convert the offset to user space + int offsetUsrX = device->ScaleDownX(offsetDevX); + int offsetUsrY = device->ScaleDownY(offsetDevY); + + // Finally calc the window's location based on the frame's and its insets user space values. + usrX = parentUsrX + parentInsetsUsrX + offsetUsrX; + usrY = parentUsrY + parentInsetsUsrY + offsetUsrY; + } + + (env)->SetIntField(target, AwtComponent::xID, usrX); + (env)->SetIntField(target, AwtComponent::yID, usrY); SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED); env->DeleteLocalRef(target); From e4febb6299ba29941344e3e2e1fac0a62dd38979 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 16 Mar 2021 20:41:23 +0300 Subject: [PATCH 108/976] JRE-604 [fps] frame's client area is one pixel beneath frame's borders Adopted. (cherry picked from commit ef2870ee38cd4360ea985f6c7d937a7b6ef3ecdc) --- .../classes/java/awt/peer/WindowPeer.java | 7 + .../classes/javax/swing/RepaintManager.java | 96 ++++++++- .../classes/sun/java2d/SunGraphics2D.java | 5 +- .../classes/sun/awt/windows/WWindowPeer.java | 8 + .../native/libawt/windows/awt_Window.cpp | 12 ++ .../native/libawt/windows/awt_Window.h | 2 + .../hidpi/ClientAreaOriginWindowsTest.java | 193 ++++++++++++++++++ 7 files changed, 316 insertions(+), 7 deletions(-) create mode 100644 test/jdk/java/awt/hidpi/ClientAreaOriginWindowsTest.java diff --git a/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java b/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java index 07013a10bd03..fcfb6d2a899a 100644 --- a/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java +++ b/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java @@ -119,6 +119,13 @@ public interface WindowPeer extends ContainerPeer { */ void repositionSecurityWarning(); + /** + * Returns the system insets (in the scale of the Window device) when available. + * + * @return the system insets or null + */ + default Insets getSysInsets() { return null; } + /** * Requests a GC that best suits this Window. The returned GC may differ * from the requested GC passed as the argument to this method. This method diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index eb696a7b489d..775aa1d95d2e 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -27,7 +27,10 @@ import java.awt.*; import java.awt.event.*; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.awt.image.VolatileImage; +import java.awt.peer.WindowPeer; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; @@ -1624,11 +1627,65 @@ public void doubleBufferingChanged(JRootPane rootPane) { */ protected void paintDoubleBuffered(JComponent c, Image image, Graphics g, int clipX, int clipY, - int clipW, int clipH) { - if (image instanceof VolatileImage && isPixelsCopying(c, g)) { - paintDoubleBufferedFPScales(c, image, g, clipX, clipY, clipW, clipH); - } else { - paintDoubleBufferedImpl(c, image, g, clipX, clipY, clipW, clipH); + int clipW, int clipH) + { + SunGraphics2D sg = (SunGraphics2D)g.create(); + try { + // [tav] For the scaling graphics we need to compensate the toplevel insets rounding error + // to place [0, 0] of the client area in its correct device pixel. + if (sg.transformState == SunGraphics2D.TRANSFORM_TRANSLATESCALE) { + Point2D err = getInsetsRoundingError(sg); + double errX = err.getX(); + double errY = err.getY(); + if (errX != 0 || errY != 0) { + // save the current tx + AffineTransform tx = sg.transform; + + // translate the constrain + Region constrainClip = sg.constrainClip; + Shape usrClip = sg.usrClip; + if (constrainClip != null) { + // SunGraphics2D.constrain(..) rounds down x/y, so to compensate we need to round up + int _errX = (int)Math.ceil(errX); + int _errY = (int)Math.ceil(errY); + if ((_errX | _errY) != 0) { + // drop everything to default + sg.constrainClip = null; + sg.usrClip = null; + sg.clipState = SunGraphics2D.CLIP_DEVICE; + sg.transform = new AffineTransform(); + sg.setDevClip(sg.getSurfaceData().getBounds()); + + Region r = constrainClip.getTranslatedRegion(_errX, _errY); + sg.constrain(r.getLoX(), r.getLoY(), r.getWidth(), r.getHeight()); + } + } + + // translate usrClip + if (usrClip != null) { + if (usrClip instanceof Rectangle2D) { + Rectangle2D u = (Rectangle2D)usrClip; + u.setRect(u.getX() + errX, u.getY() + errY, u.getWidth(), u.getHeight()); + } else { + usrClip = AffineTransform.getTranslateInstance(errX, errY).createTransformedShape(usrClip); + } + sg.transform = new AffineTransform(); + sg.setClip(usrClip); // constrain clip is already valid + } + + // finally translate the tx + AffineTransform newTx = AffineTransform.getTranslateInstance(errX - sg.constrainX, errY - sg.constrainY); + newTx.concatenate(tx); + sg.setTransform(newTx); + } + } + if (image instanceof VolatileImage && isPixelsCopying(c, g)) { + paintDoubleBufferedFPScales(c, image, sg, clipX, clipY, clipW, clipH); + } else { + paintDoubleBufferedImpl(c, image, sg, clipX, clipY, clipW, clipH); + } + } finally { + sg.dispose(); } } @@ -1673,6 +1730,35 @@ private void paintDoubleBufferedImpl(JComponent c, Image image, } } + /** + * For the scaling graphics and a decorated toplevel as the destination, + * calculates the rounding error of the toplevel insets. + * + * @return the left/top insets rounding error, in device space + */ + private static Point2D getInsetsRoundingError(SunGraphics2D g) { + Point2D.Double err = new Point2D.Double(0, 0); + if (g.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { + Object dst = g.getSurfaceData().getDestination(); + if (dst instanceof Frame && !((Frame)dst).isUndecorated() || + dst instanceof Dialog && !((Dialog)dst).isUndecorated()) + { + Window wnd = (Window)dst; + WindowPeer peer = (WindowPeer)AWTAccessor.getComponentAccessor().getPeer(wnd); + Insets sysInsets = peer != null ? peer.getSysInsets() : null; + if (sysInsets != null) { + Insets insets = wnd.getInsets(); + // insets.left/top is a scaled down rounded value + // insets.left/top * tx.scale is a scaled up value (which contributes to graphics translate) + // sysInsets.left/top is the precise system value + err.x = sysInsets.left - insets.left * g.transform.getScaleX(); + err.y = sysInsets.top - insets.top * g.transform.getScaleY(); + } + } + } + return err; + } + private void paintDoubleBufferedFPScales(JComponent c, Image image, Graphics g, int clipX, int clipY, int clipW, int clipH) { diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 86666b1f894b..bec43b3e9037 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -370,8 +370,9 @@ public void constrain(int x, int y, int w, int h, Region region) { // changes parameters according to the current scale and translate. final double scaleX = transform.getScaleX(); final double scaleY = transform.getScaleY(); - x = constrainX = (int) transform.getTranslateX(); - y = constrainY = (int) transform.getTranslateY(); + // [tav] rounding down affects aligning by insets in RepaintManager.paintDoubleBuffered + x = constrainX = (int)Math.floor(transform.getTranslateX()); + y = constrainY = (int)Math.floor(transform.getTranslateY()); w = Region.dimAdd(x, Region.clipScale(w, scaleX)); h = Region.dimAdd(y, Region.clipScale(h, scaleY)); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index 7b82229c02cd..62e45e95dec4 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -110,6 +110,8 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, */ private WindowListener windowListener; + private Insets sysInsets; // set from native updateInsets + /** * Initialize JNI field IDs */ @@ -204,6 +206,7 @@ public void setResizable(boolean resizable) { void initialize() { super.initialize(); + sysInsets = (Insets)insets_.clone(); updateInsets(insets_); if (!((Window) target).isFontSet()) { @@ -317,6 +320,11 @@ final void syncBounds() { // state. native void updateInsets(Insets i); + @Override + public Insets getSysInsets() { + return (Insets)sysInsets.clone(); + } + static native int getSysMinWidth(); static native int getSysMinHeight(); static native int getSysIconWidth(); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 129b34a8d07e..720daa81d605 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -164,6 +164,7 @@ jfieldID AwtWindow::securityWarningHeightID; jfieldID AwtWindow::windowTypeID; jmethodID AwtWindow::notifyWindowStateChangedMID; +jfieldID AwtWindow::sysInsetsID; jmethodID AwtWindow::getWarningStringMID; jmethodID AwtWindow::calculateSecurityWarningPositionMID; @@ -1505,12 +1506,21 @@ BOOL AwtWindow::UpdateInsets(jobject insets) jobject peerInsets = (env)->GetObjectField(peer, AwtPanel::insets_ID); DASSERT(!safe_ExceptionOccurred(env)); + jobject peerSysInsets = (env)->GetObjectField(peer, AwtWindow::sysInsetsID); + DASSERT(!safe_ExceptionOccurred(env)); + if (peerInsets != NULL) { // may have been called during creation (env)->SetIntField(peerInsets, AwtInsets::topID, ScaleDownY(m_insets.top)); (env)->SetIntField(peerInsets, AwtInsets::bottomID, ScaleDownY(m_insets.bottom)); (env)->SetIntField(peerInsets, AwtInsets::leftID, ScaleDownX(m_insets.left)); (env)->SetIntField(peerInsets, AwtInsets::rightID, ScaleDownX(m_insets.right)); } + if (peerSysInsets != NULL) { + (env)->SetIntField(peerSysInsets, AwtInsets::topID, m_insets.top); + (env)->SetIntField(peerSysInsets, AwtInsets::bottomID, m_insets.bottom); + (env)->SetIntField(peerSysInsets, AwtInsets::leftID, m_insets.left); + (env)->SetIntField(peerSysInsets, AwtInsets::rightID, m_insets.right); + } /* Get insets into the Inset object (if any) that was passed */ if (insets != NULL) { (env)->SetIntField(insets, AwtInsets::topID, ScaleDownY(m_insets.top)); @@ -3421,6 +3431,8 @@ Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls) { TRY; + CHECK_NULL(AwtWindow::sysInsetsID = env->GetFieldID(cls, "sysInsets", "Ljava/awt/Insets;")); + AwtWindow::windowTypeID = env->GetFieldID(cls, "windowType", "Ljava/awt/Window$Type;"); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.h b/src/java.desktop/windows/native/libawt/windows/awt_Window.h index 90f7e0386bef..8b761bcf3e8e 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h @@ -66,6 +66,8 @@ class AwtWindow : public AwtCanvas { static jmethodID calculateSecurityWarningPositionMID; static jmethodID windowTypeNameMID; + static jfieldID sysInsetsID; + AwtWindow(); virtual ~AwtWindow(); diff --git a/test/jdk/java/awt/hidpi/ClientAreaOriginWindowsTest.java b/test/jdk/java/awt/hidpi/ClientAreaOriginWindowsTest.java new file mode 100644 index 000000000000..bf539dcda0be --- /dev/null +++ b/test/jdk/java/awt/hidpi/ClientAreaOriginWindowsTest.java @@ -0,0 +1,193 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.util.concurrent.CountDownLatch; +import java.util.function.Function; + +/* @test + * bug JRE-604 + * @summary Tests that the frame's client area origin is correctly positioned in the frame. + * @author Anton Tarasov + * @requires (os.family == "windows") + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.25 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.5 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.75 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.0 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.25 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.5 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.75 + * -Dsun.java2d.d3d=false + * ClientAreaOriginWindowsTest + */ +// +// Notes: +// 1) -Dsun.java2d.d3d=false is the current IDEA (ver. 181) mode. +// 2) The JDK build should contain the fix for JRE-573 for the test to pass. +// +public class ClientAreaOriginWindowsTest { + static final int F_WIDTH = 300; + static final int F_HEIGHT = 200; + + static final Color COLOR_BG = Color.green; + static final Color COLOR_OUTLINE = Color.red; + static final Color COLOR_FG = Color.blue; + + static volatile JFrame frame; + static volatile Timer timer; + + static volatile CountDownLatch latch = new CountDownLatch(1); + static volatile boolean framePainted = false; + + public static void main(String[] args) throws InterruptedException { + EventQueue.invokeLater(() -> show()); + + timer = new Timer(100, (event) -> { + Point loc; + try { + loc = frame.getContentPane().getLocationOnScreen(); + } catch (IllegalComponentStateException e) { + latch.countDown(); + return; + } + Rectangle rect = new Rectangle(loc.x - 1, loc.y - 1, 6, 6); + Robot robot; + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException(e); + } + BufferedImage capture = robot.createScreenCapture(rect); + int width = capture.getWidth(); + int height = capture.getHeight(); + + // First, check the frame's client area is painted, otherwise bounce. + Color fgPixel = new Color(capture.getRGB(width - 2, height - 2)); + if (!COLOR_FG.equals(fgPixel)) { + latch.countDown(); + return; + } + framePainted = true; + + Function check = (isXaxis) -> { + StringBuilder err = new StringBuilder(); + boolean hasOutline = false; + boolean hasBg = false; + boolean hasFg = false; + + for (int i = (isXaxis ? width - 1 : height - 1); i >= 0; i--) { + int x = isXaxis ? i : width - 1; + int y = isXaxis ? height - 1 : i; + Color c = new Color(capture.getRGB(x, y)); + hasOutline = c.equals(COLOR_OUTLINE) || hasOutline; + // assuming the frame's border system color is not COLOR_BG/COLOR_BG_FALLBACK. + hasBg = c.equals(COLOR_BG) || hasBg; + hasFg = c.equals(COLOR_FG) || hasFg; + } + String axis = isXaxis ? "X-axis" : "Y-axis"; + if (!hasOutline) err.append("no outline pixel by " + axis); + if (hasBg) err.append("; has background pixels by " + axis); + if (!hasFg) err.append("; no foreground pixels by " + axis); + return err.toString(); + }; + + String xAxis = check.apply(true); + String yAxis = check.apply(false); + + if (xAxis.length() > 0 || yAxis.length() > 0) { + StringBuilder err = new StringBuilder(). + append(xAxis). + append("; "). + append(yAxis); + throw new RuntimeException("Test FAILED: " + err); + } + latch.countDown(); + }); + timer.setRepeats(false); + + latch.await(); + latch = new CountDownLatch(1); + + while (!framePainted) { + timer.start(); + latch.await(); + if (!framePainted) latch = new CountDownLatch(1); + } + + System.out.println("Test PASSED"); + } + + static void show() { + frame = new JFrame("frame"); + frame.setLocationRelativeTo(null); + frame.setBackground(COLOR_BG); + frame.getContentPane().setBackground(COLOR_BG); + + JPanel panel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + AffineTransform tx = g2d.getTransform(); + double pixelX = 1 / tx.getScaleX(); + double pixelY = 1 / tx.getScaleY(); + + g2d.setColor(COLOR_OUTLINE); + g2d.fill(new Rectangle2D.Double(0, 0, F_WIDTH, F_HEIGHT)); + g2d.setColor(COLOR_FG); + g2d.fill(new Rectangle2D.Double(pixelX, pixelY, F_WIDTH - pixelX * 2, F_HEIGHT - pixelY * 2)); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(F_WIDTH, F_HEIGHT); + } + }; + + // Backs the main frame with black color. + JFrame bgFrame = new JFrame("bg_frame"); + bgFrame.setUndecorated(true); + bgFrame.setSize(F_WIDTH * 2, F_HEIGHT * 2); + bgFrame.setLocationRelativeTo(null); + bgFrame.setAlwaysOnTop(true); + JPanel cp = new JPanel(); + cp.setOpaque(true); + cp.setBackground(Color.black); + bgFrame.setContentPane(cp); + bgFrame.setVisible(true); + + frame.add(panel); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setAlwaysOnTop(true); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent e) { + latch.countDown(); + } + }); + frame.setVisible(true); + } +} \ No newline at end of file From 2268fe79217861bc80e8bf381c0160c8d85bc6ca Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 25 Dec 2017 16:18:38 +0300 Subject: [PATCH 109/976] JRE-612 [windows] icon in frame title is not dpi-aware (cherry picked from commit dec04385177a2abb677add909d3b94f94c62a14e) (cherry picked from commit 38466cbab02d7772b6b2ddd46ccada52597c81e8) --- .../classes/sun/awt/windows/WFramePeer.java | 8 ++++++ .../native/libawt/windows/awt_Dialog.cpp | 2 +- .../native/libawt/windows/awt_Frame.cpp | 26 ++++++++++++++++++- .../native/libawt/windows/awt_Toolkit.cpp | 12 ++++++++- .../native/libawt/windows/awt_Toolkit.h | 2 +- .../native/libawt/windows/awt_Window.cpp | 14 +++++----- .../native/libawt/windows/awt_Window.h | 2 +- 7 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java index 6b3fa5823fee..5235482a935e 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java @@ -123,6 +123,14 @@ private Rectangle adjustMaximizedBounds(Rectangle bounds) { return bounds; } + @Override + public void displayChanged() { + super.displayChanged(); + updateIcon(); + } + + private native void updateIcon(); + @Override public boolean updateGraphicsData(GraphicsConfiguration gc) { boolean result = super.updateGraphicsData(gc); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp index 8e3ca77c4723..37ebfd355cd6 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp @@ -403,7 +403,7 @@ HICON AwtDialog::GetEffectiveIcon(int iconType) //Java cup icon is not loaded in window class for dialogs //It needs to be set explicitly for resizable dialogs //and ownerless dialogs - hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() : + hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm(reinterpret_cast(this)) : AwtToolkit::GetInstance().GetAwtIcon(); } else if ((hIcon != NULL) && IsIconInherited() && !isResizable) { //Non-resizable dialogs without explicitly set icon diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 8876a5a8d98d..e5ef12074d81 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1185,6 +1185,19 @@ MsgRouting AwtFrame::WmGetIcon(WPARAM iconType, LRESULT& retVal) } } +void _UpdateIcon(void* p) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + jobject self = reinterpret_cast(p); + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + + AwtFrame* frame = (AwtFrame*)pData; + frame->DoUpdateIcon(); +ret: + env->DeleteGlobalRef(self); +} + void AwtFrame::DoUpdateIcon() { //Workaround windows bug: @@ -1201,7 +1214,7 @@ HICON AwtFrame::GetEffectiveIcon(int iconType) BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/)); HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon(); if (hIcon == NULL) { - hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() : + hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm(reinterpret_cast(this)) : AwtToolkit::GetInstance().GetAwtIcon(); } return hIcon; @@ -1962,6 +1975,17 @@ Java_sun_awt_windows_WFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, CATCH_BAD_ALLOC; } +JNIEXPORT void JNICALL +Java_sun_awt_windows_WFramePeer_updateIcon(JNIEnv *env, jobject self) +{ + TRY; + + AwtToolkit::GetInstance().InvokeFunction(_UpdateIcon, env->NewGlobalRef(self)); + // global ref is deleted in _UpdateIcon() + + CATCH_BAD_ALLOC; +} + } /* extern "C" */ static bool SetFocusToPluginControl(HWND hwndPlugin) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 8f2e523b5002..294b5747c62a 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -1909,7 +1909,7 @@ HICON AwtToolkit::GetAwtIcon() return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON")); } -HICON AwtToolkit::GetAwtIconSm() +HICON AwtToolkit::GetAwtIconSm(void* pAwtWindow) { static HICON defaultIconSm = NULL; static int prevSmx = 0; @@ -1918,6 +1918,16 @@ HICON AwtToolkit::GetAwtIconSm() int smx = GetSystemMetrics(SM_CXSMICON); int smy = GetSystemMetrics(SM_CYSMICON); + if (AwtWin32GraphicsDevice::IsUiScaleEnabled() && pAwtWindow != NULL) { + AwtWindow *wnd = reinterpret_cast(pAwtWindow); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(AwtWin32GraphicsDevice::DeviceIndexForWindow(wnd->GetHWnd())); + if (device) { + smx = 16 * device->GetScaleX(); + smy = 16 * device->GetScaleY(); + } + } + // Fixed 6364216: LoadImage() may leak memory if (defaultIconSm == NULL || smx != prevSmx || smy != prevSmy) { defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h index 5ff1d499eb9b..ef9d7f910bf6 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h @@ -370,7 +370,7 @@ class AwtToolkit { /* Return the current application icon. */ HICON GetAwtIcon(); - HICON GetAwtIconSm(); + HICON GetAwtIconSm(void* pAwtWindow = NULL); // Calculate a wave-like value out of the integer 'value' and // the specified period. diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 720daa81d605..54faf85dfd41 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1886,8 +1886,8 @@ MsgRouting AwtWindow::WmMove(int x, int y) // NOTE: See also AwtWindow::Reshape return mrDoDefault; } - // Check for the new screen and update the java peer - CheckIfOnNewScreen(false); // postpone if different DPI + + if (CheckIfOnNewScreen(false)) DoUpdateIcon(); /* Update the java AWT target component's fields directly */ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -2259,7 +2259,7 @@ int AwtWindow::GetScreenImOn() { * Check to see if we've been moved onto another screen. * If so, update internal data, surfaces, etc. */ -void AwtWindow::CheckIfOnNewScreen(BOOL force) { +BOOL AwtWindow::CheckIfOnNewScreen(BOOL force) { int curScrn = GetScreenImOn(); if (curScrn != m_screenNum) { // we've been moved @@ -2273,7 +2273,7 @@ void AwtWindow::CheckIfOnNewScreen(BOOL force) { if (oldDevice->GetScaleX() != newDevice->GetScaleX() || oldDevice->GetScaleY() != newDevice->GetScaleY()) { // scales are different, wait for WM_DPICHANGED - return; + return TRUE; } } @@ -2281,21 +2281,23 @@ void AwtWindow::CheckIfOnNewScreen(BOOL force) { jclass peerCls = env->GetObjectClass(m_peerObject); DASSERT(peerCls); - CHECK_NULL(peerCls); + CHECK_NULL_RETURN(peerCls, TRUE); jmethodID draggedID = env->GetMethodID(peerCls, "draggedToNewScreen", "()V"); DASSERT(draggedID); if (draggedID == NULL) { env->DeleteLocalRef(peerCls); - return; + return TRUE; } env->CallVoidMethod(m_peerObject, draggedID); m_screenNum = curScrn; env->DeleteLocalRef(peerCls); + return TRUE; } + return FALSE; } // The shared code is not ready to the top-level window which crosses a few diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.h b/src/java.desktop/windows/native/libawt/windows/awt_Window.h index 8b761bcf3e8e..6db2e53012ea 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h @@ -133,7 +133,7 @@ class AwtWindow : public AwtCanvas { virtual void RecalcNonClient(); virtual void RedrawNonClient(); virtual int GetScreenImOn(); - virtual void CheckIfOnNewScreen(BOOL force); + virtual BOOL CheckIfOnNewScreen(BOOL force); virtual void Grab(); virtual void Ungrab(); virtual void Ungrab(BOOL doPost); From 7f4290ee9c3477da27cdb40bd6241299d36a23c9 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 28 Dec 2017 17:39:18 +0300 Subject: [PATCH 110/976] JRE-616 [linux] notify when dpi correction factor is applied to fonts (cherry picked from commit f57d41f3118bfd773c99ce32d58cfae16931be6a) (cherry picked from commit 6246abc72f1c651955419faef74dfcd68b5dd852) --- .../com/sun/java/swing/plaf/gtk/PangoFonts.java | 11 +++++++++-- src/java.desktop/share/classes/java/awt/Toolkit.java | 5 +++++ .../share/classes/sun/awt/AWTAccessor.java | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java index cf81f7501e92..7f39194d314f 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java @@ -30,6 +30,7 @@ import javax.swing.plaf.FontUIResource; import java.util.StringTokenizer; +import sun.awt.AWTAccessor; import sun.font.FontConfigManager; import sun.font.FontUtilities; @@ -161,8 +162,8 @@ static Font lookupFont(String pangoName) { */ double dsize = size; int dpi = 96; - Object value = - Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI"); + Object xftDPI = Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI"); + Object value = xftDPI; if (!(value instanceof Integer)) { value = GTKEngine.INSTANCE.getSetting(GTKEngine.Settings.GTK_XFT_DPI); @@ -179,6 +180,12 @@ static Font lookupFont(String pangoName) { * 72 dpi, so we need to adjust for that. */ dsize = ((double)(dpi * size)/ 72.0); + + if (xftDPI == null) { + // [tav] used to indicate the 96/72 scale correction to the client app + AWTAccessor.getToolkitAccessor().setDesktopProperty( + Toolkit.getDefaultToolkit(), "gnome.Xft/DPI", value); + } } else { /* If there's no property, GTK scales for the resolution * reported by the Xserver using the formula listed above. diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index 54053fdc2e17..b84d036d577c 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -1401,6 +1401,11 @@ private static void initStatic() { public void setPlatformResources(ResourceBundle bundle) { Toolkit.setPlatformResources(bundle); } + + @Override + public void setDesktopProperty(Toolkit tk, String prop, Object value) { + tk.setDesktopProperty(prop, value); + } }); java.security.AccessController.doPrivileged( diff --git a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index 1303ef7b282f..15b582418c88 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -782,6 +782,7 @@ public interface SequencedEventAccessor { */ public interface ToolkitAccessor { void setPlatformResources(ResourceBundle bundle); + void setDesktopProperty(Toolkit tk, String prop, Object value); } /* From 910177c5e6fb5306a44462f7888a2e7b4f182d70 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 22 Feb 2018 15:04:23 +0300 Subject: [PATCH 111/976] JRE-665 Navigate Class/File/Symbol, Find in Path popup windows don't pick characters from input method (cherry picked from commit 676f305b2b3b278e305bd4d9bde4269f27b3d676) (cherry picked from commit 6ce31e0a326bdfc55877d201353f71819a3aad9d) --- .../sun/lwawt/macosx/CInputMethod.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index 64d8a101d69f..305a58f35b00 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -292,6 +292,18 @@ protected void setAWTFocussedComponent(Component component) { if (component.getInputMethodRequests() == null) { imInstance = null; } + + LWWindowPeer windowPeer = peer.getPlatformWindow().getPeer(); + if (windowPeer.isSimpleWindow()) { + // A simple window gains focus. Cocoa won't dispatch IME events into the simple window, but into its owner. + // This IM represents the focused component in the simple window. We will use the owner as IME proxy. + // For that, this IM is set for the owner and is dropped for the simple window. + Window owner = windowPeer.getTarget().getOwner(); + assert owner != null && owner.isActive(); + long ownerPtr = getNativeViewPtr((LWComponentPeer)AWTAccessor.getComponentAccessor().getPeer(owner)); + nativeNotifyPeer(ownerPtr, this); + imInstance = null; + } } if (peer != null) { @@ -368,6 +380,14 @@ public void dispose() { fAwtFocussedComponentPeer = null; } + private boolean isValid() { + return fIMContext != null && + fAwtFocussedComponent != null && + fAwtFocussedComponentPeer != null && + fCurrentText != null && + fCurrentTextAsString != null; + } + /** * Returns a control object from this input method, or null. A * control object provides methods that control the behavior of the @@ -587,6 +607,7 @@ private synchronized String attributedSubstringFromRange(final int locationIn, f final String[] retString = new String[1]; try { + if (isValid()) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(retString) { int location = locationIn; @@ -639,6 +660,7 @@ private synchronized int[] selectedRange() { final int[] returnValue = new int[2]; try { + if (isValid()) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(returnValue) { AttributedCharacterIterator theIterator = fIMContext.getSelectedText(null); @@ -714,6 +736,7 @@ private synchronized int[] firstRectForCharacterRange(final int absoluteTextOffs final int[] rect = new int[4]; try { + if (isValid()) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(rect) { int insertOffset = fIMContext.getInsertPositionOffset(); @@ -758,6 +781,7 @@ private synchronized int characterIndexForPoint(final int screenX, final int scr final int[] insertPositionOffset = new int[1]; try { + if (isValid()) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(offsetInfo) { offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY); From 9811fa797032c28cc0a34e5af7ec0f6910461aa0 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 7 Mar 2018 14:44:29 +0300 Subject: [PATCH 112/976] JRE-681 [windows] direct drawing into frame graphics may have wrong translate (cherry picked from commit ab6dee4c1fc453ad3cb5adb69fc243e550d184ae) (cherry picked from commit 6ea1d45fd13eeac3337b2964112d816ad8535c72) --- .../classes/javax/swing/RepaintManager.java | 90 +-------- .../classes/sun/java2d/SunGraphics2D.java | 2 +- .../classes/sun/awt/windows/WWindowPeer.java | 84 +++++++++ .../awt/hidpi/DrawOnFrameGraphicsTest.java | 176 ++++++++++++++++++ 4 files changed, 265 insertions(+), 87 deletions(-) create mode 100644 test/jdk/java/awt/hidpi/DrawOnFrameGraphicsTest.java diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index 775aa1d95d2e..52fa35a0f43b 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -1629,63 +1629,10 @@ protected void paintDoubleBuffered(JComponent c, Image image, Graphics g, int clipX, int clipY, int clipW, int clipH) { - SunGraphics2D sg = (SunGraphics2D)g.create(); - try { - // [tav] For the scaling graphics we need to compensate the toplevel insets rounding error - // to place [0, 0] of the client area in its correct device pixel. - if (sg.transformState == SunGraphics2D.TRANSFORM_TRANSLATESCALE) { - Point2D err = getInsetsRoundingError(sg); - double errX = err.getX(); - double errY = err.getY(); - if (errX != 0 || errY != 0) { - // save the current tx - AffineTransform tx = sg.transform; - - // translate the constrain - Region constrainClip = sg.constrainClip; - Shape usrClip = sg.usrClip; - if (constrainClip != null) { - // SunGraphics2D.constrain(..) rounds down x/y, so to compensate we need to round up - int _errX = (int)Math.ceil(errX); - int _errY = (int)Math.ceil(errY); - if ((_errX | _errY) != 0) { - // drop everything to default - sg.constrainClip = null; - sg.usrClip = null; - sg.clipState = SunGraphics2D.CLIP_DEVICE; - sg.transform = new AffineTransform(); - sg.setDevClip(sg.getSurfaceData().getBounds()); - - Region r = constrainClip.getTranslatedRegion(_errX, _errY); - sg.constrain(r.getLoX(), r.getLoY(), r.getWidth(), r.getHeight()); - } - } - - // translate usrClip - if (usrClip != null) { - if (usrClip instanceof Rectangle2D) { - Rectangle2D u = (Rectangle2D)usrClip; - u.setRect(u.getX() + errX, u.getY() + errY, u.getWidth(), u.getHeight()); - } else { - usrClip = AffineTransform.getTranslateInstance(errX, errY).createTransformedShape(usrClip); - } - sg.transform = new AffineTransform(); - sg.setClip(usrClip); // constrain clip is already valid - } - - // finally translate the tx - AffineTransform newTx = AffineTransform.getTranslateInstance(errX - sg.constrainX, errY - sg.constrainY); - newTx.concatenate(tx); - sg.setTransform(newTx); - } - } - if (image instanceof VolatileImage && isPixelsCopying(c, g)) { - paintDoubleBufferedFPScales(c, image, sg, clipX, clipY, clipW, clipH); - } else { - paintDoubleBufferedImpl(c, image, sg, clipX, clipY, clipW, clipH); - } - } finally { - sg.dispose(); + if (image instanceof VolatileImage && isPixelsCopying(c, g)) { + paintDoubleBufferedFPScales(c, image, g, clipX, clipY, clipW, clipH); + } else { + paintDoubleBufferedImpl(c, image, g, clipX, clipY, clipW, clipH); } } @@ -1730,35 +1677,6 @@ private void paintDoubleBufferedImpl(JComponent c, Image image, } } - /** - * For the scaling graphics and a decorated toplevel as the destination, - * calculates the rounding error of the toplevel insets. - * - * @return the left/top insets rounding error, in device space - */ - private static Point2D getInsetsRoundingError(SunGraphics2D g) { - Point2D.Double err = new Point2D.Double(0, 0); - if (g.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { - Object dst = g.getSurfaceData().getDestination(); - if (dst instanceof Frame && !((Frame)dst).isUndecorated() || - dst instanceof Dialog && !((Dialog)dst).isUndecorated()) - { - Window wnd = (Window)dst; - WindowPeer peer = (WindowPeer)AWTAccessor.getComponentAccessor().getPeer(wnd); - Insets sysInsets = peer != null ? peer.getSysInsets() : null; - if (sysInsets != null) { - Insets insets = wnd.getInsets(); - // insets.left/top is a scaled down rounded value - // insets.left/top * tx.scale is a scaled up value (which contributes to graphics translate) - // sysInsets.left/top is the precise system value - err.x = sysInsets.left - insets.left * g.transform.getScaleX(); - err.y = sysInsets.top - insets.top * g.transform.getScaleY(); - } - } - } - return err; - } - private void paintDoubleBufferedFPScales(JComponent c, Image image, Graphics g, int clipX, int clipY, int clipW, int clipH) { diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index bec43b3e9037..5fcc4da643a4 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -370,7 +370,7 @@ public void constrain(int x, int y, int w, int h, Region region) { // changes parameters according to the current scale and translate. final double scaleX = transform.getScaleX(); final double scaleY = transform.getScaleY(); - // [tav] rounding down affects aligning by insets in RepaintManager.paintDoubleBuffered + // [tav] rounding down affects aligning by insets in WWindowPeer.getGraphics x = constrainX = (int)Math.floor(transform.getTranslateX()); y = constrainY = (int)Math.floor(transform.getTranslateY()); w = Region.dimAdd(x, Region.clipScale(w, scaleX)); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index 62e45e95dec4..abfb593f3cc0 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -48,6 +48,9 @@ import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.geom.AffineTransform; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.awt.image.DataBufferInt; import java.awt.peer.WindowPeer; import java.beans.PropertyChangeEvent; @@ -64,6 +67,8 @@ import sun.awt.Win32GraphicsDevice; import sun.awt.Win32GraphicsEnvironment; import sun.java2d.pipe.Region; + +import sun.java2d.SunGraphics2D; import sun.util.logging.PlatformLogger; import static sun.java2d.SunGraphicsEnvironment.toUserSpace; @@ -909,4 +914,83 @@ public void propertyChange(PropertyChangeEvent e) { } } } + + @Override + public Graphics getGraphics() { + Graphics g = super.getGraphics(); + if (!(g instanceof SunGraphics2D)) return g; + SunGraphics2D sg = (SunGraphics2D)g; + + // [tav] For the scaling graphics we need to compensate the toplevel insets rounding error + // to place [0, 0] of the client area in its correct device pixel. + if (sg.transformState == SunGraphics2D.TRANSFORM_TRANSLATESCALE) { + Point2D err = getInsetsRoundingError(sg); + double errX = err.getX(); + double errY = err.getY(); + if (errX != 0 || errY != 0) { + // save the current tx + AffineTransform tx = sg.transform; + + // translate the constrain + Region constrainClip = sg.constrainClip; + Shape usrClip = sg.usrClip; + if (constrainClip != null) { + // SunGraphics2D.constrain(..) rounds down x/y, so to compensate we need to round up + int _errX = (int) Math.ceil(errX); + int _errY = (int) Math.ceil(errY); + if ((_errX | _errY) != 0) { + // drop everything to default + sg.constrainClip = null; + sg.usrClip = null; + sg.clipState = SunGraphics2D.CLIP_DEVICE; + sg.transform = new AffineTransform(); + sg.setDevClip(sg.getSurfaceData().getBounds()); + + Region r = constrainClip.getTranslatedRegion(_errX, _errY); + sg.constrain(r.getLoX(), r.getLoY(), r.getWidth(), r.getHeight()); + } + } + + // translate usrClip + if (usrClip != null) { + if (usrClip instanceof Rectangle2D) { + Rectangle2D u = (Rectangle2D) usrClip; + u.setRect(u.getX() + errX, u.getY() + errY, u.getWidth(), u.getHeight()); + } else { + usrClip = AffineTransform.getTranslateInstance(errX, errY).createTransformedShape(usrClip); + } + sg.transform = new AffineTransform(); + sg.setClip(usrClip); // constrain clip is already valid + } + + // finally translate the tx (in the device space, so via concatenate) + AffineTransform newTx = AffineTransform.getTranslateInstance(errX - sg.constrainX, errY - sg.constrainY); + newTx.concatenate(tx); + sg.setTransform(newTx); + } + } + return sg; + } + + /** + * For the scaling graphics and a decorated toplevel as the destination, + * calculates the rounding error of the toplevel insets. + * + * @return the left/top insets rounding error, in device space + */ + private Point2D getInsetsRoundingError(SunGraphics2D g) { + Point2D.Double err = new Point2D.Double(0, 0); + if (g.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE && !isTargetUndecorated()) { + Insets sysInsets = getSysInsets(); + if (sysInsets != null) { + Insets insets = ((Window)target).getInsets(); + // insets.left/top is a scaled down rounded value + // insets.left/top * tx.scale is a scaled up value (which contributes to graphics translate) + // sysInsets.left/top is the precise system value + err.x = sysInsets.left - insets.left * g.transform.getScaleX(); + err.y = sysInsets.top - insets.top * g.transform.getScaleY(); + } + } + return err; + } } diff --git a/test/jdk/java/awt/hidpi/DrawOnFrameGraphicsTest.java b/test/jdk/java/awt/hidpi/DrawOnFrameGraphicsTest.java new file mode 100644 index 000000000000..061a79a3368e --- /dev/null +++ b/test/jdk/java/awt/hidpi/DrawOnFrameGraphicsTest.java @@ -0,0 +1,176 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.util.concurrent.CountDownLatch; + +/* @test + * bug JRE-681 + * @summary Tests that drawing directly into frame's graphics doesn't shift relative to the frame's content. + * @author Anton Tarasov + * @requires (os.family == "windows") + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.25 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.5 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=1.75 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.0 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.25 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.5 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2.75 + * -Dsun.java2d.d3d=false + * DrawOnFrameGraphicsTest + */ +// Note: -Dsun.java2d.d3d=false is the current IDEA mode. +public class DrawOnFrameGraphicsTest { + static final int F_WIDTH = 300; + static final int F_HEIGHT = 200; + + static final Color FRAME_BG = Color.GREEN; + static final Color RECT_COLOR_1 = Color.RED; + static final Color RECT_COLOR_2 = Color.BLUE; + static final int RECT_SIZE = 20; + + static final Rectangle rect = new Rectangle(F_WIDTH/2 - RECT_SIZE/2, F_HEIGHT/2 - RECT_SIZE/2, RECT_SIZE, RECT_SIZE); + static JFrame frame; + static JComponent comp; + + static volatile CountDownLatch latch = new CountDownLatch(1); + static volatile boolean framePainted = false; + + static Robot robot; + + public static void main(String[] args) throws AWTException, InterruptedException { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException(e); + } + + EventQueue.invokeLater(DrawOnFrameGraphicsTest::show); + + Timer timer = new Timer(100, (event) -> { + Point loc; + try { + loc = frame.getContentPane().getLocationOnScreen(); + } catch (IllegalComponentStateException e) { + latch.countDown(); + return; + } + BufferedImage capture = robot.createScreenCapture( + new Rectangle(loc.x + 50, loc.y + 50, 1, 1)); + Color pixel = new Color(capture.getRGB(0, 0)); + framePainted = FRAME_BG.equals(pixel); + + latch.countDown(); + return; + }); + + timer.setRepeats(false); + latch.await(); // wait for ACTIVATED + latch = new CountDownLatch(1); + + //noinspection Duplicates + while (!framePainted) { + timer.start(); + latch.await(); + latch = new CountDownLatch(1); + } + + // + // Draw on the frame + // + EventQueue.invokeLater(DrawOnFrameGraphicsTest::draw); + latch.await(); + + // + // Take the capture of the colored rect with some extra space + // + Point pt = comp.getLocationOnScreen(); + BufferedImage capture = robot.createScreenCapture( + new Rectangle(pt.x + rect.x - 5, pt.y + rect.y - 5, + rect.width + 10, rect.height + 10)); + + // + // Test RECT_COLOR_1 is fully covered with RECT_COLOR_2 + // + boolean hasRectColor2 = false; + for (int x=0; x Date: Fri, 18 May 2018 18:30:23 +0300 Subject: [PATCH 113/976] JRE-772 swing returns incorrect FRC when AA is off (cherry picked from commit a161897d908aa10da6306c06452c5d6317fed2f0) (cherry picked from commit 2bf5a7ca5cc0292d507ecaf9841ed0f8a417b488) --- src/java.desktop/share/classes/sun/swing/SwingUtilities2.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java index c7e8213d6758..55f9916f27d3 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java +++ b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java @@ -178,8 +178,8 @@ public static void putAATextInfo(boolean lafCondition, Map hints = (Map) desktopHints; Object aaHint = hints.get(KEY_TEXT_ANTIALIASING); if (aaHint == null - || aaHint == VALUE_TEXT_ANTIALIAS_OFF - || aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT) { + /*|| aaHint == VALUE_TEXT_ANTIALIAS_OFF + || aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT*/) { return; } map.put(KEY_TEXT_ANTIALIASING, aaHint); From 5e76423e4129d8cc818a3733d452c15b054a02f9 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 8 Aug 2018 19:52:14 +0300 Subject: [PATCH 114/976] Do not scale base font in HiDPI mode on Linux (cherry picked from commit 6fb2c365290e04c15d9257eadce91e7cf5590512) --- .../share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java index 7f39194d314f..50288aec9f82 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java @@ -33,6 +33,7 @@ import sun.awt.AWTAccessor; import sun.font.FontConfigManager; import sun.font.FontUtilities; +import sun.java2d.SunGraphicsEnvironment; /** * @author Shannon Hickey @@ -170,7 +171,7 @@ static Font lookupFont(String pangoName) { } if (value instanceof Integer) { dpi = ((Integer)value).intValue() / 1024; - if (dpi == -1) { + if (dpi == -1 || SunGraphicsEnvironment.isUIScaleEnabled()) { dpi = 96; } if (dpi < 50) { /* 50 dpi is the minimum value gnome allows */ From ae096295b12b35bb776bb515e2b4fd9ad2ea039f Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 18 Mar 2021 13:26:35 +0300 Subject: [PATCH 115/976] Revert "8239894: Xserver crashes when the wrong high refresh rate is used" This code is needed for "Read org.gnome.desktop.interface/scaling-factor". Keep it until "JDK-8260270 Implement the HiDPI scale factor reading" is fixed. This reverts commit a7c2ebc7 --- .../classes/sun/awt/X11GraphicsDevice.java | 5 +- .../common/awt/systemscale/systemScale.c | 178 +++++++++++++++++- .../common/awt/systemscale/systemScale.h | 4 +- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 130 ++++++++++++- .../native/libsplashscreen/splashscreen_sys.c | 4 +- 5 files changed, 305 insertions(+), 16 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 573d842e5f29..0032c898af7b 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -439,10 +439,7 @@ public synchronized DisplayMode getDisplayMode() { @Override public synchronized DisplayMode[] getDisplayModes() { - if (!isFullScreenSupported() - || ((X11GraphicsEnvironment) GraphicsEnvironment - .getLocalGraphicsEnvironment()).runningXinerama()) { - // only the current mode will be returned + if (!isFullScreenSupported()) { return super.getDisplayModes(); } ArrayList modes = new ArrayList(); diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c index cb14db56a919..d0a9f5c4c078 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -24,7 +24,169 @@ */ #include "systemScale.h" +#include "jni.h" +#include "jni_util.h" +#include "jvm_md.h" +#include +#include #include +#include + +typedef void* g_settings_schema_source_get_default(); +typedef void* g_settings_schema_source_ref(void *); +typedef void g_settings_schema_source_unref(void *); +typedef void* g_settings_schema_source_lookup(void *, char *, int); +typedef int g_settings_schema_has_key(void *, char *); +typedef void* g_settings_new_full(void *, void *, char *); +typedef void* g_settings_get_value(void *, char *); +typedef int g_variant_is_of_type(void *, char *); +typedef unsigned long g_variant_n_children(void *); +typedef void* g_variant_get_child_value(void *, unsigned long); +typedef void g_variant_unref(void *); +typedef char* g_variant_get_string(void *, unsigned long *); +typedef int g_variant_get_int32(void *); +typedef double g_variant_get_double(void *); + +static g_settings_schema_has_key* fp_g_settings_schema_has_key; +static g_settings_new_full* fp_g_settings_new_full; +static g_settings_get_value* fp_g_settings_get_value; +static g_variant_is_of_type* fp_g_variant_is_of_type; +static g_variant_n_children* fp_g_variant_n_children; +static g_variant_get_child_value* fp_g_variant_get_child_value; +static g_variant_get_string* fp_g_variant_get_string; +static g_variant_get_int32* fp_g_variant_get_int32; +static g_variant_get_double* fp_g_variant_get_double; +static g_variant_unref* fp_g_variant_unref; + +static void* get_schema_value(char *name, char *key) { + static void *lib_handle; + static int initialized = 0; + static void * default_schema; + static g_settings_schema_source_lookup* schema_lookup; + void *schema = NULL, *fp = NULL; + if (!initialized) { + initialized = 1; + lib_handle = dlopen(JNI_LIB_NAME("gio-2.0"), RTLD_GLOBAL | RTLD_LAZY); + if (!lib_handle) { + CHECK_NULL_RETURN(lib_handle = + dlopen(VERSIONED_JNI_LIB_NAME("gio-2.0", "0"), + RTLD_GLOBAL | RTLD_LAZY), NULL); + } + CHECK_NULL_RETURN(fp_g_settings_schema_has_key = + (g_settings_schema_has_key*) + dlsym(lib_handle, "g_settings_schema_has_key"), NULL); + CHECK_NULL_RETURN(fp_g_settings_new_full = + (g_settings_new_full*) + dlsym(lib_handle, "g_settings_new_full"), NULL); + CHECK_NULL_RETURN(fp_g_settings_get_value = + (g_settings_get_value*) + dlsym(lib_handle, "g_settings_get_value"), NULL); + CHECK_NULL_RETURN(fp_g_variant_is_of_type = + (g_variant_is_of_type*) + dlsym(lib_handle, "g_variant_is_of_type"), NULL); + CHECK_NULL_RETURN(fp_g_variant_n_children = + (g_variant_n_children*) + dlsym(lib_handle, "g_variant_n_children"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_child_value = + (g_variant_get_child_value*) + dlsym(lib_handle, "g_variant_get_child_value"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_string = + (g_variant_get_string*) + dlsym(lib_handle, "g_variant_get_string"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_int32 = + (g_variant_get_int32*) + dlsym(lib_handle, "g_variant_get_int32"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_double = + (g_variant_get_double*) + dlsym(lib_handle, "g_variant_get_double"), NULL); + CHECK_NULL_RETURN(fp_g_variant_unref = + (g_variant_unref*) + dlsym(lib_handle, "g_variant_unref"), NULL); + + fp = dlsym(lib_handle, "g_settings_schema_source_get_default"); + if (fp) { + default_schema = ((g_settings_schema_source_get_default*)fp)(); + } + if (default_schema) { + fp = dlsym(lib_handle, "g_settings_schema_source_ref"); + if (fp) { + ((g_settings_schema_source_ref*)fp)(default_schema); + } + } + schema_lookup = (g_settings_schema_source_lookup*) + dlsym(lib_handle, "g_settings_schema_source_lookup"); + } + + if (!default_schema || !schema_lookup) { + return NULL; + } + + schema = schema_lookup(default_schema, name, 1); + if (schema) { + if (fp_g_settings_schema_has_key(schema, key)) { + void *settings = fp_g_settings_new_full(schema, NULL, NULL); + if (settings) { + return fp_g_settings_get_value(settings, key); + } + } + } + return NULL; +} + + +static double getDesktopScale(char *output_name) { + double result = -1; + if(output_name) { + void *value = get_schema_value("com.ubuntu.user-interface", + "scale-factor"); + if (value) { + if(fp_g_variant_is_of_type(value, "a{si}")) { + int num = fp_g_variant_n_children(value); + int i = 0; + while (i < num) { + void *entry = fp_g_variant_get_child_value(value, i++); + if (entry) { + void *screen = fp_g_variant_get_child_value(entry, 0); + void *scale = fp_g_variant_get_child_value(entry, 1); + if (screen && scale) { + char *name = fp_g_variant_get_string(screen, NULL); + if (name && !strcmp(name, output_name)) { + result = fp_g_variant_get_int32(scale) / 8.; + } + fp_g_variant_unref(screen); + fp_g_variant_unref(scale); + } + fp_g_variant_unref(entry); + } + if (result > 0) { + break; + } + } + } + fp_g_variant_unref(value); + } + if (result > 0) { + value = get_schema_value("com.canonical.Unity.Interface", + "text-scale-factor"); + if (value && fp_g_variant_is_of_type(value, "d")) { + result *= fp_g_variant_get_double(value); + fp_g_variant_unref(value); + } + } + } + + if (result <= 0) { + void *value = get_schema_value("org.gnome.desktop.interface", + "text-scaling-factor"); + if (value && fp_g_variant_is_of_type(value, "d")) { + result = fp_g_variant_get_double(value); + fp_g_variant_unref(value); + } + } + + return result; + +} static int getScale(const char *name) { char *uiScale = getenv(name); @@ -38,8 +200,10 @@ static int getScale(const char *name) { return -1; } -double getNativeScaleFactor() { +double getNativeScaleFactor(char *output_name) { static int scale = -2.0; + double native_scale = 0; + int gdk_scale = 0; if (scale == -2) { scale = getScale("J2D_UISCALE"); @@ -49,5 +213,13 @@ double getNativeScaleFactor() { return scale; } - return getScale("GDK_SCALE"); + native_scale = getDesktopScale(output_name); + + if (native_scale <= 0) { + native_scale = 1; + } + + gdk_scale = getScale("GDK_SCALE"); + + return gdk_scale > 0 ? native_scale * gdk_scale : native_scale; } diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h index 2dc6e37c3a3d..10de165f4138 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ #include #include -double getNativeScaleFactor(); +double getNativeScaleFactor(char *output_name); #endif diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index aa2e88940dca..2ff76142d41e 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1741,7 +1741,49 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode AWT_LOCK(); - if (screen < ScreenCount(awt_display)) { + if (usingXinerama && XScreenCount(awt_display) > 0) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, 0)); + if (res) { + if (res->noutput > screen) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[screen]); + if (output_info) { + if (output_info->crtc) { + XRRCrtcInfo *crtc_info = + awt_XRRGetCrtcInfo (awt_display, res, + output_info->crtc); + if (crtc_info) { + if (crtc_info->mode) { + int i; + for (i = 0; i < res->nmode; i++) { + XRRModeInfo *mode = &res->modes[i]; + if (mode->id == crtc_info->mode) { + float rate = 0; + if (mode->hTotal && mode->vTotal) { + rate = ((float)mode->dotClock / + ((float)mode->hTotal * + (float)mode->vTotal)); + } + displayMode = X11GD_CreateDisplayMode( + env, + mode->width, + mode->height, + BIT_DEPTH_MULTI, + (int)(rate +.2)); + break; + } + } + } + awt_XRRFreeCrtcInfo(crtc_info); + } + } + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + } else { config = awt_XRRGetScreenInfo(awt_display, RootWindow(awt_display, screen)); @@ -1791,8 +1833,45 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes AWT_LOCK(); - if (XScreenCount(awt_display) > 0) { - + if (usingXinerama && XScreenCount(awt_display) > 0) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, 0)); + if (res) { + if (res->noutput > screen) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[screen]); + if (output_info) { + int i; + for (i = 0; i < output_info->nmode; i++) { + RRMode m = output_info->modes[i]; + int j; + XRRModeInfo *mode; + for (j = 0; j < res->nmode; j++) { + mode = &res->modes[j]; + if (mode->id == m) { + float rate = 0; + if (mode->hTotal && mode->vTotal) { + rate = ((float)mode->dotClock / + ((float)mode->hTotal * + (float)mode->vTotal)); + } + X11GD_AddDisplayMode(env, arrayList, + mode->width, mode->height, + BIT_DEPTH_MULTI, (int)(rate +.2)); + if ((*env)->ExceptionCheck(env)) { + goto ret0; + } + break; + } + } + } +ret0: + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + } else { XRRScreenConfiguration *config; config = awt_XRRGetScreenInfo(awt_display, @@ -1950,6 +2029,42 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive * End DisplayMode/FullScreen support */ +static char *get_output_screen_name(JNIEnv *env, int screen) { +#ifdef NO_XRANDR + return NULL; +#else + if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) { + return NULL; + } + char *name = NULL; + AWT_LOCK(); + int scr = 0, out = 0; + if (usingXinerama && XScreenCount(awt_display) > 0) { + out = screen; + } else { + scr = screen; + } + + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, scr)); + if (res) { + if (res->noutput > out) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[out]); + if (output_info) { + if (output_info->name) { + name = strdup(output_info->name); + } + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + AWT_UNLOCK(); + return name; +#endif /* NO_XRANDR */ +} + /* * Class: sun_awt_X11GraphicsDevice * Method: getNativeScaleFactor @@ -1958,6 +2073,11 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor (JNIEnv *env, jobject this, jint screen) { - - return getNativeScaleFactor(); + // in case of Xinerama individual screen scales are not supported + char *name = get_output_screen_name(env, usingXinerama ? 0 : screen); + double scale = getNativeScaleFactor(name); + if (name) { + free(name); + } + return scale; } diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c index c532f1658cb9..ab79637e8349 100644 --- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, 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 @@ -813,7 +813,7 @@ SplashGetScaledImageName(const char* jarName, const char* fileName, #ifndef __linux__ return JNI_FALSE; #endif - *scaleFactor = (float)getNativeScaleFactor(); + *scaleFactor = (float)getNativeScaleFactor(NULL); return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength); } From 9dab09b726dabc544d2fa56cafa5237cf1720d96 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 8 Aug 2018 20:58:18 +0300 Subject: [PATCH 116/976] Read org.gnome.desktop.interface/scaling-factor (cherry picked from commit 277357ae73457c83b9fd8efdc8c0954104cd4806) --- .../native/common/awt/systemscale/systemScale.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c index d0a9f5c4c078..878949fb60da 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c @@ -45,6 +45,7 @@ typedef void* g_variant_get_child_value(void *, unsigned long); typedef void g_variant_unref(void *); typedef char* g_variant_get_string(void *, unsigned long *); typedef int g_variant_get_int32(void *); +typedef unsigned g_variant_get_uint32(void *); typedef double g_variant_get_double(void *); static g_settings_schema_has_key* fp_g_settings_schema_has_key; @@ -55,6 +56,7 @@ static g_variant_n_children* fp_g_variant_n_children; static g_variant_get_child_value* fp_g_variant_get_child_value; static g_variant_get_string* fp_g_variant_get_string; static g_variant_get_int32* fp_g_variant_get_int32; +static g_variant_get_uint32* fp_g_variant_get_uint32; static g_variant_get_double* fp_g_variant_get_double; static g_variant_unref* fp_g_variant_unref; @@ -96,6 +98,9 @@ static void* get_schema_value(char *name, char *key) { CHECK_NULL_RETURN(fp_g_variant_get_int32 = (g_variant_get_int32*) dlsym(lib_handle, "g_variant_get_int32"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_uint32 = + (g_variant_get_uint32*) + dlsym(lib_handle, "g_variant_get_uint32"), NULL); CHECK_NULL_RETURN(fp_g_variant_get_double = (g_variant_get_double*) dlsym(lib_handle, "g_variant_get_double"), NULL); @@ -175,6 +180,15 @@ static double getDesktopScale(char *output_name) { } } + if (result <= 0) { + void *value = get_schema_value("org.gnome.desktop.interface", + "scaling-factor"); + if (value && fp_g_variant_is_of_type(value, "u")) { + result = fp_g_variant_get_uint32(value); + fp_g_variant_unref(value); + } + } + if (result <= 0) { void *value = get_schema_value("org.gnome.desktop.interface", "text-scaling-factor"); From 55ef918604d02190f9f29ad30416dc7193e943c6 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 18 Mar 2021 14:04:17 +0300 Subject: [PATCH 117/976] JRE-681 [windows] direct drawing into frame graphics may have wrong translate (cherry picked from commit 6ea1d45fd13eeac3337b2964112d816ad8535c72) --- make/modules/java.desktop/lib/Awt2dLibraries.gmk | 1 + src/java.base/windows/native/launcher/java.rc | 3 +-- src/java.base/windows/native/launcher/java_rc.h | 6 ++++++ .../windows/native/libawt/windows/awt_Toolkit.cpp | 11 +++++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/java.base/windows/native/launcher/java_rc.h diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index e274005e6074..785d5f543b32 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -74,6 +74,7 @@ ifeq ($(call isTargetOs, windows), true) $(TOPDIR)/src/$(MODULE)/share/native/common/font \ $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \ $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \ + $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/launcher \ # endif diff --git a/src/java.base/windows/native/launcher/java.rc b/src/java.base/windows/native/launcher/java.rc index 27c6465de210..6789a9a6091b 100644 --- a/src/java.base/windows/native/launcher/java.rc +++ b/src/java.base/windows/native/launcher/java.rc @@ -1,6 +1,5 @@ #include "version.rc" - -#define IDI_ICON 2000 +#include "java_rc.h" ///////////////////////////////////////////////////////////////////////////// // diff --git a/src/java.base/windows/native/launcher/java_rc.h b/src/java.base/windows/native/launcher/java_rc.h new file mode 100644 index 000000000000..d3a1efe7536e --- /dev/null +++ b/src/java.base/windows/native/launcher/java_rc.h @@ -0,0 +1,6 @@ +#ifndef _JAVA_RC_H_ +#define _JAVA_RC_H_ + +#define IDI_ICON 2000 + +#endif // _JAVA_RC_H_ diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 294b5747c62a..c5a703c8ced7 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -54,6 +54,8 @@ #include "debug_trace.h" #include "debug_mem.h" +#include "java_rc.h" + #include "ComCtl32Util.h" #include "DllUtil.h" @@ -1906,7 +1908,9 @@ AwtObject* AwtToolkit::LookupCmdID(UINT id) HICON AwtToolkit::GetAwtIcon() { - return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON")); + HICON hIcon = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON)); + if (!hIcon) hIcon = ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON")); + return hIcon; } HICON AwtToolkit::GetAwtIconSm(void* pAwtWindow) @@ -1930,7 +1934,10 @@ HICON AwtToolkit::GetAwtIconSm(void* pAwtWindow) // Fixed 6364216: LoadImage() may leak memory if (defaultIconSm == NULL || smx != prevSmx || smy != prevSmy) { - defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0); + defaultIconSm = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON)); + if (!defaultIconSm) { + defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0); + } prevSmx = smx; prevSmy = smy; } From 23a5c2ff137ae3230aa9ec4359bc37a3081fc654 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 16 Aug 2018 17:23:28 +0300 Subject: [PATCH 118/976] [jdk9] HiDPI scale is not detected on some linux desktops (cherry picked from commit 9279d80110cb573a5aae887b66b72b78f12aadbb) --- .../com/sun/java/swing/plaf/gtk/GTKEngine.java | 13 +++++++++++++ .../classes/sun/awt/X11GraphicsDevice.java | 18 +++++++++++++++++- .../common/awt/systemscale/systemScale.c | 12 +++++++----- .../common/awt/systemscale/systemScale.h | 2 +- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 2 +- .../native/libsplashscreen/splashscreen_sys.c | 2 +- 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 0804747a4263..8ebd8de13913 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -40,6 +40,7 @@ import sun.awt.image.SunWritableRaster; import sun.swing.ImageCache; +import sun.awt.X11GraphicsDevice; /** * GTKEngine delegates all painting job to native GTK libraries. @@ -271,6 +272,18 @@ private native void nativeSetRangeValue(int widgetType, double value, regionToWidgetTypeMap.put(Region.TREE, WidgetType.TREE); regionToWidgetTypeMap.put(Region.TREE_CELL, WidgetType.TREE_CELL); regionToWidgetTypeMap.put(Region.VIEWPORT, WidgetType.VIEWPORT); + + Object value = INSTANCE.getSetting(Settings.GTK_XFT_DPI); + if (value instanceof Integer) { + int dpi = ((Integer)value).intValue() / 1024; + if (dpi == -1) { + dpi = 96; + } + if (dpi < 50) { + dpi = 50; + } + X11GraphicsDevice.setGlobalScale(Math.round(dpi / 96f)); + } } /** Translate Region and JComponent into WidgetType ordinals */ diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 0032c898af7b..3d6946398f61 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -72,6 +72,8 @@ public final class X11GraphicsDevice extends GraphicsDevice private volatile Insets insets; private boolean shutdownHookRegistered; private int scale; + private volatile boolean isNativeScaleDefault; + private static int globalScale; // derived from Xft.dpi public X11GraphicsDevice(int screennum) { this.screen = screennum; @@ -570,6 +572,17 @@ public int getNativeScale() { return (int)Math.round(getNativeScaleFactor(screen)); } + public static void setGlobalScale(int scale) { + globalScale = scale; + for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { + X11GraphicsDevice x11gd = (X11GraphicsDevice)gd; + if (x11gd.isNativeScaleDefault) { + x11gd.scale = globalScale; + x11gd.isNativeScaleDefault = false; + } + } + } + private int initScaleFactor() { if (SunGraphicsEnvironment.isUIScaleEnabled()) { @@ -580,7 +593,10 @@ private int initScaleFactor() { return (int) debugScale; } int nativeScale = getNativeScale(); - return nativeScale >= 1 ? nativeScale : 1; + if (nativeScale > 0) return nativeScale; + if (globalScale > 0) return globalScale; + isNativeScaleDefault = true; + return 1; } return 1; diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c index 878949fb60da..105756bbddc0 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c @@ -170,6 +170,7 @@ static double getDesktopScale(char *output_name) { } fp_g_variant_unref(value); } + /* [tav] if (result > 0) { value = get_schema_value("com.canonical.Unity.Interface", "text-scale-factor"); @@ -177,7 +178,7 @@ static double getDesktopScale(char *output_name) { result *= fp_g_variant_get_double(value); fp_g_variant_unref(value); } - } + }*/ } if (result <= 0) { @@ -189,6 +190,7 @@ static double getDesktopScale(char *output_name) { } } + /* [tav] if (result <= 0) { void *value = get_schema_value("org.gnome.desktop.interface", "text-scaling-factor"); @@ -196,7 +198,7 @@ static double getDesktopScale(char *output_name) { result = fp_g_variant_get_double(value); fp_g_variant_unref(value); } - } + }*/ return result; @@ -214,7 +216,7 @@ static int getScale(const char *name) { return -1; } -double getNativeScaleFactor(char *output_name) { +double getNativeScaleFactor(char *output_name, double default_value) { static int scale = -2.0; double native_scale = 0; int gdk_scale = 0; @@ -230,10 +232,10 @@ double getNativeScaleFactor(char *output_name) { native_scale = getDesktopScale(output_name); if (native_scale <= 0) { - native_scale = 1; + native_scale = default_value; } gdk_scale = getScale("GDK_SCALE"); - return gdk_scale > 0 ? native_scale * gdk_scale : native_scale; + return gdk_scale > 0 ? (native_scale <= 0 ? 1 : native_scale) * gdk_scale : native_scale; } diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h index 10de165f4138..16aa9ff6f989 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h @@ -28,7 +28,7 @@ #include #include -double getNativeScaleFactor(char *output_name); +double getNativeScaleFactor(char *output_name, double default_value); #endif diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 2ff76142d41e..04abe38596d0 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -2075,7 +2075,7 @@ Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor (JNIEnv *env, jobject this, jint screen) { // in case of Xinerama individual screen scales are not supported char *name = get_output_screen_name(env, usingXinerama ? 0 : screen); - double scale = getNativeScaleFactor(name); + double scale = getNativeScaleFactor(name, -1); if (name) { free(name); } diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c index ab79637e8349..51fe626b885c 100644 --- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c @@ -813,7 +813,7 @@ SplashGetScaledImageName(const char* jarName, const char* fileName, #ifndef __linux__ return JNI_FALSE; #endif - *scaleFactor = (float)getNativeScaleFactor(NULL); + *scaleFactor = (float)getNativeScaleFactor(NULL, 1); return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength); } From 1ec5ead3ed76e9107dbd1dbe77f44d9377f99674 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 3 Sep 2018 18:15:48 +0300 Subject: [PATCH 119/976] JRE-934 Diff viewer errors are not visible on HiDPI Linux (cherry picked from commit 641a09dd526d2cdb2a95d23b70a9626a7f21493c) --- .../JEditorPanePreferredSizeTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/jdk/javax/swing/JEditorPane/JEditorPanePreferredSizeTest/JEditorPanePreferredSizeTest.java diff --git a/test/jdk/javax/swing/JEditorPane/JEditorPanePreferredSizeTest/JEditorPanePreferredSizeTest.java b/test/jdk/javax/swing/JEditorPane/JEditorPanePreferredSizeTest/JEditorPanePreferredSizeTest.java new file mode 100644 index 000000000000..15611c5ea4e9 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/JEditorPanePreferredSizeTest/JEditorPanePreferredSizeTest.java @@ -0,0 +1,28 @@ +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.InvocationTargetException; + +/* @test + * bug JRE-934 + * @summary Diff viewer errors are not visible on HiDPI Linux (fixed by JDK-8231084) + * @run main JEditorPanePreferredSizeTest + */ +public class JEditorPanePreferredSizeTest { + public static void main(String[] args) throws InvocationTargetException, InterruptedException { + final Dimension size = new Dimension(0, 0); + SwingUtilities.invokeAndWait(() -> { + JEditorPane myEditorPane = new JEditorPane("text/html", "text"); + myEditorPane.setBorder(null); + // triggers initial BasicTextUI layout + myEditorPane.getPreferredSize(); + // triggers BasicTextUI.modelChanged(), font here should be different from component's default font + myEditorPane.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + + size.setSize(myEditorPane.getPreferredSize()); + }); + if (size.width <= 0 || size.height <= 0) { + throw new RuntimeException("Test FAILED: bad preferred size: " + size); + } + System.out.println("Test PASSED"); + } +} \ No newline at end of file From 6ae83eb3477d532802c53bbb74a17b6eeb1717bc Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 18 Mar 2021 14:37:20 +0300 Subject: [PATCH 120/976] JRE-907 macOS: add ability to check for scaled display mode (cherry picked from commit e496262aa1200d03cffc523f5825ba1016bb928f) --- .../macosx/native/libawt_lwawt/awt/CGraphicsDevice.m | 6 ++++-- .../share/classes/java/awt/DisplayMode.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m index 468c5f6dae09..08feb79ce444 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m @@ -169,9 +169,11 @@ static jobject createJavaDisplayMode(CGDisplayModeRef mode, JNIEnv *env) { w = CGDisplayModeGetWidth(mode); CFRelease(currentBPP); } + uint32_t flags = CGDisplayModeGetIOFlags(mode); + BOOL isDisplayModeDefault = (flags & kDisplayModeDefaultFlag) ? YES : NO; DECLARE_CLASS_RETURN(jc_DisplayMode, "java/awt/DisplayMode", ret); - DECLARE_METHOD_RETURN(jc_DisplayMode_ctor, jc_DisplayMode, "", "(IIII)V", ret); - ret = (*env)->NewObject(env, jc_DisplayMode, jc_DisplayMode_ctor, w, h, bpp, refrate); + DECLARE_METHOD_RETURN(jc_DisplayMode_ctor, jc_DisplayMode, "", "(IIIIZ)V", ret); + ret = (*env)->NewObject(env, jc_DisplayMode, jc_DisplayMode_ctor, w, h, bpp, refrate, (jboolean)isDisplayModeDefault); CHECK_EXCEPTION(); JNI_COCOA_EXIT(env); return ret; diff --git a/src/java.desktop/share/classes/java/awt/DisplayMode.java b/src/java.desktop/share/classes/java/awt/DisplayMode.java index 21585e14e36b..a0c2d3447639 100644 --- a/src/java.desktop/share/classes/java/awt/DisplayMode.java +++ b/src/java.desktop/share/classes/java/awt/DisplayMode.java @@ -51,6 +51,7 @@ public final class DisplayMode { private Dimension size; private int bitDepth; private int refreshRate; + private boolean isDefault; /** * Create a new display mode object with the supplied parameters. @@ -71,6 +72,13 @@ public DisplayMode(int width, int height, int bitDepth, int refreshRate) { this.refreshRate = refreshRate; } + private DisplayMode(int width, int height, int bitDepth, int refreshRate, boolean isDefault) { + this.size = new Dimension(width, height); + this.bitDepth = bitDepth; + this.refreshRate = refreshRate; + this.isDefault = isDefault; + } + /** * Returns the height of the display, in pixels. * @return the height of the display, in pixels @@ -123,6 +131,10 @@ public int getRefreshRate() { return refreshRate; } + private boolean isDefault() { + return isDefault; + } + /** * Returns whether the two display modes are equal. * From 0876c7774437c7fd5cb2ace06c032c801172f4aa Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 5 Sep 2018 16:34:13 +0300 Subject: [PATCH 121/976] JRE-938 [windows] Frame.setMaximizedBounds not hidpi-aware (cherry picked from commit cc97899923320e1fa17f5e44975c4a0f0ba51014) (cherry picked from commit ccfe65be7f5e860a383318984fe58d22bb062b44) --- .../native/libawt/windows/awt_Frame.cpp | 4 ++ .../awt/hidpi/SetMaximizedBoundsTest.java | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/jdk/java/awt/hidpi/SetMaximizedBoundsTest.java diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index e5ef12074d81..20e37d9eb21a 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1475,6 +1475,10 @@ void AwtFrame::_SetMaximizedBounds(void *param) if (::IsWindow(f->GetHWnd())) { DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame))); + x = f->ScaleUpAbsX(x); + y = f->ScaleUpAbsY(y); + width = f->ScaleUpX(width); + height = f->ScaleUpY(height); f->SetMaximizedBounds(x, y, width, height); } ret: diff --git a/test/jdk/java/awt/hidpi/SetMaximizedBoundsTest.java b/test/jdk/java/awt/hidpi/SetMaximizedBoundsTest.java new file mode 100644 index 000000000000..d817dbbb096c --- /dev/null +++ b/test/jdk/java/awt/hidpi/SetMaximizedBoundsTest.java @@ -0,0 +1,54 @@ +import javax.swing.*; +import java.awt.*; +import sun.awt.SunToolkit; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; + +/* @test + * bug JRE-938 + * @summary Tests that Frame.setMaximizedBounds meets HiDPI. + * @author Anton Tarasov + * @requires (os.family == "windows") + * @modules java.desktop/sun.awt + * @run main/othervm -Dsun.java2d.uiScale.enabled=true + * -Dsun.java2d.uiScale=2 + * SetMaximizedBoundsTest + */ +public class SetMaximizedBoundsTest { + private static volatile JFrame frame; + private static final Rectangle MAX_BOUNDS = new Rectangle(100, 100, 500, 500); + private static volatile Rectangle testBounds; + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(SetMaximizedBoundsTest::show); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + + EventQueue.invokeAndWait(SetMaximizedBoundsTest::maximize); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + + EventQueue.invokeAndWait(SetMaximizedBoundsTest::test); + + if (!MAX_BOUNDS.equals(testBounds)) { + throw new RuntimeException("Test FAILED: bad bounds " + testBounds); + } + System.out.println("Test PASSED"); + } + + private static void show() { + frame = new JFrame("frame"); + frame.setBounds(200, 200, 200, 200); + frame.setVisible(true); + } + + private static void maximize() { + frame.setMaximizedBounds(MAX_BOUNDS); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + } + + private static void test() { + testBounds = frame.getBounds(); + frame.dispose(); + } +} \ No newline at end of file From 04782116aed68a4b65e9fe7e2b2b20c30c2e86c5 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 6 Nov 2018 22:05:12 +0300 Subject: [PATCH 122/976] JRE-981 IM workaround does not work anymore forward port of 2d7c29b in JetBrains/jdk8u_jdk (cherry picked from commit f3ccc53e02d3738f72a628468754d0a23228c675) --- .../classes/sun/lwawt/macosx/CInputMethod.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index 305a58f35b00..774b936e8729 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -380,14 +380,6 @@ public void dispose() { fAwtFocussedComponentPeer = null; } - private boolean isValid() { - return fIMContext != null && - fAwtFocussedComponent != null && - fAwtFocussedComponentPeer != null && - fCurrentText != null && - fCurrentTextAsString != null; - } - /** * Returns a control object from this input method, or null. A * control object provides methods that control the behavior of the @@ -607,7 +599,7 @@ private synchronized String attributedSubstringFromRange(final int locationIn, f final String[] retString = new String[1]; try { - if (isValid()) + if (fIMContext != null) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(retString) { int location = locationIn; @@ -660,7 +652,7 @@ private synchronized int[] selectedRange() { final int[] returnValue = new int[2]; try { - if (isValid()) + if (fIMContext != null) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(returnValue) { AttributedCharacterIterator theIterator = fIMContext.getSelectedText(null); @@ -736,7 +728,7 @@ private synchronized int[] firstRectForCharacterRange(final int absoluteTextOffs final int[] rect = new int[4]; try { - if (isValid()) + if (fIMContext != null) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(rect) { int insertOffset = fIMContext.getInsertPositionOffset(); @@ -755,7 +747,7 @@ public void run() { synchronized(rect) { if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) { Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0)); - if (r.equals(r2)) { + if (r.equals(r2) && fCurrentTextAsString != null) { // FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate // window off the right edge of the component. String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset); @@ -781,7 +773,7 @@ private synchronized int characterIndexForPoint(final int screenX, final int scr final int[] insertPositionOffset = new int[1]; try { - if (isValid()) + if (fIMContext != null) LWCToolkit.invokeAndWait(new Runnable() { public void run() { synchronized(offsetInfo) { offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY); From 9114725476d7bbd1c78e57516f8f029f197e2102 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 4 Dec 2018 18:10:14 +0300 Subject: [PATCH 123/976] fix JNI_OnUnload definition (cherry picked from the commit 3571e390710d7383777439ce942a0e00d7ef5cc0) (cherry picked from commit 1019d8f0f2b68aab0aabe6bea033b53d9651acb0) --- src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index f272eabd1fe1..6d9402948541 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -2003,7 +2003,8 @@ Java_sun_font_FreetypeFontScaler_getGlyphPointNative( sunFontIDs.pt2DFloatCtr, x, y); } -void JNI_OnUnload(JavaVM *vm, void *reserved) { +JNIEXPORT void JNICALL +JNI_OnUnload(JavaVM *vm, void *reserved) { if (libFontConfig != NULL) { #ifndef _WIN32 dlclose(libFontConfig); From 1d742fe05117d8b695a7d4bd07d59198fe6e207a Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 18 Jan 2019 17:22:18 +0300 Subject: [PATCH 124/976] JRE-1111 [JDK11] java/beans/Beans/TypoInBeanDescription.java crashes at libawt_xawt.so+0x4a30d (cherry picked from commit b89e6aed0b74104e4e9ff834e435faaca1f4c8b7) --- .../com/sun/java/swing/plaf/gtk/GTKEngine.java | 13 ------------- .../com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java | 13 +++++++++++++ .../unix/native/libawt_xawt/awt/gtk3_interface.c | 2 ++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 8ebd8de13913..0804747a4263 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -40,7 +40,6 @@ import sun.awt.image.SunWritableRaster; import sun.swing.ImageCache; -import sun.awt.X11GraphicsDevice; /** * GTKEngine delegates all painting job to native GTK libraries. @@ -272,18 +271,6 @@ private native void nativeSetRangeValue(int widgetType, double value, regionToWidgetTypeMap.put(Region.TREE, WidgetType.TREE); regionToWidgetTypeMap.put(Region.TREE_CELL, WidgetType.TREE_CELL); regionToWidgetTypeMap.put(Region.VIEWPORT, WidgetType.VIEWPORT); - - Object value = INSTANCE.getSetting(Settings.GTK_XFT_DPI); - if (value instanceof Integer) { - int dpi = ((Integer)value).intValue() / 1024; - if (dpi == -1) { - dpi = 96; - } - if (dpi < 50) { - dpi = 50; - } - X11GraphicsDevice.setGlobalScale(Math.round(dpi / 96f)); - } } /** Translate Region and JComponent into WidgetType ordinals */ diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 72b8c759e30b..63595c4416d8 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -45,6 +45,7 @@ import sun.awt.SunToolkit; import sun.awt.UNIXToolkit; import sun.awt.OSInfo; +import sun.awt.X11GraphicsDevice; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; import sun.swing.SwingAccessor; @@ -1449,6 +1450,18 @@ public void initialize() { gtkAAFontSettingsCond = SwingUtilities2.isLocalDisplay(); aaTextInfo = new HashMap<>(2); SwingUtilities2.putAATextInfo(gtkAAFontSettingsCond, aaTextInfo); + + Object value = GTKEngine.INSTANCE.getSetting(GTKEngine.Settings.GTK_XFT_DPI); + if (value instanceof Integer) { + int dpi = ((Integer)value).intValue() / 1024; + if (dpi == -1) { + dpi = 96; + } + if (dpi < 50) { + dpi = 50; + } + X11GraphicsDevice.setGlobalScale(Math.round(dpi / 96f)); + } } static ReferenceQueue queue = new ReferenceQueue(); diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index ff637430edf3..4d50413ffbe3 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -2753,6 +2753,8 @@ static jobject gtk3_get_setting(JNIEnv *env, Setting property) return get_string_property(env, settings, "gtk-font-name"); case GTK_ICON_SIZES: return get_string_property(env, settings, "gtk-icon-sizes"); + case GTK_XFT_DPI: + return get_integer_property(env, settings, "gtk-xft-dpi"); case GTK_CURSOR_BLINK: return get_boolean_property(env, settings, "gtk-cursor-blink"); case GTK_CURSOR_BLINK_TIME: From cc1af415c4867aba3f6f4de9d023091839e2c926 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 18 Jan 2019 18:36:52 +0300 Subject: [PATCH 125/976] JRE-1142 [jdk11] hidpi is not detected since Ubuntu 18.04 (cherry picked from commit be4f8c0d9d94ff031ec4af6ef1df9dc474e54d7a) --- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 04abe38596d0..e117b2d085a1 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #ifndef NO_XRANDR #include #endif @@ -2076,6 +2078,26 @@ Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor // in case of Xinerama individual screen scales are not supported char *name = get_output_screen_name(env, usingXinerama ? 0 : screen); double scale = getNativeScaleFactor(name, -1); + +#ifndef HEADLESS + // Ubuntu 18.04 introduced a new settings for a scale factor: Settings > Devices > Displays > Scale. + // It is propagated to Xresource (and is read fine with 'xrdb' util) but is not propagated to GSettings + // (gtk3 doesn't see it in 'gtk-xft-dpi'). So, retrieve "Xft.dpi" from Xresource via X11 API call. + if (scale <= 0 && awt_display) { + char *resource_manager = XResourceManagerString(awt_display); + if (resource_manager) { + XrmDatabase db = XrmGetStringDatabase(resource_manager); + if (db) { + XrmValue value; + char *type; + if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &type, &value)) { + scale = (double)atoi(value.addr) / 96; + } + } + } + } +#endif + if (name) { free(name); } From 53d02344f8d30cd1e67f8a91b748bfd78d226eca Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 28 Jan 2019 18:45:26 +0300 Subject: [PATCH 126/976] JRE-1162 [jdk11] support on-the-fly DPI change on linux (cherry picked from commit c06c4c69d37654e60c6053d75745e29950a7fa1a) --- .../unix/classes/sun/awt/X11/XToolkit.java | 5 ++++- .../unix/classes/sun/awt/X11/XWM.java | 4 ++++ .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 22 +++++++++++-------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 1b4f45b55f1f..c7535312398e 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -351,7 +351,10 @@ void init() { XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() { @Override public void dispatchEvent(XEvent ev) { - if (ev.get_type() == XConstants.ConfigureNotify) { + if (ev.get_type() == XConstants.ConfigureNotify || + (ev.get_type() == XConstants.PropertyNotify && + ev.get_xproperty().get_atom() == XWM.XA_NET_DESKTOP_GEOMETRY.getAtom())) // possible DPI change + { awtUnlock(); try { ((X11GraphicsEnvironment)GraphicsEnvironment. diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java index 0382a7b6caf3..31c1b7655168 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java @@ -89,6 +89,9 @@ final class XWM static final XAtom XA_NET_FRAME_EXTENTS = new XAtom(); static final XAtom XA_NET_REQUEST_FRAME_EXTENTS = new XAtom(); +/* Root window */ + static final XAtom XA_NET_DESKTOP_GEOMETRY = new XAtom(); + static final int UNDETERMINED_WM = 1, NO_WM = 2, @@ -206,6 +209,7 @@ static void initAtoms() { { XA_MWM_HINTS, "_MOTIF_WM_HINTS" }, { XA_NET_FRAME_EXTENTS, "_NET_FRAME_EXTENTS" }, { XA_NET_REQUEST_FRAME_EXTENTS, "_NET_REQUEST_FRAME_EXTENTS" }, + { XA_NET_DESKTOP_GEOMETRY, "_NET_DESKTOP_GEOMETRY" } }; String[] names = new String[atomInitList.length]; diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index e117b2d085a1..b07d9d2660b7 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -2083,17 +2083,21 @@ Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor // Ubuntu 18.04 introduced a new settings for a scale factor: Settings > Devices > Displays > Scale. // It is propagated to Xresource (and is read fine with 'xrdb' util) but is not propagated to GSettings // (gtk3 doesn't see it in 'gtk-xft-dpi'). So, retrieve "Xft.dpi" from Xresource via X11 API call. - if (scale <= 0 && awt_display) { - char *resource_manager = XResourceManagerString(awt_display); - if (resource_manager) { - XrmDatabase db = XrmGetStringDatabase(resource_manager); - if (db) { - XrmValue value; - char *type; - if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &type, &value)) { - scale = (double)atoi(value.addr) / 96; + if (scale <= 0) { + Display *display = XOpenDisplay(NULL); // need to open new display to get up-to-date XResource value + if (display) { + char *resource_manager = XResourceManagerString(display); + if (resource_manager) { + XrmDatabase db = XrmGetStringDatabase(resource_manager); + if (db) { + XrmValue value; + char *type; + if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &type, &value)) { + scale = (double)atoi(value.addr) / 96; + } } } + XCloseDisplay(display); } } #endif From 191fb7eb8d2f4863b9d15539f1ec1e0beda092d0 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 21 Feb 2019 20:03:47 +0300 Subject: [PATCH 127/976] JRE-1232 forwardport: JRE-1228 support custom frame decoration (cherry picked from commit d2820524a1aa211b1c49b30f659b9b4d07a6f96e) --- .../share/classes/java/awt/Window.java | 12 ++ .../classes/sun/awt/windows/WWindowPeer.java | 15 +++ .../native/libawt/windows/awt_Component.cpp | 4 +- .../native/libawt/windows/awt_Component.h | 3 +- .../native/libawt/windows/awt_Frame.cpp | 115 ++++++++++++++++++ .../windows/native/libawt/windows/awt_Frame.h | 5 + .../native/libawt/windows/awt_List.cpp | 2 +- .../windows/native/libawt/windows/awt_List.h | 2 +- .../native/libawt/windows/awt_ScrollPane.cpp | 2 +- .../native/libawt/windows/awt_ScrollPane.h | 2 +- .../native/libawt/windows/awt_Scrollbar.cpp | 2 +- .../native/libawt/windows/awt_Scrollbar.h | 2 +- .../native/libawt/windows/awt_TextArea.cpp | 2 +- .../native/libawt/windows/awt_TextArea.h | 2 +- .../native/libawt/windows/awt_Window.cpp | 2 +- .../native/libawt/windows/awt_Window.h | 4 +- 16 files changed, 163 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index c5d876b9bde9..e97bdba9b7d7 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -3994,6 +3994,18 @@ private static void setLayersOpaque(Component component, boolean isOpaque) { } } + private volatile boolean hasCustomDecoration; + + boolean hasCustomDecoration() { + return hasCustomDecoration; + } + + /** + * Set via reflection (JB JdkEx API). + */ + void setHasCustomDecoration() { + hasCustomDecoration = true; + } // ************************** MIXING CODE ******************************* diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index abfb593f3cc0..df6594990f22 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -57,6 +57,7 @@ import java.beans.PropertyChangeListener; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; import sun.awt.AWTAccessor; import sun.awt.AppContext; @@ -993,4 +994,18 @@ private Point2D getInsetsRoundingError(SunGraphics2D g) { } return err; } + + private volatile List hitTestSpots; + + private void setCustomDecorationHitTestSpots(List hitTestSpots) { + this.hitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots); + } + + private boolean hitTestCustomDecoration(int x, int y) { + if (hitTestSpots == null) return false; + for (Rectangle spot : hitTestSpots) { + if (spot.contains(x, y)) return true; + } + return false; + } } diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index b9e55848f75f..eda0b5adec86 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -1890,7 +1890,7 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) mr = WmNcPaint((HRGN)wParam); break; case WM_NCHITTEST: - mr = WmNcHitTest(LOWORD(lParam), HIWORD(lParam), retValue); + mr = WmNcHitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), retValue); break; case WM_AWT_RESHAPE_COMPONENT: { @@ -4637,7 +4637,7 @@ MsgRouting AwtComponent::WmNcPaint(HRGN hrgn) return mrDoDefault; } -MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal) +MsgRouting AwtComponent::WmNcHitTest(int x, int y, LRESULT &retVal) { return mrDoDefault; } diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 47c9b93633ee..68148927d4c5 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -586,7 +586,7 @@ class AwtComponent : public AwtObject { LPNCCALCSIZE_PARAMS lpncsp, LRESULT &retVal); virtual MsgRouting WmNcPaint(HRGN hrgn); - virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal); + virtual MsgRouting WmNcHitTest(int x, int y, LRESULT &retVal); virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos); virtual MsgRouting WmEnterSizeMove(); virtual MsgRouting WmExitSizeMove(); @@ -755,6 +755,7 @@ class AwtComponent : public AwtObject { virtual void FillBackground(HDC hMemoryDC, SIZE &size); virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha); +public: int ScaleUpX(int x); int ScaleUpAbsX(int x); int ScaleUpY(int y); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 20e37d9eb21a..c5812547a118 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -32,6 +32,8 @@ #include "ComCtl32Util.h" #include +#include +#include #include #include @@ -125,6 +127,7 @@ AwtFrame::AwtFrame() { m_zoomed = FALSE; m_maxBoundsSet = FALSE; m_forceResetZoomed = FALSE; + m_pHasCustomDecoration = NULL; isInManualMoveOrSize = FALSE; grabbedHitTest = 0; @@ -1659,6 +1662,118 @@ void AwtFrame::_NotifyModalBlocked(void *param) delete nmbs; } +// {start} Custom Decoration Support + +BOOL AwtFrame::HasCustomDecoration() +{ + if (!m_pHasCustomDecoration) { + m_pHasCustomDecoration = new BOOL; + JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + *m_pHasCustomDecoration = JNU_CallMethodByName(env, NULL, GetTarget(env), "hasCustomDecoration", "()Z").z; + } + return *m_pHasCustomDecoration; +} + +void GetSysInsets(RECT* insets) { + static RECT* sysInsets = NULL; + + if (!sysInsets) { + sysInsets = new RECT; + sysInsets->left = sysInsets->right = ::GetSystemMetrics(SM_CXSIZEFRAME); + sysInsets->top = sysInsets->bottom = ::GetSystemMetrics(SM_CYSIZEFRAME); + sysInsets->top += ::GetSystemMetrics(SM_CYCAPTION); + } + ::CopyRect(insets, sysInsets); +} + +LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { + RECT rcWindow; + RECT insets; + + GetSysInsets(&insets); + GetWindowRect(frame->GetHWnd(), &rcWindow); + + // Get the frame rectangle, adjusted for the style without a caption. + RECT rcFrame = {0}; + AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL); + + USHORT uRow = 1; + USHORT uCol = 1; + BOOL fOnResizeBorder = FALSE; + + if (y >= rcWindow.top && + y < rcWindow.top + insets.top) + { + JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env), + "hitTestCustomDecoration", "(II)Z", + frame->ScaleDownX(x - rcWindow.left), + frame->ScaleDownY(y - rcWindow.top)).z) + { + return HTNOWHERE; + } + fOnResizeBorder = (y < (rcWindow.top - rcFrame.top)); + uRow = 0; + } else if (y < rcWindow.bottom && + y >= rcWindow.bottom - insets.bottom) { + uRow = 2; + } + + if (x >= rcWindow.left && + x < rcWindow.left + insets.left) + { + uCol = 0; + } else if (x < rcWindow.right && + x >= rcWindow.right - insets.right) + { + uCol = 2; + } + + LRESULT hitTests[3][3] = { + {HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT}, + {HTLEFT, HTNOWHERE, HTRIGHT}, + {HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT}, + }; + + return hitTests[uRow][uCol]; +} + +MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal) +{ + if (!wParam || !HasCustomDecoration()) { + return AwtWindow::WmNcCalcSize(wParam, lpncsp, retVal); + } + if (::IsZoomed(GetHWnd())) { + RECT insets; + GetSysInsets(&insets); + static int xBorder = ::GetSystemMetrics(SM_CXBORDER); + static int yBorder = ::GetSystemMetrics(SM_CYBORDER); + + // When maximized we should include insets or otherwise the client area edges get out of a screen + lpncsp->rgrc[0].left = lpncsp->rgrc[0].left + insets.left - xBorder; + lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + insets.bottom - yBorder; // do not count caption + lpncsp->rgrc[0].right = lpncsp->rgrc[0].right - insets.right + xBorder; + lpncsp->rgrc[0].bottom = lpncsp->rgrc[0].bottom - insets.bottom + yBorder; + } + retVal = 0L; + return mrConsume; +} + +MsgRouting AwtFrame::WmNcHitTest(int x, int y, LRESULT& retVal) +{ + if (!HasCustomDecoration()) { + return AwtWindow::WmNcHitTest(x, y, retVal); + } + if (::IsWindow(GetModalBlocker(GetHWnd()))) { + retVal = HTCLIENT; + return mrConsume; + } + retVal = HitTestNCA(this, x, y); + return retVal == HTNOWHERE ? mrDoDefault : mrConsume; +} + +// {end} Custom Decoration Support + /************************************************************************ * WFramePeer native methods */ diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.h b/src/java.desktop/windows/native/libawt/windows/awt_Frame.h index 8b70720448ae..97d3c60d2fdf 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.h @@ -114,6 +114,8 @@ class AwtFrame : public AwtWindow { MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal); MsgRouting WmShowWindow(BOOL show, UINT status); MsgRouting WmWindowPosChanging(LPARAM windowPos); + MsgRouting WmNcCalcSize(BOOL fCalcValidRects, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal); + MsgRouting WmNcHitTest(int x, int y, LRESULT& retVal); virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos); @@ -156,6 +158,9 @@ class AwtFrame : public AwtWindow { INLINE HWND GetImeTargetComponent() { return m_imeTargetComponent; } INLINE void SetImeTargetComponent(HWND hwnd) { m_imeTargetComponent = hwnd; } + BOOL* m_pHasCustomDecoration; + BOOL HasCustomDecoration(); + protected: /* The frame is undecorated. */ BOOL m_isUndecorated; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp index 7ffbb5c6a852..973442e030be 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp @@ -404,7 +404,7 @@ AwtList::OwnerMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT& measureInfo) } MsgRouting -AwtList::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) +AwtList::WmNcHitTest(int x, int y, LRESULT& retVal) { if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { retVal = HTCLIENT; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_List.h b/src/java.desktop/windows/native/libawt/windows/awt_List.h index 3450089b5091..69c97a520cc0 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_List.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_List.h @@ -110,7 +110,7 @@ class AwtList : public AwtComponent { /* * Windows message handler functions */ - MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); + MsgRouting WmNcHitTest(int x, int y, LRESULT& retVal); MsgRouting WmMouseDown(UINT flags, int x, int y, int button); MsgRouting WmMouseUp(UINT flags, int x, int y, int button); MsgRouting WmNotify(UINT notifyCode); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp index 0bfba78c0905..347f8d8fedc4 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp @@ -359,7 +359,7 @@ void AwtScrollPane::PostScrollEvent(int orient, int scrollCode, int pos) { } MsgRouting -AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) +AwtScrollPane::WmNcHitTest(int x, int y, LRESULT& retVal) { if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { retVal = HTCLIENT; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.h b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.h index 129b0e12cd8c..203ef348d553 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.h @@ -75,7 +75,7 @@ class AwtScrollPane : public AwtCanvas { /* * Windows message handler functions */ - virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); + virtual MsgRouting WmNcHitTest(int x, int y, LRESULT& retVal); virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar); virtual MsgRouting WmVScroll(UINT scrollCode, UINT pos, HWND hScrollBar); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp index f13677cfbed5..e59fce9cb387 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.cpp @@ -223,7 +223,7 @@ AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) } MsgRouting -AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) +AwtScrollbar::WmNcHitTest(int x, int y, LRESULT& retVal) { if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { retVal = HTCLIENT; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h index 9369cab0e589..6db58abf8f3f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Scrollbar.h @@ -71,7 +71,7 @@ class AwtScrollbar : public AwtComponent { // Prevent KB Q102552 race. virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button); - virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); + virtual MsgRouting WmNcHitTest(int x, int y, LRESULT& retVal); virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp b/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp index 6dc21c5addae..0e71f0637b70 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp @@ -138,7 +138,7 @@ AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { } MsgRouting -AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) +AwtTextArea::WmNcHitTest(int x, int y, LRESULT& retVal) { if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { retVal = HTCLIENT; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h b/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h index 1738e64b8edb..eba97e333023 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h @@ -59,7 +59,7 @@ class AwtTextArea : public AwtTextComponent { LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); MsgRouting WmEnable(BOOL fEnabled); - MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal); + MsgRouting WmNcHitTest(int x, int y, LRESULT &retVal); MsgRouting HandleEvent(MSG *msg, BOOL synthetic); virtual BOOL InheritsNativeMouseWheelBehavior(); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 54faf85dfd41..3d3e7355095d 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -2083,7 +2083,7 @@ MsgRouting AwtWindow::WmNcCalcSize(BOOL fCalcValidRects, return mrRetVal; } -MsgRouting AwtWindow::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) +MsgRouting AwtWindow::WmNcHitTest(int x, int y, LRESULT& retVal) { // If this window is blocked by modal dialog, return HTCLIENT for any point of it. // That prevents it to be moved or resized using the mouse. Disabling these diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.h b/src/java.desktop/windows/native/libawt/windows/awt_Window.h index 6db2e53012ea..6c10fdc62f7b 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h @@ -181,7 +181,7 @@ class AwtWindow : public AwtCanvas { virtual MsgRouting WmSettingChange(UINT wFlag, LPCTSTR pszSection); virtual MsgRouting WmNcCalcSize(BOOL fCalcValidRects, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal); - virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); + virtual MsgRouting WmNcHitTest(int x, int y, LRESULT& retVal); virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button); virtual MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal); virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); @@ -265,6 +265,8 @@ class AwtWindow : public AwtCanvas { inline HWND GetOverriddenHWnd() { return m_overriddenHwnd; } inline void OverrideHWnd(HWND hwnd) { m_overriddenHwnd = hwnd; } + virtual BOOL HasCustomDecoration() { return FALSE; } + private: static int ms_instanceCounter; static HHOOK ms_hCBTFilter; From 4712c493e6257cb917fce9eafb781a091ab62b66 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 19 Mar 2021 17:12:36 +0300 Subject: [PATCH 128/976] JBR-1278 allow native border and shadow for custom decoration mode (cherry picked from commit a879ad5739523947daf1187a9a82b9eea0f9acf8) --- .../java.desktop/lib/Awt2dLibraries.gmk | 2 +- .../libawt/windows/awt_DesktopProperties.cpp | 12 +++++++++ .../native/libawt/windows/awt_Frame.cpp | 25 +++++++++++-------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index 785d5f543b32..7da3cf8ecced 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -167,7 +167,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ LIBS_windows := kernel32.lib user32.lib gdi32.lib winspool.lib \ imm32.lib ole32.lib uuid.lib shell32.lib \ comdlg32.lib winmm.lib comctl32.lib shlwapi.lib \ - delayimp.lib jvm.lib $(WIN_JAVA_LIB) advapi32.lib, \ + delayimp.lib jvm.lib $(WIN_JAVA_LIB) advapi32.lib dwmapi.lib, \ VERSIONINFO_RESOURCE := $(LIBAWT_VERSIONINFO_RESOURCE), \ EXTRA_RCFLAGS := $(LIBAWT_RCFLAGS), \ )) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index 97bb74919401..8720cea32e12 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -38,6 +38,8 @@ #include #include +#include + // WDesktopProperties fields jfieldID AwtDesktopProperties::pDataID = 0; jmethodID AwtDesktopProperties::setBooleanPropertyID = 0; @@ -510,6 +512,16 @@ void AwtDesktopProperties::GetColorParameters() { SetColorProperty(TEXT("win.frame.activeCaptionColor"), GetSysColor(COLOR_ACTIVECAPTION)); SetColorProperty(TEXT("win.frame.activeBorderColor"), GetSysColor(COLOR_ACTIVEBORDER)); + BOOL enabled; + DwmIsCompositionEnabled(&enabled); + if (enabled) { + DWORD color; + BOOL opaque = FALSE; + // [tav] todo: listen WM_DWMCOLORIZATIONCOLORCHANGED + DwmGetColorizationColor(&color, &opaque); + SetColorProperty(TEXT("win.dwm.colorizationColor"), RGB(GetBValue(color), GetGValue(color), GetRValue(color))); + } + // ?? ?? ?? SetColorProperty(TEXT("win.frame.color"), GetSysColor(COLOR_WINDOWFRAME)); // ?? WHAT THE HECK DOES THIS MEAN ?? // ?? ?? ?? diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index c5812547a118..e01dbafa3c77 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1743,18 +1743,23 @@ MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESU if (!wParam || !HasCustomDecoration()) { return AwtWindow::WmNcCalcSize(wParam, lpncsp, retVal); } - if (::IsZoomed(GetHWnd())) { - RECT insets; - GetSysInsets(&insets); - static int xBorder = ::GetSystemMetrics(SM_CXBORDER); - static int yBorder = ::GetSystemMetrics(SM_CYBORDER); - // When maximized we should include insets or otherwise the client area edges get out of a screen - lpncsp->rgrc[0].left = lpncsp->rgrc[0].left + insets.left - xBorder; - lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + insets.bottom - yBorder; // do not count caption - lpncsp->rgrc[0].right = lpncsp->rgrc[0].right - insets.right + xBorder; - lpncsp->rgrc[0].bottom = lpncsp->rgrc[0].bottom - insets.bottom + yBorder; + RECT insets; + GetSysInsets(&insets); + RECT* rect = &lpncsp->rgrc[0]; + + rect->left = rect->left + insets.left; + if (::IsZoomed(GetHWnd())) { + lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + insets.bottom; + } + else { + // this makes the native caption go uncovered + // int yBorder = ::GetSystemMetrics(SM_CYBORDER); + // lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + yBorder; } + rect->right = rect->right - insets.right; + rect->bottom = rect->bottom - insets.bottom; + retVal = 0L; return mrConsume; } From 9949ae16c30c6b5e2fc21998a2e0a332bf32b5fe Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 26 Mar 2019 10:15:50 +0300 Subject: [PATCH 129/976] JBR-1293 do not modify client bounds when custom-decorated frame is set undecorated (cherry picked from commit cb188edaab8e393c49b2133714044943549e83bf) --- .../windows/native/libawt/windows/awt_Frame.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index e01dbafa3c77..1b3f224e6462 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1674,9 +1674,13 @@ BOOL AwtFrame::HasCustomDecoration() return *m_pHasCustomDecoration; } -void GetSysInsets(RECT* insets) { +void GetSysInsets(RECT* insets, AwtFrame* pFrame) { static RECT* sysInsets = NULL; + if (pFrame->IsUndecorated()) { + ::SetRect(insets, 0, 0, 0, 0); + return; + } if (!sysInsets) { sysInsets = new RECT; sysInsets->left = sysInsets->right = ::GetSystemMetrics(SM_CXSIZEFRAME); @@ -1690,7 +1694,7 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { RECT rcWindow; RECT insets; - GetSysInsets(&insets); + GetSysInsets(&insets, frame); GetWindowRect(frame->GetHWnd(), &rcWindow); // Get the frame rectangle, adjusted for the style without a caption. @@ -1743,9 +1747,8 @@ MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESU if (!wParam || !HasCustomDecoration()) { return AwtWindow::WmNcCalcSize(wParam, lpncsp, retVal); } - RECT insets; - GetSysInsets(&insets); + GetSysInsets(&insets, this); RECT* rect = &lpncsp->rgrc[0]; rect->left = rect->left + insets.left; From f084523ce99d2020ad1262c132b293836cc08635 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 28 Mar 2019 19:16:29 +0300 Subject: [PATCH 130/976] JBR-1313 wrong insets for non-resizable custom-decorated frame (cherry picked from commit 9179718cb6c8c7b43429daec2f7ed17d75579ad5) --- .../windows/native/libawt/windows/awt_Frame.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 1b3f224e6462..ce61f8548a31 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1675,19 +1675,13 @@ BOOL AwtFrame::HasCustomDecoration() } void GetSysInsets(RECT* insets, AwtFrame* pFrame) { - static RECT* sysInsets = NULL; - if (pFrame->IsUndecorated()) { ::SetRect(insets, 0, 0, 0, 0); return; } - if (!sysInsets) { - sysInsets = new RECT; - sysInsets->left = sysInsets->right = ::GetSystemMetrics(SM_CXSIZEFRAME); - sysInsets->top = sysInsets->bottom = ::GetSystemMetrics(SM_CYSIZEFRAME); - sysInsets->top += ::GetSystemMetrics(SM_CYCAPTION); - } - ::CopyRect(insets, sysInsets); + insets->left = insets->right = ::GetSystemMetrics(pFrame->IsResizable() ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME); + insets->top = insets->bottom = ::GetSystemMetrics(pFrame->IsResizable() ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME); + insets->top += ::GetSystemMetrics(SM_CYCAPTION); } LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { From 02b84b049d959fe33b0c6540757683af2ff2964c Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 19 Mar 2021 17:23:17 +0300 Subject: [PATCH 131/976] JBR-1351 Borderless UI: Bold frame around IDEA window appears on non-HiDPI display (cherry picked from commit 06d35de06951adacc04cba6c35bf7d568ff11f79) --- .../windows/native/libawt/windows/awt.h | 2 ++ .../windows/native/libawt/windows/awt_Frame.cpp | 16 +++++++++++----- .../native/libawt/windows/awt_Toolkit.cpp | 8 ++++++++ .../windows/native/libawt/windows/awt_Toolkit.h | 8 ++++++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt.h b/src/java.desktop/windows/native/libawt/windows/awt.h index 0aa848ce644f..dc4f188454c3 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt.h +++ b/src/java.desktop/windows/native/libawt/windows/awt.h @@ -48,6 +48,8 @@ typedef enum _PROCESS_DPI_AWARENESS { } PROCESS_DPI_AWARENESS; #endif +typedef BOOL(WINAPI AdjustWindowRectExForDpiFunc)(LPRECT, DWORD, BOOL, DWORD, UINT); + class AwtObject; typedef AwtObject* PDATA; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index ce61f8548a31..cd2f05e6674d 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1676,12 +1676,18 @@ BOOL AwtFrame::HasCustomDecoration() void GetSysInsets(RECT* insets, AwtFrame* pFrame) { if (pFrame->IsUndecorated()) { - ::SetRect(insets, 0, 0, 0, 0); + ::SetRectEmpty(insets); return; } - insets->left = insets->right = ::GetSystemMetrics(pFrame->IsResizable() ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME); - insets->top = insets->bottom = ::GetSystemMetrics(pFrame->IsResizable() ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME); - insets->top += ::GetSystemMetrics(SM_CYCAPTION); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(AwtWin32GraphicsDevice::DeviceIndexForWindow(pFrame->GetHWnd())); + int dpi = device ? device->GetScaleX() * 96 : 96; + + // GetSystemMetricsForDpi gives incorrect values, use AdjustWindowRectExForDpi for border metrics instead + RECT rect = {}; + DWORD style = pFrame->IsResizable() ? WS_OVERLAPPEDWINDOW : WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME; + AwtToolkit::AdjustWindowRectExForDpi(&rect, style, FALSE, NULL, dpi); + ::SetRect(insets, -rect.left, -rect.top, rect.right, rect.bottom); } LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { @@ -1692,7 +1698,7 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { GetWindowRect(frame->GetHWnd(), &rcWindow); // Get the frame rectangle, adjusted for the style without a caption. - RECT rcFrame = {0}; + RECT rcFrame = {}; AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL); USHORT uRow = 1; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index c5a703c8ced7..86008b60025f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -141,6 +141,8 @@ extern "C" JNIEXPORT jboolean JNICALL AWTIsHeadless() { #define IDT_AWT_MOUSECHECK 0x101 +AdjustWindowRectExForDpiFunc* AwtToolkit::lpAdjustWindowRectExForDpi = NULL; + static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit"); static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2. @@ -665,6 +667,12 @@ BOOL AwtToolkit::Initialize() { awt_dnd_initialize(); + HMODULE hLibUser32Dll = JDK_LoadSystemLibrary("User32.dll"); + if (hLibUser32Dll != NULL) { + lpAdjustWindowRectExForDpi = (AdjustWindowRectExForDpiFunc*)GetProcAddress(hLibUser32Dll, "AdjustWindowRectExForDpi"); + ::FreeLibrary(hLibUser32Dll); + } + /* * Initialization of the touch keyboard related variables. */ diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h index ef9d7f910bf6..094d0cb1f86f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h @@ -426,6 +426,12 @@ class AwtToolkit { static BOOL CALLBACK CommonPeekMessageFunc(MSG& msg); static BOOL activateKeyboardLayout(HKL hkl); + static INLINE BOOL AdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) + { + return lpAdjustWindowRectExForDpi != NULL ? + lpAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi) : ::AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); + } + HANDLE m_waitEvent; volatile DWORD eventNumber; volatile BOOL isDnDSourceActive; @@ -492,6 +498,8 @@ class AwtToolkit { HANDLE m_inputMethodWaitEvent; LRESULT m_inputMethodData; + static AdjustWindowRectExForDpiFunc *lpAdjustWindowRectExForDpi; + /* track display changes - used by palette-updating code. This is a workaround for a windows bug that prevents WM_PALETTECHANGED event from occurring immediately after From cdbad6758313bb8b137acd6c9f1c2ccc15020bc8 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 11 Apr 2019 13:24:53 +0300 Subject: [PATCH 132/976] IDEA-210154 Borderless UI: Top frame of IDEA window is blue (cherry picked from commit 2dd4163bc4145fb0230816963443673feb20f5a2) --- .../native/libawt/windows/awt_DesktopProperties.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index 8720cea32e12..31367c0c22f0 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -494,6 +494,16 @@ void CheckFontSmoothingSettings(HWND hWnd) { } } +BOOL ColorizationColorAffectsBorders() { + DWORD result = 0; + DWORD bufSize(sizeof(DWORD)); + HKEY hKey = NULL; + if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\DWM"), 0, KEY_READ, &hKey) != ERROR_SUCCESS) return TRUE; + if (::RegQueryValueEx(hKey, _T("ColorPrevalence"), NULL, NULL, reinterpret_cast(&result), &bufSize) != ERROR_SUCCESS) return TRUE; + RegCloseKey(hKey); + return result == 0 ? FALSE : TRUE; +} + void AwtDesktopProperties::GetColorParameters() { SetColorProperty(TEXT("win.frame.activeCaptionGradientColor"), @@ -520,6 +530,7 @@ void AwtDesktopProperties::GetColorParameters() { // [tav] todo: listen WM_DWMCOLORIZATIONCOLORCHANGED DwmGetColorizationColor(&color, &opaque); SetColorProperty(TEXT("win.dwm.colorizationColor"), RGB(GetBValue(color), GetGValue(color), GetRValue(color))); + SetBooleanProperty(TEXT("win.dwm.colorizationColor.affects.borders"), ColorizationColorAffectsBorders()); } // ?? ?? ?? From 4a360c9bcc3e53babcfd757efd251b9bc3d1bb18 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 16 May 2019 18:27:24 +0300 Subject: [PATCH 133/976] JBR-1427 pycharm jupyter preview stuck and no response when click on preview. (cherry picked from commit 1746b04686e97b570c9089b33db9c20799e9f955) --- .../macosx/classes/sun/lwawt/macosx/CInputMethod.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index 774b936e8729..3ffc6ebbac4b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -758,7 +758,7 @@ public void run() { synchronized(rect) { } } }} - }, fAwtFocussedComponent); + }, fAwtFocussedComponent, true); // [tav] avoid deadlock with javafx } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(rect) { return rect; } @@ -779,7 +779,7 @@ public void run() { synchronized(offsetInfo) { offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY); insertPositionOffset[0] = fIMContext.getInsertPositionOffset(); }} - }, fAwtFocussedComponent); + }, fAwtFocussedComponent, true); // [tav] avoid deadlock with javafx } catch (InvocationTargetException ite) { ite.printStackTrace(); } // This bit of gymnastics ensures that the returned location is within the composed text. From e2beb0701858944d8f13f3bf097e1d0a00cf5d68 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 24 Jun 2019 14:28:43 +0300 Subject: [PATCH 134/976] JBR-1492 Not able to start Intellij Idea 2017.2.5 with modified vmoptions (cherry picked from commit e7ca6db66b2310cb3ec0928fddd72d4c55d87660) --- .../com/apple/laf/AquaImageFactory.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java index 2fddf6483a5d..a1371c416889 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java @@ -84,11 +84,11 @@ public static IconUIResource getLockImageIcon() { @SuppressWarnings("removal") static Image getGenericJavaIcon() { - return java.security.AccessController.doPrivileged(new PrivilegedAction() { + return checkValidOrStub(java.security.AccessController.doPrivileged(new PrivilegedAction() { public Image run() { return com.apple.eawt.Application.getApplication().getDockIconImage(); } - }); + })); } @SuppressWarnings("removal") @@ -521,4 +521,23 @@ public static Color getSelectionInactiveForegroundColorUIResource() { public static Color getSelectedControlColorUIResource() { return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.SELECTED_CONTROL_TEXT_COLOR)); } + + private static class EmptyImage { + static final BufferedImage INSTANCE; + static { + INSTANCE = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); + Graphics g = INSTANCE.createGraphics(); + g.setColor(new Color(0, 0, 0, 0)); + g.fillRect(0, 0, 16, 16); + g.dispose(); + } + } + + // [tav] a workaround for JBR-1492 + private static Image checkValidOrStub(Image image) { + if (image == null || image.getWidth(null) <= 0 || image.getHeight(null) <= 0) { + return EmptyImage.INSTANCE; + } + return image; + } } From 5647a552343c671517df9b4f75a00e899cba0dd6 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 26 Jun 2019 14:39:30 +0300 Subject: [PATCH 135/976] JBR-1629 Maximized window cut at the right and bottom (cherry picked from commit 9e768377db0ea999bd372444d0acc5c22910e861) --- .../windows/native/libawt/windows/awt_Frame.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index cd2f05e6674d..224da30afc55 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1680,7 +1680,16 @@ void GetSysInsets(RECT* insets, AwtFrame* pFrame) { return; } Devices::InstanceAccess devices; - AwtWin32GraphicsDevice* device = devices->GetDevice(AwtWin32GraphicsDevice::DeviceIndexForWindow(pFrame->GetHWnd())); + HMONITOR hmon; + if (::IsZoomed(pFrame->GetHWnd())) { + WINDOWPLACEMENT wp; + ::GetWindowPlacement(pFrame->GetHWnd(), &wp); + hmon = ::MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST); + } else { + // this method can return wrong monitor in a zoomed state in multi-dpi env + hmon = ::MonitorFromWindow(pFrame->GetHWnd(), MONITOR_DEFAULTTONEAREST); + } + AwtWin32GraphicsDevice* device = devices->GetDevice(AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hmon)); int dpi = device ? device->GetScaleX() * 96 : 96; // GetSystemMetricsForDpi gives incorrect values, use AdjustWindowRectExForDpi for border metrics instead From 9982529ab883bc41a7668b77499a477d57dd1d3f Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 8 Jul 2019 18:51:30 +0300 Subject: [PATCH 136/976] JBR-1650 propagate custom decoration title bar height to native (cherry picked from commit f6fc65d0149bba71f8ec9386376df1d8994312bf) --- .../classes/sun/awt/windows/WWindowPeer.java | 22 +++++++++++++++---- .../native/libawt/windows/awt_Frame.cpp | 11 +++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index df6594990f22..1caa2aa3ae19 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -995,17 +995,31 @@ private Point2D getInsetsRoundingError(SunGraphics2D g) { return err; } - private volatile List hitTestSpots; + private volatile List customDecorHitTestSpots; + private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected + // called from client via reflection private void setCustomDecorationHitTestSpots(List hitTestSpots) { - this.hitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots); + this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots); } + // called from client via reflection + private void setCustomDecorationTitleBarHeight(int height) { + if (height >= 0) customDecorTitleBarHeight = height; + } + + // called from native private boolean hitTestCustomDecoration(int x, int y) { - if (hitTestSpots == null) return false; - for (Rectangle spot : hitTestSpots) { + List spots = customDecorHitTestSpots; + if (spots == null) return false; + for (Rectangle spot : spots) { if (spot.contains(x, y)) return true; } return false; } + + // called from native + private int getCustomDecorationTitleBarHeight() { + return customDecorTitleBarHeight; + } } diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 224da30afc55..2f198125e5c9 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1710,6 +1710,16 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { RECT rcFrame = {}; AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL); + JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + int titleHeight = (int)JNU_CallMethodByName(env, NULL, frame->GetPeer(env), + "getCustomDecorationTitleBarHeight", "()I", + frame->ScaleDownX(x - rcWindow.left), + frame->ScaleDownY(y - rcWindow.top)).i; + if (titleHeight >= 0) { + titleHeight = frame->ScaleUpY(titleHeight); + insets.top = titleHeight; // otherwise leave default + } + USHORT uRow = 1; USHORT uCol = 1; BOOL fOnResizeBorder = FALSE; @@ -1717,7 +1727,6 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) { if (y >= rcWindow.top && y < rcWindow.top + insets.top) { - JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env), "hitTestCustomDecoration", "(II)Z", frame->ScaleDownX(x - rcWindow.left), From 85e45abc50354e21c821ad3da88687430b462580 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 18 Jul 2019 17:01:18 +0300 Subject: [PATCH 137/976] JBR-1669 IDE-managed HiDPI mode is broken (cherry picked from commit 461b0b5cd4c9a770497f7a6e4ef0bcbf59d08aea) --- src/java.desktop/share/classes/javax/swing/UIManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/UIManager.java b/src/java.desktop/share/classes/javax/swing/UIManager.java index fe23e1d21e0f..bd75ce45ce47 100644 --- a/src/java.desktop/share/classes/javax/swing/UIManager.java +++ b/src/java.desktop/share/classes/javax/swing/UIManager.java @@ -61,7 +61,7 @@ import java.util.Objects; import sun.awt.AppContext; import sun.awt.AWTAccessor; - +import java.awt.GraphicsEnvironment; /** * {@code UIManager} manages the current look and feel, the set of @@ -384,6 +384,11 @@ public String toString() { if (osType == OSInfo.OSType.WINDOWS) { iLAFs.add(new LookAndFeelInfo("Windows", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel")); + if (!GraphicsEnvironment.isHeadless()) { + // Force DPI settings in Win32GraphicsEnvironment.initDisplayWrapper() + // prior to font size settings in desktop properties. + GraphicsEnvironment.getLocalGraphicsEnvironment(); + } if (Toolkit.getDefaultToolkit().getDesktopProperty( "win.xpstyle.themeActive") != null) { iLAFs.add(new LookAndFeelInfo("Windows Classic", From edb6aaefa52ed4ab37b480aabf917384030f5747 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 2 Aug 2019 20:17:31 +0300 Subject: [PATCH 138/976] JBR-1693 difficult to input Japanese text with "Fast" Key Repeat (cherry picked from commit 12de3e287ed726b385c7d37e41a1a79fdcf284ee) --- .../sun/lwawt/macosx/CInputMethod.java | 167 ++++++++++++++---- 1 file changed, 129 insertions(+), 38 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index 3ffc6ebbac4b..e727f34467fe 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -26,6 +26,7 @@ package sun.lwawt.macosx; import java.awt.im.spi.*; +import java.lang.reflect.Method; import java.util.*; import java.awt.*; import java.awt.peer.*; @@ -36,17 +37,21 @@ import java.lang.reflect.InvocationTargetException; import java.text.AttributedCharacterIterator.Attribute; import java.text.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.text.JTextComponent; import sun.awt.AWTAccessor; +import sun.awt.AppContext; +import sun.awt.SunToolkit; import sun.awt.im.InputMethodAdapter; import sun.lwawt.*; import static sun.awt.AWTAccessor.ComponentAccessor; public class CInputMethod extends InputMethodAdapter { - private InputMethodContext fIMContext; - private Component fAwtFocussedComponent; + private volatile InputMethodContext fIMContext; + private volatile Component fAwtFocussedComponent; private LWComponentPeer fAwtFocussedComponentPeer; private boolean isActive; @@ -728,37 +733,38 @@ private synchronized int[] firstRectForCharacterRange(final int absoluteTextOffs final int[] rect = new int[4]; try { - if (fIMContext != null) - LWCToolkit.invokeAndWait(new Runnable() { - public void run() { synchronized(rect) { - int insertOffset = fIMContext.getInsertPositionOffset(); - int composedTextOffset = absoluteTextOffset - insertOffset; - if (composedTextOffset < 0) composedTextOffset = 0; - Rectangle r = fIMContext.getTextLocation(TextHitInfo.beforeOffset(composedTextOffset)); - rect[0] = r.x; - rect[1] = r.y; - rect[2] = r.width; - rect[3] = r.height; - - // This next if-block is a hack to work around a bug in JTextComponent. getTextLocation ignores - // the TextHitInfo passed to it and always returns the location of the insertion point, which is - // at the start of the composed text. We'll do some calculation so the candidate window for Kotoeri - // follows the requested offset into the composed text. - if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) { - Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0)); - - if (r.equals(r2) && fCurrentTextAsString != null) { - // FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate - // window off the right edge of the component. - String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset); - Graphics g = fAwtFocussedComponent.getGraphics(); - int xOffset = g.getFontMetrics().stringWidth(inProgressSubstring); - rect[0] += xOffset; - g.dispose(); + if (fIMContext != null) { + FxInvoker.invoke(() -> { + synchronized (rect) { + int insertOffset = fIMContext.getInsertPositionOffset(); + int composedTextOffset = absoluteTextOffset - insertOffset; + if (composedTextOffset < 0) composedTextOffset = 0; + Rectangle r = fIMContext.getTextLocation(TextHitInfo.beforeOffset(composedTextOffset)); + rect[0] = r.x; + rect[1] = r.y; + rect[2] = r.width; + rect[3] = r.height; + + // This next if-block is a hack to work around a bug in JTextComponent. getTextLocation ignores + // the TextHitInfo passed to it and always returns the location of the insertion point, which is + // at the start of the composed text. We'll do some calculation so the candidate window for Kotoeri + // follows the requested offset into the composed text. + if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) { + Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0)); + + if (r.equals(r2) && fCurrentTextAsString != null) { + // FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate + // window off the right edge of the component. + String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset); + Graphics g = fAwtFocussedComponent.getGraphics(); + int xOffset = g.getFontMetrics().stringWidth(inProgressSubstring); + rect[0] += xOffset; + g.dispose(); + } } } - }} - }, fAwtFocussedComponent, true); // [tav] avoid deadlock with javafx + }, (sun.awt.im.InputContext)fIMContext, fAwtFocussedComponent); + } } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(rect) { return rect; } @@ -773,13 +779,14 @@ private synchronized int characterIndexForPoint(final int screenX, final int scr final int[] insertPositionOffset = new int[1]; try { - if (fIMContext != null) - LWCToolkit.invokeAndWait(new Runnable() { - public void run() { synchronized(offsetInfo) { - offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY); - insertPositionOffset[0] = fIMContext.getInsertPositionOffset(); - }} - }, fAwtFocussedComponent, true); // [tav] avoid deadlock with javafx + if (fIMContext != null) { + FxInvoker.invoke(() -> { + synchronized (offsetInfo) { + offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY); + insertPositionOffset[0] = fIMContext.getInsertPositionOffset(); + } + }, (sun.awt.im.InputContext)fIMContext, fAwtFocussedComponent); + } } catch (InvocationTargetException ite) { ite.printStackTrace(); } // This bit of gymnastics ensures that the returned location is within the composed text. @@ -829,4 +836,88 @@ public String getNativeInputMethodInfo() // Initialize toolbox routines static native void nativeInit(); + + private static class FxInvoker { + final static Method GET_CLIENT_COMPONENT_METHOD; + static Class JFX_PANEL_CLASS; + + static { + Method m = null; + try { + m = sun.awt.im.InputContext.class.getDeclaredMethod("getClientComponent"); + if (m != null) m.setAccessible(true); + } catch (NoSuchMethodException ignore) { + } + GET_CLIENT_COMPONENT_METHOD = m; + } + + static Component getClientComponent(sun.awt.im.InputContext ctx) { + if (GET_CLIENT_COMPONENT_METHOD != null) { + try { + return (Component)GET_CLIENT_COMPONENT_METHOD.invoke(ctx); + } catch (IllegalAccessException | InvocationTargetException ignore) { + } + } + return null; + } + + static boolean instanceofJFXPanel(Component clientComponent) { + if (clientComponent != null) { + if (JFX_PANEL_CLASS == null) { + try { + // the class is not available in the current class loader context, use the client class loader + JFX_PANEL_CLASS = Class.forName("javafx.embed.swing.JFXPanel", false, clientComponent.getClass().getClassLoader()); + } catch (ClassNotFoundException ignore) { + } + } + if (JFX_PANEL_CLASS != null) { + return JFX_PANEL_CLASS.isInstance(clientComponent); + } + } + return false; + } + + static void await(CountDownLatch latch) { + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + // Executed on AppKit + static void invoke(Runnable runnable, sun.awt.im.InputContext inputContext, Component targetToAppContext) throws InvocationTargetException { + CountDownLatch edtLatch = new CountDownLatch(1); + CountDownLatch tkLatch = new CountDownLatch(1); + AtomicBoolean runOnAppKit = new AtomicBoolean(false); + + // Emulate EventQueue.invokeAndWait(runnable) for the runnable that delegates execution + // back to AppKit (JavaFX Event thread), without running secondary loop on AppKit. + + InvocationEvent event = new InvocationEvent(targetToAppContext, () -> { + try { + runOnAppKit.set(instanceofJFXPanel(getClientComponent(inputContext))); + if (!runOnAppKit.get()) { + runnable.run(); + } + } finally { + edtLatch.countDown(); + await(tkLatch); + } + }); + assert targetToAppContext != null; + AppContext appContext = SunToolkit.targetToAppContext(targetToAppContext); + SunToolkit.postEvent(appContext, event); + SunToolkit.flushPendingEvents(appContext); + + await(edtLatch); + try { + if (runOnAppKit.get()) { + runnable.run(); + } + } finally { + tkLatch.countDown(); + } + } + } } From b94e21815d26dc12bd1b495455ed0e8179db0902 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 21 Aug 2019 14:41:50 +0300 Subject: [PATCH 139/976] JBR-1770 [windows] frame does not open as maximized (cherry picked from commit d9dfc3c6c53785b296e3f95615a3d4861db1989b) --- .../windows/native/libawt/windows/awt_Frame.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 2f198125e5c9..2f5bdd229b2e 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1419,6 +1419,16 @@ void AwtFrame::_SetState(void *param) f->setIconic(iconify); f->setZoomed(zoom); + + // [tav] With custom decor enabled, MS Win will send WM_SIZE msg w/o SIZE_MAXIMIZED param set + // before the frame will be shown. The msg handler will drop the maximized state in response. + // In order to prevent that, we set the maximized state on the native frame in advance. + if (zoom && f->HasCustomDecoration()) { + WINDOWPLACEMENT wp; + ::GetWindowPlacement(f->GetHWnd(), &wp); + wp.showCmd = SW_SHOWMAXIMIZED; + ::SetWindowPlacement(f->GetHWnd(), &wp); + } } } ret: From 9ebf0a1991c49461497e4a9397001259fde43653 Mon Sep 17 00:00:00 2001 From: Vyacheslav Moklev Date: Thu, 16 May 2019 10:00:44 +0300 Subject: [PATCH 140/976] JBR-1509 Client area size is wrong in Borderless mode Fix client area size (cherry picked from commit 00d32e58dc3941f5e4ec1885114189678933e311) --- .../windows/native/libawt/windows/awt_Frame.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 2f5bdd229b2e..d6273c424c21 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1779,18 +1779,21 @@ MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESU GetSysInsets(&insets, this); RECT* rect = &lpncsp->rgrc[0]; - rect->left = rect->left + insets.left; + rect->left += insets.left; + rect->right -= insets.right; + rect->bottom -= insets.bottom; + if (::IsZoomed(GetHWnd())) { - lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + insets.bottom; + rect->top += insets.bottom; + // [moklev] Workaround for RIDER-27069, IDEA-211327 + rect->right += this->ScaleUpX(1); + rect->bottom -= 1; } else { // this makes the native caption go uncovered // int yBorder = ::GetSystemMetrics(SM_CYBORDER); - // lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + yBorder; + // rect->top += yBorder; } - rect->right = rect->right - insets.right; - rect->bottom = rect->bottom - insets.bottom; - retVal = 0L; return mrConsume; } From 627fa65d27326d7448ee37c2a90220495c291aa4 Mon Sep 17 00:00:00 2001 From: Vyacheslav Moklev Date: Thu, 30 May 2019 11:02:00 +0300 Subject: [PATCH 141/976] JBR-1552 Invalid screen bounds in full screen mode Check is window is not in undecorated state (cherry picked from commit 5547701e2cedeb4fc5788ba9e243f5c838fc44f6) --- .../windows/native/libawt/windows/awt_Frame.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index d6273c424c21..08521975e997 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1786,8 +1786,10 @@ MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESU if (::IsZoomed(GetHWnd())) { rect->top += insets.bottom; // [moklev] Workaround for RIDER-27069, IDEA-211327 - rect->right += this->ScaleUpX(1); - rect->bottom -= 1; + if (!this->IsUndecorated()) { + rect->right += this->ScaleUpX(1); + rect->bottom -= 1; + } } else { // this makes the native caption go uncovered From beace4fa2da3e9bc5bf65fe93a1da2908ef96c16 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 26 Aug 2019 16:51:59 +0300 Subject: [PATCH 142/976] JBR-1786 Weird white border for IDE window (cherry picked from commit 4b09614a0e5cefe780f10ca705ca55ae8ab0deda) --- .../windows/native/libawt/windows/awt_Frame.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 08521975e997..3f1f245a91ec 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -30,6 +30,7 @@ #include "awt_IconCursor.h" #include "awt_Win32GraphicsDevice.h" #include "ComCtl32Util.h" +#include "shellapi.h" #include #include @@ -1788,7 +1789,15 @@ MsgRouting AwtFrame::WmNcCalcSize(BOOL wParam, LPNCCALCSIZE_PARAMS lpncsp, LRESU // [moklev] Workaround for RIDER-27069, IDEA-211327 if (!this->IsUndecorated()) { rect->right += this->ScaleUpX(1); - rect->bottom -= 1; + // [tav] Decrement NC bottom only when taskbar is bottom/autohide (JBR-1786) + APPBARDATA abData; + abData.cbSize = sizeof(abData); + if (::SHAppBarMessage(ABM_GETTASKBARPOS, &abData) && + abData.uEdge == ABE_BOTTOM && + ::SHAppBarMessage(ABM_GETSTATE, &abData) == ABS_AUTOHIDE) + { + rect->bottom -= 1; + } } } else { From 7e3102dcd3c38be9eb7e98a8e54c8d61f5155894 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 26 Aug 2019 17:24:19 +0300 Subject: [PATCH 143/976] JBR-1609 Jupyter Notebook eventually causes IDEA to become unresponsive on Mac OSX (cherry picked from commit 8ae0be8eb6dec53d8e5f30de41a47ff7e2cd80da) --- .../sun/lwawt/macosx/CInputMethod.java | 43 ++++--------------- .../classes/sun/lwawt/macosx/LWCToolkit.java | 4 +- 2 files changed, 11 insertions(+), 36 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index e727f34467fe..14ba72809680 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -877,46 +877,21 @@ static boolean instanceofJFXPanel(Component clientComponent) { return false; } - static void await(CountDownLatch latch) { - try { - latch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - // Executed on AppKit static void invoke(Runnable runnable, sun.awt.im.InputContext inputContext, Component targetToAppContext) throws InvocationTargetException { - CountDownLatch edtLatch = new CountDownLatch(1); - CountDownLatch tkLatch = new CountDownLatch(1); AtomicBoolean runOnAppKit = new AtomicBoolean(false); - // Emulate EventQueue.invokeAndWait(runnable) for the runnable that delegates execution - // back to AppKit (JavaFX Event thread), without running secondary loop on AppKit. - - InvocationEvent event = new InvocationEvent(targetToAppContext, () -> { - try { - runOnAppKit.set(instanceofJFXPanel(getClientComponent(inputContext))); - if (!runOnAppKit.get()) { - runnable.run(); - } - } finally { - edtLatch.countDown(); - await(tkLatch); - } - }); - assert targetToAppContext != null; - AppContext appContext = SunToolkit.targetToAppContext(targetToAppContext); - SunToolkit.postEvent(appContext, event); - SunToolkit.flushPendingEvents(appContext); - - await(edtLatch); - try { - if (runOnAppKit.get()) { + // 1) Do not run secondary msg loop in this case. + // 2) Delegate runnable back to FX when applicable. + LWCToolkit.invokeAndWait(() -> { + runOnAppKit.set(instanceofJFXPanel(getClientComponent(inputContext))); + if (!runOnAppKit.get()) { runnable.run(); } - } finally { - tkLatch.countDown(); + }, targetToAppContext); + + if (runOnAppKit.get()) { + runnable.run(); } } } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index d4ffba2a85e1..101f51b089f3 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -498,9 +498,9 @@ public int getScreenResolution() throws HeadlessException { public Insets getScreenInsets(final GraphicsConfiguration gc) { GraphicsDevice gd = gc.getDevice(); if (!(gd instanceof CGraphicsDevice)) { - return super.getScreenInsets(gc); + return LWCToolkit.SelectorPerformer.perform(() -> super.getScreenInsets(gc)); } - return ((CGraphicsDevice)gd).getScreenInsets(); + return LWCToolkit.SelectorPerformer.perform(() -> ((CGraphicsDevice)gd).getScreenInsets()); } @Override From 3f70b9a5498071fb5541232ecbb0bf4c369173a3 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 27 Aug 2019 22:40:50 +0300 Subject: [PATCH 144/976] JBR-1795 Project opened from Welcome screen goes to backgound after loading (cherry picked from commit 322526458ab93e2af595ffbc7d90c603e3c7ac55) --- .../native/libawt/windows/awt_Frame.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 3f1f245a91ec..0b12888140c3 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -786,6 +786,24 @@ AwtFrame::Show() } else { ::ShowWindow(hwnd, SW_SHOWMAXIMIZED); } + + // [tav] Workaround for unclear platform behaviour. + // When a custom decor frame is being shown maximized at the moment + // some another AWT window is still foreground - the frame can go + // in background when shown if: + // 1) the other AWT window is closed the moment after frame's show + // 2) some another maximized window is behind the frame, it steals activation + if (HasCustomDecoration()) { + HWND fgHWnd = ::GetForegroundWindow(); + if (fgHWnd != NULL && + GetComponent(fgHWnd) != NULL && // it's awt window + IsFocusableWindow() && + IsAutoRequestFocus() && + !::IsWindow(GetModalBlocker(GetHWnd()))) + { + ::SetForegroundWindow(GetHWnd()); + } + } } else if (m_isInputMethodWindow) { // Don't activate input methow window From 8022c5fa808e9f0cda3f7139bc09b9875fda05de Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 30 Aug 2019 12:13:35 +0300 Subject: [PATCH 145/976] JBR-1802 com/sun/java/accessibility/util/8051626/Bug8051626.java: access denied ("java.lang.RuntimePermission" "getClassLoader") (cherry picked from commit eae772aca986710c0ac3f3ae40d492928b966266) --- .../classes/sun/lwawt/macosx/LWCToolkit.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 101f51b089f3..b6a94876482b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -757,19 +757,21 @@ private T performImpl(Callable selector) { assert EventQueue.isDispatchThread(); if (executor == null) { // init on EDT - executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), - new ThreadFactory() { - private ThreadFactory factory = Executors.privilegedThreadFactory(); - @Override - public Thread newThread(Runnable r) { - Thread t = factory.newThread(r); - t.setDaemon(true); - t.setName("AWT-SelectorPerformer " + t.getName()); - return t; - } - }); + AccessController.doPrivileged((PrivilegedAction)() -> + executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + new ThreadFactory() { + private ThreadFactory factory = Executors.privilegedThreadFactory(); + @Override + public Thread newThread(Runnable r) { + Thread t = factory.newThread(r); + t.setDaemon(true); + t.setName("AWT-SelectorPerformer " + t.getName()); + return t; + } + }) + ); } LinkedBlockingQueue currentQueue; synchronized (invocations) { From 6982be5a401d5feba31f6e839f295cbd1c0859df Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 5 Sep 2019 12:56:14 +0300 Subject: [PATCH 146/976] JBR-1824 export NSWindow::setIgnoresMouseEvents to java internal API (cherry picked from commit 4399dc382c402ec26c62c12d5be8011900165ddd) --- .../macosx/native/libawt_lwawt/awt/AWTWindow.m | 18 +++++++++++++++++- .../share/classes/java/awt/Window.java | 13 +++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index 77d1e216a75c..d71acb4dc0de 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -1131,6 +1131,17 @@ + (AWTWindow *) lastKeyWindow { NSView *contentView = OBJC(contentViewPtr); NSRect frameRect = NSMakeRect(x, y, w, h); AWTWindow *owner = [OBJC(ownerPtr) delegate]; + + BOOL isIgnoreMouseEvents = NO; + GET_CPLATFORM_WINDOW_CLASS_RETURN(nil); + DECLARE_FIELD_RETURN(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;", nil); + jobject awtWindow = (*env)->GetObjectField(env, obj, jf_target); + if (awtWindow != NULL) { + DECLARE_CLASS_RETURN(jc_Window, "java/awt/Window", nil); + DECLARE_METHOD_RETURN(jm_isIgnoreMouseEvents, jc_Window, "isIgnoreMouseEvents", "()Z", nil); + isIgnoreMouseEvents = (*env)->CallBooleanMethod(env, awtWindow, jm_isIgnoreMouseEvents) == JNI_TRUE ? YES : NO; + (*env)->DeleteLocalRef(env, awtWindow); + } [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ window = [[AWTWindow alloc] initWithPlatformWindow:platformWindow @@ -1140,7 +1151,12 @@ + (AWTWindow *) lastKeyWindow { contentView:contentView]; // the window is released is CPlatformWindow.nativeDispose() - if (window) [window.nsWindow retain]; + if (window) { + [window.nsWindow retain]; + if (isIgnoreMouseEvents) { + [window.nsWindow setIgnoresMouseEvents:YES]; + } + } }]; JNI_COCOA_EXIT(env); diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index e97bdba9b7d7..531d90bbf327 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -4007,6 +4007,19 @@ void setHasCustomDecoration() { hasCustomDecoration = true; } + private volatile boolean ignoreMouseEvents; + + boolean isIgnoreMouseEvents() { + return ignoreMouseEvents; + } + + /** + * Set via reflection (JB JdkEx API). + */ + void setIgnoreMouseEvents(boolean ignore) { + ignoreMouseEvents = ignore; + } + // ************************** MIXING CODE ******************************* // A window has an owner, but it does NOT have a container From 36867af4a00c47c443405a57c8f0f02b22212b77 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 25 Nov 2019 12:08:51 +0300 Subject: [PATCH 147/976] JBR-1976 [jcef] need mouse-transparent window on Windows (cherry picked from commit b60fac96b4a114a992ec9ea3cba6f17b4adbefeb) --- src/java.desktop/windows/native/libawt/windows/awt_Window.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 3d3e7355095d..7c29d22f4925 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -1111,6 +1111,9 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent) if (env->ExceptionCheck()) goto done; DWORD style = WS_CLIPCHILDREN | WS_POPUP; DWORD exStyle = WS_EX_NOACTIVATE; + if (JNU_CallMethodByName(env, NULL, target, "isIgnoreMouseEvents", "()Z").z) { + exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT; + } if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; if (GetRTLReadingOrder()) From 9af6999a5fa3f30d383defba8559786977185cb6 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 11 Dec 2019 11:45:13 +0300 Subject: [PATCH 148/976] Comment assertion (originally JRE-965) The assert line crashes debug hotspot. (cherry picked from commit a00074a86c4896d7356467626e294c3b82defc1d) --- src/hotspot/share/opto/loopPredicate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index fd0576832cf7..a74c1a183ba9 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1223,7 +1223,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod Node* idx = cmp->in(1); assert(!invar.is_invariant(idx), "index is variant"); Node* rng = cmp->in(2); - assert(rng->Opcode() == Op_LoadRange || iff->is_RangeCheck() || _igvn.type(rng)->is_int()->_lo >= 0, "must be"); + // [tav: crash] assert(rng->Opcode() == Op_LoadRange || iff->is_RangeCheck() || _igvn.type(rng)->is_int()->_lo >= 0, "must be"); assert(invar.is_invariant(rng), "range must be invariant"); int scale = 1; Node* offset = zero; From 464f0e2a22679816344a280dd984c521916ae6db Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 13 Dec 2019 15:14:17 +0300 Subject: [PATCH 149/976] JBR-2019 provide getWindowHandle method for jcef (cherry picked from commit 7ae706b629435f06540ef2c8b1fec2f452b194e6) --- .../macosx/classes/sun/lwawt/LWWindowPeer.java | 14 ++++++++++++++ .../share/classes/java/awt/peer/WindowPeer.java | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 7f218e4d1baa..b8bc89466856 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -79,6 +79,7 @@ import sun.java2d.loops.Blit; import sun.java2d.loops.CompositeType; import sun.java2d.pipe.Region; +import sun.lwawt.macosx.CPlatformWindow; import sun.util.logging.PlatformLogger; public class LWWindowPeer @@ -1523,4 +1524,17 @@ public void updateSecurityWarningVisibility() { public String toString() { return super.toString() + " [target is " + getTarget() + "]"; } + + /** + * [tav] Used externally. + */ + @Override + public long getWindowHandle() { + final long[] handle = new long[1]; + PlatformWindow window = getPlatformWindow(); + if (window instanceof CPlatformWindow) { + ((CPlatformWindow)window).execute(ptr -> handle[0] = ptr); + } + return handle[0]; + } } diff --git a/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java b/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java index fcfb6d2a899a..b62965631840 100644 --- a/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java +++ b/src/java.desktop/share/classes/java/awt/peer/WindowPeer.java @@ -126,6 +126,15 @@ public interface WindowPeer extends ContainerPeer { */ default Insets getSysInsets() { return null; } + /** + * Returns platform window handle. + * + * @return the window handle + */ + default long getWindowHandle() { + throw new UnsupportedOperationException("unimplemented"); + } + /** * Requests a GC that best suits this Window. The returned GC may differ * from the requested GC passed as the argument to this method. This method From abdb45ecc77e1f58b66e63bf372048c05654d5de Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Wed, 16 Jan 2019 16:52:26 +0300 Subject: [PATCH 150/976] JRE-1083 [JDK11] Test com/sun/java/accessibility/util/8051626/Bug8051626.java fails on macOS on JB JDK11b Wrapped SelectorPerformer invocation into privileged action (cherry picked from commit 48e7b547aec575d691b08ca9e11c8418187b147e) --- .../sun/lwawt/macosx/CPlatformWindow.java | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 1d4e80f8fb73..7f520fd0a991 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -25,6 +25,7 @@ package sun.lwawt.macosx; +import java.awt.AWTError; import java.awt.Color; import java.awt.Component; import java.awt.DefaultKeyboardFocusManager; @@ -53,7 +54,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.Callable; +import java.security.PrivilegedAction; import javax.swing.JRootPane; import javax.swing.RootPaneContainer; @@ -345,28 +346,35 @@ public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner } else { bounds = _peer.constrainBounds(_target.getBounds()); } - long nativeWindowPtr = LWCToolkit.SelectorPerformer.perform(() -> { - AtomicLong ref = new AtomicLong(); - contentView.execute(viewPtr -> { - boolean hasOwnerPtr = false; - - if (owner != null) { - hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> { - ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits, - bounds.x, bounds.y, - bounds.width, bounds.height)); - return 1; - }); - } - - if (!hasOwnerPtr) { - ref.set(nativeCreateNSWindow(viewPtr, 0, - styleBits, bounds.x, bounds.y, - bounds.width, bounds.height)); - } - }); - return ref.get(); - }); + long nativeWindowPtr = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> { + try { + return LWCToolkit.SelectorPerformer.perform(() -> { + AtomicLong ref = new AtomicLong(); + contentView.execute(viewPtr -> { + boolean hasOwnerPtr = false; + + if (owner != null) { + hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> { + ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits, + bounds.x, bounds.y, + bounds.width, bounds.height)); + return 1; + }); + } + + if (!hasOwnerPtr) { + ref.set(nativeCreateNSWindow(viewPtr, 0, + styleBits, bounds.x, bounds.y, + bounds.width, bounds.height)); + } + }); + return ref.get(); + }); + } catch (Throwable throwable) { + throw new AWTError(throwable.getMessage()); + } + }); setPtr(nativeWindowPtr); if (peer != null) { // Not applicable to CWarningWindow peer.setTextured(IS(TEXTURED, styleBits)); From f6d7c48ad0609368436eec1714288de730ad4499 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 19 Mar 2021 20:03:04 +0300 Subject: [PATCH 151/976] JBR-2031 [mac] jcef deadlocks with a11y on start (cherry picked from commit 4f44b37f08d13e91d006bdc3003ffc58232b8ace) --- .../sun/lwawt/macosx/CPlatformWindow.java | 3 +- .../classes/sun/lwawt/macosx/LWCToolkit.java | 163 +----------------- .../sun/awt/InvokeOnToolkitHelper.java | 157 +++++++++++++++++ 3 files changed, 164 insertions(+), 159 deletions(-) create mode 100644 src/java.desktop/share/classes/sun/awt/InvokeOnToolkitHelper.java diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 7f520fd0a991..5fa2a9fa8db1 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -65,6 +65,7 @@ import sun.awt.AWTAccessor; import sun.awt.AWTAccessor.ComponentAccessor; import sun.awt.AWTAccessor.WindowAccessor; +import sun.awt.InvokeOnToolkitHelper; import sun.java2d.SurfaceData; import sun.lwawt.LWLightweightFramePeer; import sun.lwawt.LWToolkit; @@ -349,7 +350,7 @@ public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner long nativeWindowPtr = java.security.AccessController.doPrivileged( (PrivilegedAction) () -> { try { - return LWCToolkit.SelectorPerformer.perform(() -> { + return InvokeOnToolkitHelper.invokeAndBlock(() -> { AtomicLong ref = new AtomicLong(); contentView.execute(viewPtr -> { boolean hasOwnerPtr = false; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index b6a94876482b..dcab8074f961 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -85,24 +85,15 @@ import java.awt.peer.TrayIconPeer; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.UndeclaredThrowableException; -import java.net.MalformedURLException; import java.net.URL; import java.security.*; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import java.net.MalformedURLException; import javax.swing.UIManager; import com.apple.laf.AquaMenuBarUI; -import sun.awt.AWTAccessor; -import sun.awt.AppContext; -import sun.awt.CGraphicsDevice; -import sun.awt.LightweightFrame; -import sun.awt.PlatformGraphicsInfo; -import sun.awt.SunToolkit; +import sun.awt.*; import sun.awt.datatransfer.DataTransferer; import sun.awt.dnd.SunDragSourceContextPeer; import sun.awt.util.ThreadGroupUtils; @@ -498,9 +489,9 @@ public int getScreenResolution() throws HeadlessException { public Insets getScreenInsets(final GraphicsConfiguration gc) { GraphicsDevice gd = gc.getDevice(); if (!(gd instanceof CGraphicsDevice)) { - return LWCToolkit.SelectorPerformer.perform(() -> super.getScreenInsets(gc)); + return InvokeOnToolkitHelper.invokeAndBlock(() -> super.getScreenInsets(gc)); } - return LWCToolkit.SelectorPerformer.perform(() -> ((CGraphicsDevice)gd).getScreenInsets()); + return InvokeOnToolkitHelper.invokeAndBlock(() -> ((CGraphicsDevice)gd).getScreenInsets()); } @Override @@ -707,150 +698,6 @@ public T getResult() throws Exception { } } - /** - * Performs a wrapped native selector on the main thread, waiting on EDT, preventing the threads from a deadlock. - */ - public static class SelectorPerformer { - private ExecutorService executor; - // every perform() pushes a queue of invocations - private Stack> invocations = new Stack<>(); - - // invocations should be dispatched on proper EDT (per AppContext) - private static final Map edt2performer = new ConcurrentHashMap<>(); - - private static final int WAIT_LIMIT_SECONDS = 5; - - private SelectorPerformer() {} - - /** - * Performs the selector wrapped in the callable. The selector should be executed via [JNFRunLoop performOnMainThreadWaiting:YES ...] - * on the native side so that the native doAWTRunLoop, which is run in [JNFRunLoop javaRunLoopMode], accepts it. - * The callable wrapper should not call any Java code which would normally be called on EDT. - *

- * If the main thread posts invocation events caused by the selector, those events are intercepted and dispatched on EDT out of order. - *

- * When called on non-EDT, the method performs the selector in place. The method is reentrant. - * - * @param selector the native selector wrapper - * @param the selector return type - * @return the selector result - */ - public static T perform(Callable selector) { - if (selector == null) return null; - - if (EventQueue.isDispatchThread()) { - SelectorPerformer performer = getInstance(Thread.currentThread()); - if (performer != null) { - return performer.performImpl(selector); - } - } - // fallback to default - try { - return selector.call(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - private T performImpl(Callable selector) { - assert EventQueue.isDispatchThread(); - if (executor == null) { - // init on EDT - AccessController.doPrivileged((PrivilegedAction)() -> - executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), - new ThreadFactory() { - private ThreadFactory factory = Executors.privilegedThreadFactory(); - @Override - public Thread newThread(Runnable r) { - Thread t = factory.newThread(r); - t.setDaemon(true); - t.setName("AWT-SelectorPerformer " + t.getName()); - return t; - } - }) - ); - } - LinkedBlockingQueue currentQueue; - synchronized (invocations) { - invocations.push(currentQueue = new LinkedBlockingQueue<>()); - } - - FutureTask task = new FutureTask(selector) { - @Override - protected void done() { - synchronized (invocations) { - // Done with the current queue, wake it up. - invocations.pop().add(new InvocationEvent(executor, () -> {})); - } - } - }; - executor.execute(task); - - try { - while (!task.isDone() || !currentQueue.isEmpty()) { - InvocationEvent event = currentQueue.poll(WAIT_LIMIT_SECONDS, TimeUnit.SECONDS); - if (event == null) { - new RuntimeException("Waiting for the invocation event timed out").printStackTrace(); - break; - } - event.dispatch(); - } - return task.isDone() ? task.get() : null; - - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - return null; - } - - /** - * Checks if there's an active SelectorPerformer corresponding to the invocation's AppContext, - * adds the invocation to the SelectorPerformer's queue and returns true. - * Otherwise does nothing and returns false. - */ - public static boolean offer(InvocationEvent invocation) { - Object source = invocation.getSource(); - - SelectorPerformer performer = (source instanceof Component) ? - getInstance((Component)source) : - getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue()); - - if (performer == null) return false; - - synchronized (performer.invocations) { - if (!performer.invocations.isEmpty()) { - performer.invocations.peek().add(invocation); - return true; - } - } - return false; - } - - private static SelectorPerformer getInstance(Component comp) { - if (comp == null) return null; - - AppContext appContext = SunToolkit.targetToAppContext(comp); - if (appContext == null) return null; - - return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY)); - } - - private static SelectorPerformer getInstance(EventQueue eq) { - if (eq == null) return null; - - return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq)); - } - - private static SelectorPerformer getInstance(Thread edt) { - if (edt == null) return null; - - return edt2performer.computeIfAbsent(edt, key -> new SelectorPerformer()); - } - } - /** * Kicks an event over to the appropriate event queue and waits for it to * finish To avoid deadlocking, we manually run the NSRunLoop while waiting @@ -874,7 +721,7 @@ public static void invokeAndWait(Runnable runnable, Component component) }, true); - if (!SelectorPerformer.offer(invocationEvent)) { + if (!InvokeOnToolkitHelper.offer(invocationEvent)) { if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component); SunToolkit.postEvent(appContext, invocationEvent); @@ -883,7 +730,7 @@ public static void invokeAndWait(Runnable runnable, Component component) SunToolkit.flushPendingEvents(appContext); } else { // This should be the equivalent to EventQueue.invokeAndWait - ((LWCToolkit) Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); + ((LWCToolkit) Toolkit.getDefaultToolkit()).getSystemEventQueueImpl().postEvent(invocationEvent); } } doAWTRunLoop(mediator, false); diff --git a/src/java.desktop/share/classes/sun/awt/InvokeOnToolkitHelper.java b/src/java.desktop/share/classes/sun/awt/InvokeOnToolkitHelper.java new file mode 100644 index 000000000000..a98e719e291d --- /dev/null +++ b/src/java.desktop/share/classes/sun/awt/InvokeOnToolkitHelper.java @@ -0,0 +1,157 @@ +package sun.awt; + +import java.awt.*; +import java.awt.event.InvocationEvent; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.Stack; +import java.util.concurrent.*; + +/** + * Used to perform a blocking invocation on Toolkit thread from EDT, preventing a deadlock. + * The deadlock can happen when EDT and Toolkit perform blocking invocations at the same time. + * The following is performed to resolve it: + * 1) The invoker spins a nested event loop on EDT while waiting for the invocation to complete. + * 2) A separate pool thread is used to perform the invocation. + */ +public class InvokeOnToolkitHelper { + private ExecutorService executor; + // every invokeAndWait() pushes a queue of invocations + private final Stack> invocations = new Stack<>(); + + // invocations should be dispatched on proper EDT (per AppContext) + private static final Map edt2invokerMap = new ConcurrentHashMap<>(); + + private static final int WAIT_LIMIT_SECONDS = 5; + + private InvokeOnToolkitHelper() {} + + /** + * Invokes the callable on Toolkit thread and blocks until the completion. The method is re-entrant. + * + * On macOS it is assumed the callable wraps a native selector. The selector should be executed via [JNFRunLoop performOnMainThreadWaiting:YES ...] + * so that the doAWTRunLoop on AppKit (which is run in [JNFRunLoop javaRunLoopMode]) accepts it. The callable wrapper should not call any Java code + * which would normally be called on EDT. + *

+ * If Toolkit posts invocation events caused by the callable, those events are intercepted and dispatched on EDT out of order. + *

+ * When called on non-EDT, the method invokes the callable in place. + */ + public static T invokeAndBlock(Callable callable) { + if (callable == null) return null; + + if (EventQueue.isDispatchThread()) { + InvokeOnToolkitHelper invoker = getInstance(Thread.currentThread()); + if (invoker != null) { + return invoker.invoke(callable); + } + } + // fallback to default + try { + return callable.call(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private T invoke(Callable callable) { + assert EventQueue.isDispatchThread(); + if (executor == null) { + // init on EDT + AccessController.doPrivileged((PrivilegedAction)() -> + executor = new ThreadPoolExecutor(1, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + new ThreadFactory() { + private final ThreadFactory factory = Executors.privilegedThreadFactory(); + @Override + public Thread newThread(Runnable r) { + Thread t = factory.newThread(r); + t.setDaemon(true); + t.setName("AWT-InvokeOnToolkitHelper " + t.getName()); + return t; + } + }) + ); + } + LinkedBlockingQueue currentQueue; + synchronized (invocations) { + invocations.push(currentQueue = new LinkedBlockingQueue<>()); + } + + FutureTask task = new FutureTask(callable) { + @Override + protected void done() { + synchronized (invocations) { + // Done with the current queue, wake it up. + invocations.pop().add(new InvocationEvent(executor, () -> {})); + } + } + }; + executor.execute(task); + + try { + while (!task.isDone() || !currentQueue.isEmpty()) { + InvocationEvent event = currentQueue.poll(WAIT_LIMIT_SECONDS, TimeUnit.SECONDS); + if (event == null) { + new RuntimeException("Waiting for the invocation event timed out").printStackTrace(); + break; + } + event.dispatch(); + } + return task.isDone() ? task.get() : null; + + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Warning: the method is used by the implementation and should not be used by a client. + * + * Checks if there's an active InvokeOnToolkitHelper corresponding to the invocation's AppContext, + * adds the invocation to the InvokeOnToolkitHelper's queue and returns true. + * Otherwise does nothing and returns false. + */ + public static boolean offer(InvocationEvent invocation) { + Object source = invocation.getSource(); + + InvokeOnToolkitHelper invoker = (source instanceof Component) ? + getInstance((Component)source) : + getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue()); + + if (invoker == null) return false; + + synchronized (invoker.invocations) { + if (!invoker.invocations.isEmpty()) { + invoker.invocations.peek().add(invocation); + return true; + } + } + return false; + } + + private static InvokeOnToolkitHelper getInstance(Component comp) { + if (comp == null) return null; + + AppContext appContext = SunToolkit.targetToAppContext(comp); + if (appContext == null) return null; + + return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY)); + } + + private static InvokeOnToolkitHelper getInstance(EventQueue eq) { + if (eq == null) return null; + + return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq)); + } + + private static InvokeOnToolkitHelper getInstance(Thread edt) { + if (edt == null) return null; + + return edt2invokerMap.computeIfAbsent(edt, key -> new InvokeOnToolkitHelper()); + } +} From ea5c5a03d98074944473bb9f39ae07f5fbaf2ffb Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Tue, 20 Sep 2016 12:07:24 +0300 Subject: [PATCH 152/976] JRE-34 IDE Crashes During Startup Added validation of dpi settings coming from xserver (cherry picked from commit b1c49c3b2766ae83f46d2a242328a09c7a408d8b) --- .../share/native/libfontmanager/freetypeScaler.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 6d9402948541..ca1bcb2102f3 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -68,6 +68,7 @@ #define FT26Dot6ToDouble(x) ((x) / ((double) (1<<6))) #define FT26Dot6ToInt(x) (((int)(x)) >> 6) #define DEFAULT_DPI 72 +#define MAX_DPI 1024 #define ADJUST_FONT_SIZE(X, DPI) (((X)*DEFAULT_DPI + ((DPI)>>1))/(DPI)) #ifndef _WIN32 @@ -249,6 +250,11 @@ static int getScreenResolution(JNIEnv *env) { (*env)->ExceptionClear(env); return DEFAULT_DPI; } + + /* Some configurations report invalid dpi settings */ + if (dpi > MAX_DPI) { + return DEFAULT_DPI; + } return dpi; } From 9754f9623e29db063b306608bd2f5e2058ba92f1 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Tue, 20 Sep 2016 14:10:34 +0300 Subject: [PATCH 153/976] Added logging for freetypeScaler via env variable OPENJDK_LOG_FFS=yes and for screen resolution in freetypeScaler (cherry picked from commit 091d74a791e64e5a802d1d6fb258ab7c5382d900) --- .../native/libfontmanager/freetypeScaler.c | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index ca1bcb2102f3..e976c740d2aa 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -155,6 +155,7 @@ typedef FcResult (*FcPatternGetIntegerPtrType) (const FcPattern *p, const char * static void *libFontConfig = NULL; static jboolean logFC = JNI_FALSE; +static jboolean logFFS = JNI_FALSE; #ifndef _WIN32 static FcPatternAddPtrType FcPatternAddPtr; @@ -199,6 +200,12 @@ static void* openFontConfig() { JNIEXPORT void JNICALL Java_sun_font_FreetypeFontScaler_initIDs( JNIEnv *env, jobject scaler, jclass FFSClass, jclass TKClass, jclass PFClass) { + char *fssLogEnabled = getenv("OPENJDK_LOG_FFS"); + + if (fssLogEnabled != NULL && !strcmp(fssLogEnabled, "yes")) { + logFFS = JNI_TRUE; + } + invalidateScalerMID = (*env)->GetMethodID(env, FFSClass, "invalidateScaler", "()V"); @@ -253,8 +260,14 @@ static int getScreenResolution(JNIEnv *env) { /* Some configurations report invalid dpi settings */ if (dpi > MAX_DPI) { + if (logFFS) { + fprintf(stderr, "FFS_LOG: Invalid dpi reported (%d) replaced with default (%d)\n", dpi, DEFAULT_DPI); + } return DEFAULT_DPI; } + if (logFFS) { + fprintf(stderr, "FFS_LOG: Screen Resolution (%d) dpi\n", dpi); + } return dpi; } @@ -697,6 +710,24 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative( return ptr_to_jlong(context); } +static void setDefaultScalerSettings(FTScalerContext *context) { + if (context->aaType == TEXT_AA_OFF) { + context->loadFlags = FT_LOAD_TARGET_MONO; + } else if (context->aaType == TEXT_AA_ON) { + context->loadFlags = FT_LOAD_TARGET_NORMAL; + } else { + context->lcdFilter = FT_LCD_FILTER_LIGHT; + if (context->aaType == TEXT_AA_LCD_HRGB || + context->aaType == TEXT_AA_LCD_HBGR) { + context->loadFlags = FT_LOAD_TARGET_LCD; + } else { + context->loadFlags = FT_LOAD_TARGET_LCD_V; + } + } + context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); +} + + // values used by FreeType (as of version 2.10.1) for italics transformation matrix in FT_GlyphSlot_Oblique #define FT_MATRIX_ONE 0x10000 #define FT_MATRIX_OBLIQUE_XY 0x0366A @@ -1277,12 +1308,45 @@ static jlong FTScalerInfo *scalerInfo = (FTScalerInfo*) jlong_to_ptr(pScaler); + if (logFFS) { + fprintf(stderr, "FFS_LOG: getGlyphImageNative '%c'(%d) ", + (glyphCode >= 0x20 && glyphCode <=0x7E)? glyphCode : ' ', + glyphCode); + } + if (isNullScalerContext(context) || scalerInfo == NULL) { + if (logFFS) fprintf(stderr, "FFS_LOG: NULL context or info\n"); return ptr_to_jlong(getNullGlyphImage()); } + else if (logFFS){ + char* aaTypeStr; + switch (context->aaType) { + case TEXT_AA_ON: + aaTypeStr = "AA_ON"; + break; + case TEXT_AA_OFF: + aaTypeStr = "AA_OFF"; + break; + case TEXT_AA_LCD_HBGR: + aaTypeStr = "AA_LCD_HBGR"; + break; + case TEXT_AA_LCD_VBGR: + aaTypeStr = "AA_LCD_VBGR"; + break; + case TEXT_AA_LCD_HRGB: + aaTypeStr = "AA_LCD_HRGB"; + break; + default: + aaTypeStr = "AA_UNKNOWN"; + break; + } + fprintf(stderr, "%s size=%.2f\n", aaTypeStr, + ((double)context->ptsz)/64.0); + } error = setupFTContext(env, font2D, scalerInfo, context, TRUE); if (error) { + if (logFFS) fprintf(stderr, "FFS_LOG: Cannot setup FT context\n"); invalidateJavaScaler(env, scaler, scalerInfo); return ptr_to_jlong(getNullGlyphImage()); } From 73a37491ddd1e3ef26514067fa822ec231e390d6 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Wed, 12 Oct 2016 14:28:38 +0300 Subject: [PATCH 154/976] JRE-48 built-in jre renders fonts abnormally heavier (normal text looks bold) than the oracle jre Disable FT_LOAD_TARGET_LIGHT for fonts with FC_AUTOHINT=false (this target implicitly enables FC_AUTOHINT) Reused setupLoadRenderFlags for all rendering cases (cherry picked from commit f3f2667a4cc3e41af2635be23ca798b7ea0b33e2) --- .../native/libfontmanager/freetypeScaler.c | 105 ++++++++---------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index e976c740d2aa..79f1212410c4 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -30,11 +30,14 @@ #include "sun_font_FreetypeFontScaler.h" #include +#include + #if !defined(_WIN32) && !defined(__APPLE_) #include +#else +#define DISABLE_FONTCONFIG #endif -#include -#include + #include "ft2build.h" #include FT_LCD_FILTER_H #include FT_FREETYPE_H @@ -43,6 +46,7 @@ #include FT_SIZES_H #include FT_OUTLINE_H #include FT_SYNTHESIS_H +#include FT_MODULE_H #include FT_LCD_FILTER_H #include FT_MODULE_H #include FT_LCD_FILTER_H @@ -437,7 +441,7 @@ static void setInterpreterVersion(FT_Library library) { const char* property = "interpreter-version"; /* If some one is setting this, don't override it */ - if (props != NULL && strstr(props, property)) { + if (props != NULL && strstr(property, props)) { return; } /* @@ -710,23 +714,32 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative( return ptr_to_jlong(context); } -static void setDefaultScalerSettings(FTScalerContext *context) { - if (context->aaType == TEXT_AA_OFF) { - context->loadFlags = FT_LOAD_TARGET_MONO; - } else if (context->aaType == TEXT_AA_ON) { - context->loadFlags = FT_LOAD_TARGET_NORMAL; - } else { - context->lcdFilter = FT_LCD_FILTER_LIGHT; - if (context->aaType == TEXT_AA_LCD_HRGB || - context->aaType == TEXT_AA_LCD_HBGR) { - context->loadFlags = FT_LOAD_TARGET_LCD; - } else { - context->loadFlags = FT_LOAD_TARGET_LCD_V; +#ifndef DISABLE_FONTCONFIG +static void setupLoadRenderFlags(FTScalerContext *context, int fcHintStyle, FcBool fcAutohint, FcBool fcAutohintSet, + FT_Int32 fcLoadFlags, FT_Render_Mode fcRenderFlags) +{ + if (!fcAutohintSet || fcAutohint) { + switch (fcHintStyle) { + case FC_HINT_NONE: + context->loadFlags = FT_LOAD_NO_HINTING; + break; + case FC_HINT_SLIGHT: + context->loadFlags = (fcRenderFlags != FT_RENDER_MODE_MONO) ? FT_LOAD_TARGET_LIGHT : FT_LOAD_NO_HINTING; + break; + default: + context->loadFlags = fcLoadFlags; } + } else { + context->loadFlags = fcLoadFlags; } - context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); -} + context->renderFlags = fcRenderFlags; + + if (fcAutohintSet && fcAutohint) { + context->loadFlags |= FT_LOAD_FORCE_AUTOHINT; + } +} +#endif // values used by FreeType (as of version 2.10.1) for italics transformation matrix in FT_GlyphSlot_Oblique #define FT_MATRIX_ONE 0x10000 @@ -750,10 +763,7 @@ static void setupTransform(FT_Matrix* target, FTScalerContext *context) { } } -static int setupFTContext(JNIEnv *env, - jobject font2D, - FTScalerInfo *scalerInfo, - FTScalerContext *context, +static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, FTScalerContext *context, FT_Bool configureFont) { FT_Matrix matrix; int errCode = 0; @@ -857,7 +867,6 @@ static int setupFTContext(JNIEnv *env, } if (fcHintStyleSet && fcHintStyle == FC_HINT_NONE) { - fcHintingSet = FcTrue; fcHinting = FcFalse; } @@ -885,26 +894,16 @@ static int setupFTContext(JNIEnv *env, if (fcAntialiasSet) fprintf(stderr, "FC_ANTIALIAS(%d) ", fcAntialias); } + FcBool fcAutohint = FcFalse; + FcBool fcAutohintSet = (*FcPatternGetBoolPtr)(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch; + + if (logFC && fcAutohintSet) fprintf(stderr, "FC_AUTOHINT(%d) ", fcAutohint); + if (context->aaType == TEXT_AA_ON) { // Greyscale AA - context->renderFlags = FT_RENDER_MODE_NORMAL; - if (fcHintingSet) { - switch (fcHintStyle) { - case FC_HINT_NONE: - context->loadFlags = FT_LOAD_NO_HINTING; - break; - case FC_HINT_SLIGHT: - context->loadFlags = FT_LOAD_TARGET_LIGHT; - break; - case FC_HINT_MEDIUM: - case FC_HINT_FULL: - default: - break; - } - } + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, FT_LOAD_DEFAULT, FT_RENDER_MODE_NORMAL); } else if (context->aaType == TEXT_AA_OFF) { // No AA - context->renderFlags = FT_RENDER_MODE_MONO; - context->loadFlags = (!fcHintingSet || fcHinting) ? FT_LOAD_TARGET_MONO : FT_LOAD_NO_HINTING; + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, FT_LOAD_TARGET_MONO, FT_RENDER_MODE_MONO); } else { int fcRGBA = FC_RGBA_UNKNOWN; if (fcAntialiasSet && fcAntialias) { @@ -913,14 +912,17 @@ static int setupFTContext(JNIEnv *env, case FC_RGBA_RGB: case FC_RGBA_BGR: if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_RGB ? "FC_RGBA_RGB " : "FC_RGBA_BGR "); - context->loadFlags = FT_LOAD_TARGET_LCD; - context->renderFlags = FT_RENDER_MODE_LCD; + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, + FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD); break; case FC_RGBA_VRGB: case FC_RGBA_VBGR: if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_VRGB ? "FC_RGBA_VRGB " : "FC_RGBA_VBGR "); - context->loadFlags = FT_LOAD_TARGET_LCD_V; - context->renderFlags = FT_RENDER_MODE_LCD_V; + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, + FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V); + break; + case FC_RGBA_NONE: + if (logFC) fprintf(stderr, "FC_RGBA_NONE "); break; default: if (logFC) fprintf(stderr, "FC_RGBA_UNKNOWN "); @@ -931,24 +933,15 @@ static int setupFTContext(JNIEnv *env, if (fcRGBA == FC_RGBA_UNKNOWN) { if (context->aaType == TEXT_AA_LCD_HRGB || context->aaType == TEXT_AA_LCD_HBGR) { - context->loadFlags = FT_LOAD_TARGET_LCD; - context->renderFlags = FT_RENDER_MODE_LCD; + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, + FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD); } else { - context->loadFlags = FT_LOAD_TARGET_LCD_V; - context->renderFlags = FT_RENDER_MODE_LCD_V; + setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, + FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V); } } } - FcBool fcAutohint = FcFalse; - FcBool fcAutohintSet = (*FcPatternGetBoolPtr)(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch; - - if (logFC && fcAutohintSet) fprintf(stderr, "FC_AUTOHINT(%d) ", fcAutohint); - - if (fcAutohintSet && fcAutohint) { - context->loadFlags |= FT_LOAD_FORCE_AUTOHINT; - } - FT_LcdFilter fcLCDFilter; FcBool fcLCDFilterSet = (*FcPatternGetIntegerPtr)(pattern, FC_LCD_FILTER, 0, (int*) &fcLCDFilter) == FcResultMatch; context->lcdFilter = FT_LCD_FILTER_DEFAULT; From 74301b5d78f8dfaf0125fbaac623b94906212324 Mon Sep 17 00:00:00 2001 From: Vitaly Provodin Date: Tue, 30 Mar 2021 11:22:35 +0700 Subject: [PATCH 155/976] exclude tests spontaneously creating windows during test execution --- test/jdk/jbProblemList.txt | 45 ++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/test/jdk/jbProblemList.txt b/test/jdk/jbProblemList.txt index 452cd8fddbcc..1a6b430e9fb0 100644 --- a/test/jdk/jbProblemList.txt +++ b/test/jdk/jbProblemList.txt @@ -878,29 +878,32 @@ java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all # various Windows are created spontaneously during test execution -javax/swing/JComboBox/6559152/bug6559152.java windows-all -javax/swing/JComboBox/6607130/bug6607130.java windows-all +javax/swing/JComboBox/6559152/bug6559152.java nobug windows-all +javax/swing/JComboBox/6607130/bug6607130.java nobug windows-all -javax/swing/JComboBox/4199622/bug4199622.java windows-all -javax/swing/JComboBox/4515752/DefaultButtonTest.java windows-all +javax/swing/JComboBox/4199622/bug4199622.java nobug windows-all +javax/swing/JComboBox/4515752/DefaultButtonTest.java nobug windows-all -javax/swing/JComboBox/8032878/bug8032878.java windows-all -javax/swing/JComboBox/8057893/bug8057893.java windows-all +javax/swing/JComboBox/8032878/bug8032878.java nobug windows-all +javax/swing/JComboBox/8057893/bug8057893.java nobug windows-all + +javax/swing/JList/6462008/bug6462008.java nobug windows-all +javax/swing/JMenu/6470128/bug6470128.java nobug windows-all # no printer found -java/awt/print/PrinterJob/CheckPrivilege.java generic-all -java/awt/print/PrinterJob/ExceptionTest.java generic-all -java/awt/print/PrinterJob/ImagePrinting/NullClipARGB.java generic-all -java/awt/print/PrinterJob/LandscapeStackOverflow.java generic-all -java/awt/print/PrinterJob/PaintText.java generic-all -java/awt/print/PrinterJob/PrintCrashTest.java generic-all -java/awt/print/PrinterJob/PrtException.java generic-all -javax/print/attribute/ChromaticityValues.java generic-all -javax/print/CheckDupFlavor.java generic-all -javax/print/PrintSE/PrintSE.sh generic-all +java/awt/print/PrinterJob/CheckPrivilege.java nobug generic-all +java/awt/print/PrinterJob/ExceptionTest.java nobug generic-all +java/awt/print/PrinterJob/ImagePrinting/NullClipARGB.java nobug generic-all +java/awt/print/PrinterJob/LandscapeStackOverflow.java nobug generic-all +java/awt/print/PrinterJob/PaintText.java nobug generic-all +java/awt/print/PrinterJob/PrintCrashTest.java nobug generic-all +java/awt/print/PrinterJob/PrtException.java nobug generic-all +javax/print/attribute/ChromaticityValues.java nobug generic-all +javax/print/CheckDupFlavor.java nobug generic-all +javax/print/PrintSE/PrintSE.sh nobug generic-all javax/print/PrintSEUmlauts/PrintSEUmlauts.java 8135174 generic-all -javax/print/PrintServiceLookup/CountPrintServices.java generic-all -javax/print/attribute/AttributeTest.java generic-all -javax/print/attribute/GetCopiesSupported.java generic-all -javax/print/attribute/SidesPageRangesTest.java generic-all -javax/print/attribute/SupportedPrintableAreas.java generic-all \ No newline at end of file +javax/print/PrintServiceLookup/CountPrintServices.java nobug generic-all +javax/print/attribute/AttributeTest.java nobug generic-all +javax/print/attribute/GetCopiesSupported.java nobug generic-all +javax/print/attribute/SidesPageRangesTest.java nobug generic-all +javax/print/attribute/SupportedPrintableAreas.java nobug generic-all \ No newline at end of file From 2739b7ae8920023efa7840e0076cbe2807b5eae8 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Wed, 14 Sep 2016 13:23:29 +0300 Subject: [PATCH 156/976] JRE-29 fontconfig lib crashes CLion on OSX Disabled fontconfig usage on OSX (cherry picked from commit 431e14429c29ce2a3a367903a211e79063a6910a) --- .../native/libfontmanager/freetypeScaler.c | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 79f1212410c4..506839652273 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -30,9 +30,13 @@ #include "sun_font_FreetypeFontScaler.h" #include +#if defined(_WIN32) || defined(MACOSX) +#define DISABLE_FONTCONFIG +#endif + #include -#if !defined(_WIN32) && !defined(__APPLE_) +#ifndef DISABLE_FONTCONFIG #include #else #define DISABLE_FONTCONFIG @@ -51,7 +55,7 @@ #include FT_MODULE_H #include FT_LCD_FILTER_H -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG /* Use bundled fontconfig.h for now */ #include "fontconfig.h" #endif @@ -75,7 +79,7 @@ #define MAX_DPI 1024 #define ADJUST_FONT_SIZE(X, DPI) (((X)*DEFAULT_DPI + ((DPI)>>1))/(DPI)) -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG #define FONTCONFIG_DLL JNI_LIB_NAME("fontconfig") #define FONTCONFIG_DLL_VERSIONED VERSIONED_JNI_LIB_NAME("fontconfig", "1") #endif @@ -144,7 +148,7 @@ static jclass tkClass; static jmethodID getScreenResolutionMID; static jfieldID platNameFID; -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG typedef FcBool (*FcPatternAddPtrType) (FcPattern *p, const char *object, FcValue value, FcBool append); typedef FcBool (*FcPatternAddBoolPtrType) (FcPattern *p, const char *object, FcBool b); typedef FcBool (*FcPatternAddDoublePtrType) (FcPattern *p, const char *object, double d); @@ -161,7 +165,7 @@ static void *libFontConfig = NULL; static jboolean logFC = JNI_FALSE; static jboolean logFFS = JNI_FALSE; -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG static FcPatternAddPtrType FcPatternAddPtr; static FcPatternAddBoolPtrType FcPatternAddBoolPtr; static FcPatternAddDoublePtrType FcPatternAddDoublePtr; @@ -176,7 +180,7 @@ static FcPatternGetIntegerPtrType FcPatternGetIntegerPtr; static void* openFontConfig() { void* libfontconfig = NULL; -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG char *fcLogEnabled = getenv("OPENJDK_FFS_LOG_FC"); if (fcLogEnabled != NULL && !strcmp(fcLogEnabled, "yes")) { @@ -225,7 +229,7 @@ Java_sun_font_FreetypeFontScaler_initIDs( tkClass = (*env)->NewGlobalRef(env, TKClass); platNameFID = (*env)->GetFieldID(env, PFClass, "platName", "Ljava/lang/String;"); libFontConfig = openFontConfig(); -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG if (libFontConfig) { FcPatternAddPtr = (FcPatternAddPtrType) dlsym(libFontConfig, "FcPatternAdd"); FcPatternAddBoolPtr = (FcPatternAddBoolPtrType) dlsym(libFontConfig, "FcPatternAddBool"); @@ -802,7 +806,7 @@ static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); return 0; } -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG FcPattern *fcPattern = 0; fcPattern = (*FcPatternCreatePtr)(); FcValue fcValue; @@ -1293,7 +1297,6 @@ static jlong GlyphInfo *glyphInfo; int target; FT_GlyphSlot ftglyph; - FT_LcdFilter lcdFilter = FT_LCD_FILTER_NONE; FT_Library library; FTScalerContext* context = @@ -2069,7 +2072,7 @@ Java_sun_font_FreetypeFontScaler_getGlyphPointNative( JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { if (libFontConfig != NULL) { -#ifndef _WIN32 +#ifndef DISABLE_FONTCONFIG dlclose(libFontConfig); #endif } From 30c312c3f546e99264129d1a1ebe9617b8178ac5 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Fri, 15 Apr 2016 01:14:55 +0300 Subject: [PATCH 157/976] IDEA-151619 CLion EAP fails to start with missing symbol: FT_Library_setLcdFilter Skip FT_Library_setLcdFilter call if the symbol is not there Cache negative FT_Library_setLcdFilter symbol lookup result Used RTLD_DEFAULT handler for process symbols lookup (cherry picked from commit e6f00557045a3b139513facca9cb8f23070588d9) --- .../native/libfontmanager/freetypeScaler.c | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 506839652273..319ef49bc14c 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -159,6 +159,7 @@ typedef FcPattern* (*FcFontMatchPtrType) (FcConfig *config, FcPattern *p, FcResu typedef void (*FcPatternDestroyPtrType) (FcPattern *p); typedef FcResult (*FcPatternGetBoolPtrType) (const FcPattern *p, const char *object, int n, FcBool *b); typedef FcResult (*FcPatternGetIntegerPtrType) (const FcPattern *p, const char *object, int n, int *i); +typedef FT_Error (*FtLibrarySetLcdFilterPtrType) (FT_Library library, FT_LcdFilter filter); #endif static void *libFontConfig = NULL; @@ -245,6 +246,28 @@ Java_sun_font_FreetypeFontScaler_initIDs( #endif } +static FT_Error FT_Library_SetLcdFilter_Proxy(FT_Library library, FT_LcdFilter filter) { +#ifndef DISABLE_FONTCONFIG + static FtLibrarySetLcdFilterPtrType FtLibrarySetLcdFilterPtr = NULL; + static int ftLibrarySetLcdFilterNotChecked = 1; + if (ftLibrarySetLcdFilterNotChecked) { + if (logFC) fprintf(stderr, "FC_LOG: Lookup FT_Library_SetLcdFilter: "); + FtLibrarySetLcdFilterPtr = (FtLibrarySetLcdFilterPtrType) dlsym(RTLD_DEFAULT, "FT_Library_SetLcdFilter"); + if (logFC) fprintf(stderr, (FtLibrarySetLcdFilterPtr)? "found\n" : "not found\n"); + ftLibrarySetLcdFilterNotChecked = 0; + } + if (FtLibrarySetLcdFilterPtr) { + return (*FtLibrarySetLcdFilterPtr)(library, filter); + } else { + if (logFC) fprintf(stderr, "FC_LOG: Skipping FT_Library_SetLcdFilter\n"); + } + + return 0; +#else + return FT_Library_SetLcdFilter(library, filter); +#endif +} + static char* getPhysFontName(JNIEnv *env, jobject font2d) { jstring jstr; jstr = (*env)->GetObjectField(env, font2d, platNameFID); @@ -1389,7 +1412,7 @@ static jlong ftglyph = scalerInfo->face->glyph; library = ftglyph->library; - FT_Library_SetLcdFilter (library, context->lcdFilter); + FT_Library_SetLcdFilter_Proxy(library, context->lcdFilter); /* apply styles */ if (context->doBold) { /* if bold style */ From 2e1e24e354a57d6403d8a34a9b2241029c405c8a Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Tue, 29 Dec 2015 13:41:00 +0300 Subject: [PATCH 158/976] IDEA-149882 Issue with fonts in Ubuntu 12.04 Provided fallback to default font rendering settings if libfontconfig unable to match font pattern (cherry picked from commit d93a5f1598ccab77e84b1ddd09d2761a051b8ac9) --- .../native/libfontmanager/freetypeScaler.c | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 319ef49bc14c..0918d68f2ccd 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -790,6 +790,23 @@ static void setupTransform(FT_Matrix* target, FTScalerContext *context) { } } +static void setDefaultScalerSettings(FTScalerContext *context) { + if (context->aaType == TEXT_AA_OFF) { + context->loadFlags = FT_LOAD_TARGET_MONO; + } else if (context->aaType == TEXT_AA_ON) { + context->loadFlags = FT_LOAD_TARGET_LIGHT; + } else { + context->lcdFilter = FT_LCD_FILTER_LIGHT; + if (context->aaType == TEXT_AA_LCD_HRGB || + context->aaType == TEXT_AA_LCD_HBGR) { + context->loadFlags = FT_LOAD_TARGET_LCD; + } else { + context->loadFlags = FT_LOAD_TARGET_LCD_V; + } + } + context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); +} + static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, FTScalerContext *context, FT_Bool configureFont) { FT_Matrix matrix; @@ -813,20 +830,7 @@ static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, context->loadFlags = FT_LOAD_DEFAULT; if (libFontConfig == NULL) { - if (context->aaType == TEXT_AA_OFF) { - context->loadFlags = FT_LOAD_TARGET_MONO; - } else if (context->aaType == TEXT_AA_ON) { - context->loadFlags = FT_LOAD_TARGET_LIGHT; - } else { - context->lcdFilter = FT_LCD_FILTER_LIGHT; - if (context->aaType == TEXT_AA_LCD_HRGB || - context->aaType == TEXT_AA_LCD_HBGR) { - context->loadFlags = FT_LOAD_TARGET_LCD; - } else { - context->loadFlags = FT_LOAD_TARGET_LCD_V; - } - } - context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags); + setDefaultScalerSettings(context); return 0; } #ifndef DISABLE_FONTCONFIG @@ -854,7 +858,8 @@ static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, if (matchResult != FcResultMatch) { (*FcPatternDestroyPtr)(fcPattern); if (logFC) fprintf(stderr, " - NOT FOUND\n"); - return 1; + setDefaultScalerSettings(context); + return 0; } if (logFC) fprintf(stderr, "\nFC_LOG: "); (*FcPatternDestroyPtr)(fcPattern); From fb8c58d19543bcf67011026881f29c67acb71d8c Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Fri, 6 May 2016 15:53:04 +0300 Subject: [PATCH 159/976] IDEA-155347 On Ubuntu with High DPI tooltip font is too thick when the tooltip is fading in and out Handled missing FC_RGBA_NONE value (cherry picked from commit 44fcbdabf8b65eebb4a368829b75c618c7d0f734) --- src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 0918d68f2ccd..bf2139d52f86 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -962,7 +962,8 @@ static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo, } } } - if (fcRGBA == FC_RGBA_UNKNOWN) { + if (fcRGBA == FC_RGBA_UNKNOWN || fcRGBA == FC_RGBA_NONE) { + if (context->aaType == TEXT_AA_LCD_HRGB || context->aaType == TEXT_AA_LCD_HBGR) { setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, From d1c4aed1815170bf926f0fd219186ecfb03380b6 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Tue, 23 Aug 2016 20:11:59 +0300 Subject: [PATCH 160/976] JRE-15 Greyscale text is too dark comparing with subpixel AA Adjusted default value for greyscale text rendering in freetype (cherry picked from commit f80497c4f0e98bed6584d52dcd6219eab5060b83) --- src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index bf2139d52f86..f9dd8bd09a8e 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -794,7 +794,7 @@ static void setDefaultScalerSettings(FTScalerContext *context) { if (context->aaType == TEXT_AA_OFF) { context->loadFlags = FT_LOAD_TARGET_MONO; } else if (context->aaType == TEXT_AA_ON) { - context->loadFlags = FT_LOAD_TARGET_LIGHT; + context->loadFlags = FT_LOAD_TARGET_NORMAL; } else { context->lcdFilter = FT_LCD_FILTER_LIGHT; if (context->aaType == TEXT_AA_LCD_HRGB || From aacb45832e86d23727c73de442d2b731e7ce4c2c Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Wed, 5 Oct 2016 05:29:21 -0700 Subject: [PATCH 161/976] JRE-43 Font.getFamily() does not work in headless mode Bundled Droid fonts to fallback in headless mode (cherry picked from commit 5b523f049eb7eb7646b6d577d6462fb15fd23183) --- make/modules/java.desktop/Copy.gmk | 10 ++ .../share/classes/sun/font/FontUtilities.java | 6 + .../classes/sun/font/SunFontManager.java | 71 +++++++- .../share/fonts/DroidSans-Bold.ttf | Bin 0 -> 194488 bytes src/java.desktop/share/fonts/DroidSans.ttf | Bin 0 -> 190776 bytes .../share/fonts/DroidSansMono.ttf | Bin 0 -> 119380 bytes .../share/fonts/DroidSansMonoDotted.ttf | Bin 0 -> 117696 bytes .../share/fonts/DroidSansMonoSlashed.ttf | Bin 0 -> 117744 bytes .../share/fonts/DroidSerif-Bold.ttf | Bin 0 -> 185228 bytes .../share/fonts/DroidSerif-BoldItalic.ttf | Bin 0 -> 190304 bytes .../share/fonts/DroidSerif-Italic.ttf | Bin 0 -> 177560 bytes .../share/fonts/DroidSerif-Regular.ttf | Bin 0 -> 172916 bytes src/java.desktop/share/fonts/LICENSE.txt | 13 ++ src/java.desktop/share/fonts/fonts.dir | 170 ++++++++++++++++++ .../fontconfigs/linux.fontconfig.properties | 42 +++++ 15 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 src/java.desktop/share/fonts/DroidSans-Bold.ttf create mode 100644 src/java.desktop/share/fonts/DroidSans.ttf create mode 100644 src/java.desktop/share/fonts/DroidSansMono.ttf create mode 100644 src/java.desktop/share/fonts/DroidSansMonoDotted.ttf create mode 100644 src/java.desktop/share/fonts/DroidSansMonoSlashed.ttf create mode 100644 src/java.desktop/share/fonts/DroidSerif-Bold.ttf create mode 100644 src/java.desktop/share/fonts/DroidSerif-BoldItalic.ttf create mode 100644 src/java.desktop/share/fonts/DroidSerif-Italic.ttf create mode 100644 src/java.desktop/share/fonts/DroidSerif-Regular.ttf create mode 100644 src/java.desktop/share/fonts/LICENSE.txt create mode 100644 src/java.desktop/share/fonts/fonts.dir create mode 100644 src/solaris/classes/sun/awt/fontconfigs/linux.fontconfig.properties diff --git a/make/modules/java.desktop/Copy.gmk b/make/modules/java.desktop/Copy.gmk index 4232e62552c8..cc8f9f24da8b 100644 --- a/make/modules/java.desktop/Copy.gmk +++ b/make/modules/java.desktop/Copy.gmk @@ -82,3 +82,13 @@ $(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \ TARGETS += $(COPY_LEGAL) ################################################################################ + +FONTFILE_SRC_DIR := $(TOPDIR)/src/java.desktop/share +FONTFILE_SRCS := $(wildcard $(FONTFILE_SRC_DIR)/fonts/*.ttf) $(FONTFILE_SRC_DIR)/fonts/fonts.dir +FONTFILE_TARGET_FILES := $(subst $(FONTFILE_SRC_DIR),$(LIB_DST_DIR),$(FONTFILE_SRCS)) + +$(LIB_DST_DIR)/fonts/%: $(FONTFILE_SRC_DIR)/fonts/% + $(call install-file) + + +TARGETS += $(FONTFILE_TARGET_FILES) diff --git a/src/java.desktop/share/classes/sun/font/FontUtilities.java b/src/java.desktop/share/classes/sun/font/FontUtilities.java index bdccf99d1ed5..0189762e5d81 100644 --- a/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -50,6 +50,12 @@ public final class FontUtilities { public static boolean isWindows; + public static boolean isOpenJDK; + + static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf"; + + static final String DROID_FILE_NAME = "DroidSans.ttf"; + private static boolean debugFonts = false; private static PlatformLogger logger = null; private static boolean logging; diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 3aec139b56d7..381cd3df5bcb 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -188,9 +188,13 @@ public boolean accept(File dir, String name) { private boolean loaded1dot0Fonts = false; boolean loadedAllFonts = false; boolean loadedAllFontFiles = false; + HashMap jreFontMap; + HashSet jreBundledFontFiles; String[] jreOtherFontFiles; boolean noOtherJREFontFiles = false; // initial assumption. + public static final String lucidaFontName = "Lucida Sans Regular"; + public static final String droidFontName = "Droid Sans"; public static String jreLibDirName; public static String jreFontDirName; private static HashSet missingFontFiles = null; @@ -258,6 +262,46 @@ public FilenameFilter getType1Filter() { */ private static int maxSoftRefCnt = 10; + private void initJREFontMap() { + + /* Key is familyname+style value as an int. + * Value is filename containing the font. + * If no mapping exists, it means there is no font file for the style + * If the mapping exists but the file doesn't exist in the deferred + * list then it means its not installed. + * This looks like a lot of code and strings but if it saves even + * a single file being opened at JRE start-up there's a big payoff. + * Lucida Sans is probably the only important case as the others + * are rarely used. Consider removing the other mappings if there's + * no evidence they are useful in practice. + */ + jreFontMap = new HashMap(); + jreBundledFontFiles = new HashSet(); + + /* Droid Sans Mono Family */ + jreFontMap.put("droid sans0", "DroidSans.ttf"); + jreFontMap.put("droid sans1", "DroidSans-Bold.ttf"); + jreFontMap.put("droid sans bold1", "DroidSans-Bold.ttf"); + + /* Droid Sans Mono Family */ + jreFontMap.put("droid sans mono0", "DroidSansMono.ttf"); + jreFontMap.put("droid sans mono slashed0", + "DroidSansMonoSlashed.ttf"); + jreFontMap.put("droid sans mono dotted0", + "DroidSansMonoDotted.ttf"); + + /* Droid Serif Family */ + jreFontMap.put("droid serif0", "DroidSerif-Regular.ttf"); + jreFontMap.put("droid serif1", "DroidSerif-Bold.ttf"); + jreFontMap.put("droid serif2", "DroidSerif-Italic.ttf"); + jreFontMap.put("droid serif3", "DroidSerif-BoldItalic.ttf"); + jreFontMap.put("droid serif bold1", "DroidSerif-Bold.ttf"); + jreFontMap.put("droid serif bold italic3", "DroidSerif-BoldItalic.ttf"); + for (String ffile : jreFontMap.values()) { + jreBundledFontFiles.add(ffile); + } + } + static { initStatic(); } @@ -306,6 +350,8 @@ public TrueTypeFont getEUDCFont() { @SuppressWarnings("removal") protected SunFontManager() { + + initJREFontMap(); AccessController.doPrivileged(new PrivilegedAction() { public Void run() { File badFontFile = @@ -801,16 +847,19 @@ PhysicalFont findJREDeferredFont(String name, int style) { if (noOtherJREFontFiles) { return null; } - synchronized (jreFontDirName) { + synchronized (jreBundledFontFiles) { if (jreOtherFontFiles == null) { HashSet otherFontFiles = new HashSet<>(); for (String deferredFile : deferredFontFiles.keySet()) { File file = new File(deferredFile); String dir = file.getParent(); + String fname = file.getName(); /* skip names which aren't absolute, aren't in the JRE * directory, or are known Lucida fonts. */ - if (dir == null || !dir.equals(jreFontDirName)) { + if (dir == null || + !dir.equals(jreFontDirName) || + jreBundledFontFiles.contains(fname)) { continue; } otherFontFiles.add(deferredFile); @@ -842,6 +891,14 @@ PhysicalFont findJREDeferredFont(String name, int style) { private PhysicalFont findOtherDeferredFont(String name, int style) { for (String fileName : deferredFontFiles.keySet()) { + File file = new File(fileName); + String dir = file.getParent(); + String fname = file.getName(); + if (dir != null && + dir.equals(jreFontDirName) && + jreBundledFontFiles.contains(fname)) { + continue; + } PhysicalFont physicalFont = initialiseDeferredFont(fileName); if (physicalFont != null && (physicalFont.getFontName(null).equalsIgnoreCase(name) || @@ -3022,6 +3079,16 @@ public synchronized String getDefaultFontFile() { return defaultFontFileName; } + private void initDefaultFonts() { + defaultFontName = droidFontName; + if (useAbsoluteFontFileNames()) { + defaultFontFileName = + jreFontDirName + File.separator + FontUtilities.DROID_FILE_NAME; + } else { + defaultFontFileName = FontUtilities.DROID_FILE_NAME; + } + } + /** * Whether registerFontFile expects absolute or relative * font file names. diff --git a/src/java.desktop/share/fonts/DroidSans-Bold.ttf b/src/java.desktop/share/fonts/DroidSans-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d065b64eb1863f83c2c982264f9442f2313a44a9 GIT binary patch literal 194488 zcmeFad3;sX^)|luIrrRoo-cvqhD#Dc$UrV6geezDAk33s7y@Ai6$F{Y5vx{36o=M% zpla2s)nFBI7PTt%3!p4H50z?;pRvexG;moN3Q{t@W(6 z_P#gg3MqsL;bak2qZ=AWiDG@T(8kA+nm>B-q-m2b>39v#1BG~a?&xXLN1S#2+O0zS z*Dc6Tjz4W$)5XtSvP}qoUm^6XCQYlXzDM5tju3Ju@>>_Kn7>M!>$pOQ8NU|7UbArh z+T^&8rcM!J*#$yq)+MW!u2{1_)h5I|zYsQK>HIaTgbh&}??!$1(z7-$>23M>T|%tB zPRJb#mMvOw?sNSYPQ!rF{>bFA#q$?^v3U4g^fv_MYnCCweXX+s&uj7AYuSpm=gI<^ zLSJzqyy3IXUO2yE*PXqEIO8((=Uy@Y+*QUw?QWF61?7_~=dW1&>9T@tLM!=72c;UAI-E zz7V@FdZqRo_lXCcLHji*=MWlG5m3jrqP>R@&fquh_KnV=f;Ji&l#YSPE zre9QwS*W^4o+fnU>Xy&6=a6GJZZpzI&o{67KCwg|$LL&kt8TYwn&pttzQ~B=Y&49S z3(;@*w2>kyk{u_k1?^#RnQevqLsCdk0YWg>*nvw@XqG)tj2PTkewMEw^C2ABt^yyI6wj63hK!iJlOpmNP^c^|xuO#f{qPjz=v! z)%`ZxRbm^{EpMvw+gL~6i25Ih1^Q%BiM-p;pRle$zYBzu_xgjPRy!gJEX(BU<`uNe z(jN5KieoAc($UT``X9s@mb=8))(6ER?GsUHc~s>$llDxrh>m0W3RS*Yw~I;~gE<$_ zVVf~jtR}tXeH{mpK1cf!e0fxy2EJBgk6EDo2t{|&{*=SkiZt*-@qxU^9^gYC@Ha;3%`0XoUVsneMeYC(-UTnN$MqH* zhd`gPoqQlKx*n7>Jd+n)5AuS%=9Tki|KGV{?(Cm5_}(jJ6g=nrmAsHX9Or+&?qELU zS;^FYxiF-3M6(p4j)PSEF6TtOeqJl}EgRrsQkatLUhnPz;$lN zYsPL|$9BA?CpunNSc9&!l;I#QDKi)w^&I;qPZj^Dzp{GHQZJ?|EZv8)z>Z}FbS-E` zELpdTIiQWOwuu$SQBjNfH40${OgU52YF zN11sPmWSmo7gpvg96?uGUJx5qc`MS2&_CL=mgD~7j<>8A2skWTVRM}A8}vHNbD2otm})%+x-JtV!2f#mS8Dr2TmhZpr>t7O5=&r@2H_Zt zV-}8)nDb!b0zA6kaD#8ulaqJV~n}6W?0S|>2 z$hG1>|a+Cj_j#WKq}@dW7n6?ESJ;CRz^ z1U$VThlW1O(dQkI^&OB$>M7dU68I)mmz-}<~9r0{h-C8=m&T-KE_zxz(;Ou#5i$A-9HOQ_6j{f8aZvy zKh_xhl^)QO*NgLse_{~Vokk4fYCwOWXYNY&(0rY~Km>@j4Z^LmQy z?X*|WThtxYbJR7bUUOpvKX&S`pgrh2=);rzfjmHmIl&9lXWb3o5g+5PlxyZ_el9id0J3 zEfJD3T9Lr5Ot{pAw+IRIp}-aK$Z#N-2uq(V@Ps|CP^{eV3`XN9law-294Rgihl7!b zjQE1S;^LBMuV5?`jz!r>w}iR`r6pb^T^6(1piD#)@v3MvDhpIVU6qqacnUlW(o>EQ zWvdK+bWvQ)yHL=_AbmlESaGZ%!k7!5Vo$N`jDfHjSu_#J#bD1cd-Fw9Eb%1@f{Z?2 z(BotDMO`I~p{N;Sy%@`bC!;eIjYZ=sVgeYQ#}~pZd&!WDO23o^30E-Tizh+_u2@3G zgPw#;$bx{UcQ_P_b_*tYV)lt(D3b8Re2GBN7m`)MM8MZA5lAE=(V(wa2xIFdWh@d( zB*MP1^!s|F%@}E2P~h(^gJ>!e^K}d6hvJENA`uV7BhHu%757Rc5*3l+xDQN;#p2;a zu#c~Mw~7*9`C)yiE=6PSu7q5#yx&n26D%uDNm}m?1L-@ztitbfL>))(O^8B zCxaNG5(>X82Bo8sUhKReQIIeh953<37(>B4ndruTg5hv+Od2v-rly9JVjQMuefNA) zz|1=emf3RdZ10_m6dE*@4Gi>!tKA}WP17y9fz2LG$34%vVBQ-R z1YNgqJ4iPS!(yl>D-u~6P41o;|LS(qi!3UfOfG?1vNRFt)762;LPZW*koWOmO) zrmJp|V-AM(vcps5(ItcG`deovc81Ozq;hIzP%}X>H9EG+DIsPr7ApqB*cntoc9#oQ zkRY2+;#pDEEUf90Hx^6{6TpmBIdx-B33=>BW#D9H^AQc0kF3dxyrOLk*^2H|z@r+b zYJzo{j?v=6A+s@)o~k^?!6%hZZg7Zb4P#ZkS`9`dTCJLtni@AqVOJcJ;41rP&x#x9 zh|^M&!!2*J)YPrIRYP?&0%rzop-Th9G0cI}+#_%(W@F4Yc&}uML$TZV%oGk0<1wXz zBUXtVF9PX?k{k$fn1+!tL*=M>@sWp>vc}q&1#=a9)SW7;YO5BIPs*qsI8QZpjuR<3 zoBe#}%u#j?q{PYAzkSE1PNrmAR3zbvAi#ph=D-3AKp`E_mJ(JqXV%V%E6Ij2VZbPm zeLw;c2cDs26>uRAZG6BOQIc2WvRS5CtSq8L95)6T4;itN8wd)&iVfy7x@0iPit1)Q zC#+iQaxy2GOHf12J#--eIAOvLXX+dl!Eg~VLbC}qP2SpUNc>LB7E*0Owh>ejfQUhV4X7vPsKV;RX86YwC6O}*Rd7}K0!cI*r7t@=B%&Q~A={K; z*z6>pNq1EVIVQEtCQuthX9~s(`l+#_C(s@N$u^sUlqrr@2XSbT7y$dXp&zpt`!k2l z5s-daNkrE+;1G%xIJDswwX8&zrrGU;ml8U(W!TUg<;Mm=SNFIwI#3K%a)Y)pp8;aY zMDqb6f{2nTizjrUM1)sRluTgjW)BK~oE|$c*~P+UhbFyM%c!OhhxRy6HFmREOw%m= z-E-#`sF?L{XcSc8$QI2xNmPuHXeZ4dGCPVWXrc zSwz4owMGpFBpaHYlVzfk1xl*f2qtYqqOL@oRcIy+8$_NJAWe$CWG%^opva;qV&kjn2Hq8LgO+jN;r>Jle!wNW0mm6}W49|Ds@du`Cp438 z5QpsFj@G~=RAEV_9xyR=Z7W>JEdbl?>fWovvidr%ambg6u_LN1u4*@784 zCzN3iB%PWk2f~KXzS*%F;bYi=XtAIF7**G*d$VdM4k^#Tp~Ge1g9&;Jb{la) z?~kO&2BsL~1&0JVf-Ks>baTQEBr3qMj1naj*G+k#P~r}7gnOb$f+B>Ru855ra0!L% zcDqR)D_FsH6uC$c_M-aD62p!Nfm|-RyG9$FS z*#xF#mWF;-ZRO~EvgI71slm}AqmCN~CCnV4i9@(*XbNxwjnI>o=uk=@_qeg+S@o|* zO0uw2Ck|1Bvm|~fDY^sFXA;APMBaf5XqZqR+C`+V|%W1Q!v8d)T9^#(EVNuS8g{(?#I8k4*gQJ1anuH;C zpiWps6*U|ruvwcd#rP4Jk`)J)%V$V8kYP&z(fz)H?%OQIQ1cfo0utAk7s$p7YX{Qse7R`ZT9a+R+7BbJ2 zsBAi0a`0JA1WP5hj3yz)Hap;m2e^)ka-0&1IlyZRMUc6a1w}kwO*UZ=s7L}5ZlH)0 z-`2n#slg;%$OQ;1nzGrPPCEn_q73RHUk!u9V}rapoD^%)4{T95RGB#(S`DW&heOQL z;el?_ZIS~9(Vbufm;|n(ebdI{R@rk!6rP-h6V5XfD{$zP7d{C%ob8bDN)$~L}413tfE^Mhd?nW;GpY; zp45#K5>2*Poe(+;0cGJ>Q4z#Yj8~5Utqm3mb91l^NkVa^cu|a;9Ht#y$TnrSyWMsW z-Hn!@_(3Oj31H#^oU$1dR`jFs0sSyL$|Sr&CHq#Z%Y|gMya3-EUU&!=o5XCKK%yI> z2_~UclGOw`BmpXfI9I{yvbwPFG;!#1!Hu@M*axhv+YNH^b4qOBU@myF0b|r03Q&M6 z2W#~r!|lY$1cb{)wZ`$YB@4j-xJT9jT4WSKk3xoT?9tUpdwOF;?MyclAWeK1P-&*gUG4qcF`rHTi6wkT}kXR)dI%^FhP=Ob2uJMmlrIV zoS>VNN}9yt4OBTaEvAEXXIC78Jc`ar*3k?)GI5AIIw2N_vl1_gkrSD0OEm=nbU2Xf z0vaLbIUIsl97Gm}K=G+K1c7Yu1{pB}x4SD2{oK;AX_yU(;Q=GSB$rJAA0*-AFsZIM zbX(oPAsigoL$_Pu5Pe!<~Mr-D}R9t^+E%NDC!AF5(b`gP;=WZV(*8fN^)?kVMHbnEH*8rou&=sfGbA zqORNJ#u$k~GVA-JS^MOfqGgIs?wrFN2SmQ-qLN~37aW4tz@f))7XXTy5*V(4plD5c z^9d&_xNPDOUL|x|7Kh+GEF?Doa0Qj+ zKZ!%P!XbzGEgYgC8w7dCe)K?lse*b|1k61vVk#1vbj6uOP!Y{2gLFp2>=LYu_vLRzJkIcr4B8x^RUn1C${H5}lO`V|vpA%_#0(DzD+*ae^I zxvFg3(}!gPs$bS*7I}(PtHn(LCLJ&rH;`v{fD1}Wh(oWJIP@SJwNZ&TWErZm0SpfL zsE2H2T`@b=8!Qka$nNnd9MS~YtZqMOVzFy@a3KPRWD?qgWMagMkr)Aanze^EkIkcS zr~`){+`?+H4;V==VAF|1yWNXs+!#23W>>x_8Yg%BDCTt`mw>=jn6Jj~P{lA)Btt9^ zz0ATeIRjcpC~J(&4T4zNG9L*}kDJ8AIOsZnp`0c`s-D<_8HqN9Rn>zVAEvUZ2gT8b z;uc%^Zpc>8HKRn!6rIkq8ZAexdhLA5R#B>nCm27VMR#g{MRD0Wl#;w3imIvSOSxhz^Vzrp$Aqq>Tap2_0jeT%wU- zYWd+{YY3Ehr<06#*`b}tC&dzwRLK`{$PN(DggS$`DrOPKsh=cVSF&`)A@|BLSrxHv zWhJKrYM66#IlLazic;tpOyZe^%rm42Gg1NbrsTi^vD+*T9Tvzw#2kAL$hJ9Mm?gl3 z9?&nO1}X^|$W_@`Br7?`7&r?z$igf)NJx!sc)gGhRHYaJffxd~kZsE8L@qewMN1ep zv?JRj%TQH4K}kT#0jFF{f_`q28fwYoV#GAOUaagDJBY&|w^o5ej1xrng56*e+9O%1 zJ`m7@QqZP;vUzP@>^;N50S>)hSO&Y-gW3gDC`{bFTWw!j?v+7m39?IiYl}r~Q zi$lnV@P!=sQojYZ+~fLBIHXRb#&yD!fiTb+wA(HxT?F7zt>ZBZE`lr$6NeB`O2oHt z2;l&23}tF)^T>DyzClB?fneg0lC4lk95RsqDtOTaJ>&1EsR2SPT!eNxm;ecqCpo5pa%HsAyDWra_bOh%nnd+yFAzf zfdFDEm?iW*^(_JEac2uFF~mI-92>wO5x<2)Dt{nNi5Gxuhw%eH!3B_pO}ShUcCf-n zI-w=v5NDpiaz3Fpi0eTD#tZs+aLeAjZbp>y`4kSxGw>(Wi9-*n`+#wN&k4#Axu&rN zw;c2*Oc+}2KD!Uw#=s%IP3rRjhv*U`0uKFt=m3|ALyXstX1qWP1>Mgv0f*#W2*vy! zP&*%cE6%K(y)b*k@H`NA)=Yv?GmIqRkV;8uf z?s-1h0?6Q@e@hFf=7}DCAU8S1hQ2>$2asz;w+25GAi0ID|l8(MB4Wfhi6fhK1=lTuO2Hs9rH@x09TQ-$~{}*r1D@C~o)&Dli<# z2IJ_Rt6fpH2OZ@wFl#vE&^OrOv65j~+<|fIi#VkIg=R9(?3uyDAzdMMfMBj7A>}3k zIuWNVg;@t<&PI+|Imv3p2OMH~PU&Z~IgBjLvKOb%XS(@0g@+=Dxm;d-m|T{d2D;5Mw3lp}rq_wt5Qp$nh$7IB7y;R^Dq{qb z{C@1P;S(i=LtmI5aX2;b%8SPQfFPIzv&f;lOxb{t(r?b;&~Ntxhj4I!L%-k9Vccj4 zJ%%M1q|Q-7$GHT&7!Bs(1N;L3mGl94&|~ywC`^6~UafVNG(ndEhfV{jCJy0g!ucT%31$SR7h+=2)F|H*IJ7}V ze5Tz4Ayq}-&`rGrrLE3TOiTy=AYYKzQ*lTJnMPkZAj%nJ!E7KC7)g?oIOIJ^--*L4 z&2psk`?)lN(B<@=!eK6#SLkl^tg@{bfDep@Y$MHZV!r@t%W!$2+PvJsp(Eyjwt)oz z?NG++^g>+&H&&`$Rngon2gd*qCu(}Rlk7!D^mlE3$SK9kg#tb&8gYXQcxF=`cQEMo zyIeui2_mcPB`WfXP=a9j-4JF#fWQR(pk>tHX@NKoM<4(*i4W2!+*V%%9*)(i0dYQ5 z55RWud%aEf$fFpp7F9$x&79tQZEU;Rjpwnw54qaXohnx%iPZ!bR z2f2dK23{}p2x27UMILg2Lku&(e3A_oDFAJ+yiXtlOGtOnhk0Y5oB`D#TuE3OI<+>S z7eMs@>8z&qJvmjf%cr!wa>UiM>PWTVu>0vkgCgW2ETJpl3;01{s2!MVQ?$NwCUv_8 zidI+gz`b(%b3K}_2hSWgVy8WX@goj{F_*x{37C@K!<}j;7knpsKp}9?59JHOcs$%j z_CsgTKth8-E`UQQVJbCTT!!H?kV--U*;KpOC_s~{L5GvHvHBpd*ot$(YXPjmFs>01 z;F_>61P}ERG_aRIR2qOeesW0RkR2dEh7q8!vWh5&I1qp(&Cp34q++R>jUE?1J4Orq z$X+$9u4z%C&#Zs3r11dA4o z&k6qs*x{6b9jF{1p3wkM$_YT#gRp3TJ9UU&NCdNd02MX1HGu9QVra_)yGK9M&qWN3 z2~3?Q6!O4(4B?4d$cNTYl_x+2*3%UTARl-56jJHg09b@>?6g3fha(uw;ShcKV)(q+ z>e9efKR_QuZ(x$&h+4Cr& zgUWD)Ff2dN5&*ey53`A-Eyx!Od)*;FQxxlh$R~G+kD%Z5J~@A`+`_~NB$@Q`pfRo` zfqRILJphP8W{7mm8Fk4QE(g587U-_-Oa^1;N=2{(UO5c25+_U();j19!swzMxX)S9 zLQCI{WO3I(!O96w_NttIB9B7Dk(<%%*L2lM7vK%a zC>*-Lf7mK$8U<^(1VQL2?72V*gEClIyWISA0jbz5BMD*QOdJ|YLLDwY)V0+Q*;T$L zaA*g;0;d1z4xlwGqYym4EDm`g|5XSm`JxI2-5CI71QG}dh&dd>0Z{qs)JYr=B)9v? z&#SN>ffn!y86tKcs84-vFa8t~VPUvQLG5ft1vt(-7ooc;_Kd(Gra>ICM|_mVi`#Jf zxYEEb0J2Fs_>aI9gpdxZkKVY`ja_-5hYBB$#31}JBzs*xKePNmB0N=_Ef|81hY#k4 zD8UK!xjg}phD~F{z@azbc85s>wB(1iLRB2fC&dLu3BnAM$we3F2R{~_xE!=VoQE?M z!WMzDhwx;4apKUaK?(vuVhH_!NdXu72M(2N0Q)ZLRx%5L|G&|R!%)a-@wkEkhyidI ziEyq8hfodfFeC|RaR-5mFf1l;IZjGtnJ5Mn+C4vXXp0nqe5Vd|6{9RZFx zF@-~TskDf|y(i$Y0ljXYhlj@<3Xp){3usRqDlM;gte&YH838m$z)#CZdSRM=Rt+ib zL2Ju4zAti=T?0j{Q`A%s?8}T48Lm0a$Z>=EiX;k$_}B^a$BC6(!N zx}l?7)&S%c>lUnl;0QrRf~NoJF>y$H=%pWo1%`qn`L9Ay;gx&`-5G#T1Vv1;B8Njx z`y}mh#NkRPx9h^CIna(4l=BJk&n}hVU7DnWg@IS?QR;&V$pl^vg!L!2+WFE8wK_NBp#vxhUBPSxTt%oO|2>TNd4xh^( zU{-*#3wvk_g&-0TFDO=pLywpL1V$3T)OjK7L61A4=#HU4U{RGMf%oQD_7XUC07+OV z5IX^shAqMF2qSP94l5ke<8<1C39OiHE*(-30I0+0hyOn21_2=gN;cfUCY>fS3&9z7 zhVe~7m$HZ9u+0Kv7lau2ZALT-*VmWDq1zLIBn6?zLjj*V0*1o@1-HEJ1d2rh$OSP# zyfFU9jYQ<8MHqmlk%J!cfS%qcaZFnV`q4{;kboUQZ_sOpGDHy{4w%g#2?)Np6dI^{ z=o04`oWmjfVn+}XNvlPL1=oQJ0nRU-Tt5ur_s5e0X5LY>a=0_Erqjan(!dP-j2FHE2m!)Cn1I8OpN(@;Aut>ZCx{QE2~MlqgW}dO z(E&oiZ-s=>tQfFhY=$^=+pwR2ja0YC3&7jmp-@O|19-g(zsSMDnSKx!HGZPe0|lo- z2wiy41Nz_%g^dB?Yuc!s2TEd}q+Ta+h{MhgWwDsB5{LXI2tLPkS+i8j5icAzaoDMl zloO-aNLC_-uwo-<5N!~oP>3YqIIXaR2wp2}5WF+&yJLKA9{}lv%wypLzyXKA85+Qe z6Hvs%n1MjGun0hYn8kIU`d}dpZw!)w!ais}Fu)fAV_7$gL$D%BffoOtBArAx`^Dt!t zIHcc9W+AvDt_Z%P>9*1@jYO;lj9UnvWbB!~}2 z$QL(+)$a*mor?eJ8%d$1Vi=%hmfQ1!6AGTxNL5}A6uvHFc<^>8M_W) zs0(f*(x8F)4mbQ(k1Yamfds&V0->?zgij3#W=OpUrq68)0*Bb;!O{tgCyTQ<1mh5( zlN~<#LC|0UqLJQ+3L$iX?G6O!7Y0C?ek+NoqH+h|(xJjhGI8OcB8Xz{dh+Z?J7@%c zAtU@lbE)LVg&^@n!dS{7<_xQ;#Bzk?H4MgPR}Xe*>M-OP6GX>0SV9D^6*dSf4eq33 zV*UVb!kiL|L3;_>c@92XKgO6C|T%h*=>x>)biCMIuVoqbb8)H*pBWh1@|`6up@^q(kUeIHV?k>%{dZgDdKa;tK*M4x>>Ua2N?g41zXmJPwlL zl@jm=A{R6T@uJK}AU>k__j4LJ$N`+_fIkk5 zV6no2z!iiM7SZR$|4jQFVPpk;IDnsMm;?l0=o$oYB@Pvr)ibHi$WJK3A@l>%QenaI zK-Fj%6owRG31*7ccg`mT%)FyenWEEqR*P@;NO6Hi&PKD}lQ_g;5c3qV9$vv^9sP6c zYQx}QBduN|uv240z#2pl&A)>DL6k0sN^LjeHx2KnG%1970V~VKds%c?6sz4lzFy zhd!$}2pop66+wp*q{9qhUw|i=1aAl`2}1`sIRPL?NsS9br#1;fJuxc;i^z|@?NR)% zKI{sVA#{W{2w{VnqUwhk2>4^MK*Z;Z;|Uu)o-q6tR3&XFdPszG2r-18lEq;ds3q#D z_&E=EEY<~wkserS*gZOU750SOF_;K2DeQqh_jvqBMIa8LH0iP(n5)`K`CDH4Qp84h~m+?xqOOrd;wpjbSNT)LnhPYn6w zE|q;O0_DS*0vREH(4PQ~u{lM!LIlIXAhyW-KD@WV?*J2gLFiH#NpCEI&nn0lI0%SP ztf;}|u*qO_1PZWaw<{8&2TE}YN8md6Vv$&cd#3Pu0mko-?7eGHILr!<*@LQ{+e?aFdlJErM2j^JC^GzJmKR0oReTS1hm^h5ULxh3~1f2M=B?`vSHwgHmP#3@< zKVO2d;lm~$aTtTRa9N}LR=B75)R16?t?*Ju*~1ElUZ0;h1j8a~JI?P1;}FQ#0M{ef zTu^WX{V7t=>d@@mDMBBRGXy}Hek<1lj5!aK4!}wM)rmu-V(T^=u{MC~OL>3Znx9h(=(5FhHmxFFv2cpslb$p+Fd)h0zTP1f4!V z{4VG)z#-&QUVyoi13W@419sf)!~O&;I%_i-l+lN`4WomFb(iqyhsOiAbQwJHSMJv-~(ISpdaj`7wx*t*MDH#@i?~X)DAKn zl1P3h4kN%}943MH<_qDGMiQ?Jp-@C4bPa+4KI_0g@tX{0M~qmfx}w6`T}`cL$| z`aAmj7LR3;WuE1Smg|jBzRa)BzdZkM`Ts7MkaQ&@$^2x`WO1@8nNAK$4oNm7FHYW< zd?5Kqp-~trj28AREH11loZD0DY3=Fj8SL4uXMWGJo=rVldoC{e)i;**j*b%@9T;0u zY?BKxrfu>ujOmyb$CzHjn0}2h34ABq9MfeO)3y4&`r8cv8)tIW2b=fi9i!nX?tuf8cjw#S(Op7oki7_4T=;-)E$IC)=w22qR z<6?ft7~J2~etG+4?dv<1bu8>y(9t56b~K#WcjB!Rdr$0X|3N$6GIRp(i)zOXTD#+q z&3}yl;k-XyD8wH;AB{Nt#o@mm{`~M?4j(>z=d+g9iVpQW)a_8>Q1FoNkpBBme!uVcdw#ndoSdXhGkGemC1${p%*|J_@>%lLm0+RQTgrTS%f!Al8VT2m_f$TGYUryOsmsgzZ+pRAT?*(p>mk4ml-)+j*(;WHk%@CnY=^ZDesbZgZDp?_sDzYee$RBe))j5 zTsuSlMSdzjlb_4K$}b=nf0JLzzss-WKeRLDKjpu)8?_&4Kh|#2Zq{zmZq;s+U(0`M z0G zF{2-fE5udeYH_2uMcgIs759ky#Qox@;sNn9@vwMEJR*KB9utp>HnCm&LOdy+5Ie+9 z@f4)#S@FDhLGy@n#3Hd+EZ2PET=5gJN}Q=B#d>juRwb?!w`t{Kjn+@A7E8qjtwigi zmC9?h3UQXWKr0jvif6+J;zP(F|i+ZJc78bGX~z9E4XK&Qw$Ii51a)sIRu3LL6c(aJvN67_ zA=xHdlZ|bo)-T)K*xFFuS8jJXN2W$Dc9!=Q+np}lx^UOlJGE-N>^)4X8?ATapzWHl zd)RH8Ueq{$QQPDx&5aFtg@rTA`;KYzrqB|y#7Na-n{{NHO*NTZ-iD!ztCQRNzO;GE zPAI(AGWVj?qWN>0+w}RUyIF7Cy!nc@Kv`R9s-dm)yg$Z4$Hi@ZQw@!6Wo&ia)Xsj! zo$OM!8Abk7a`Qg~rjz>oGt8q)%KU7KwaEVu!OT(M)aK2jQpr)9TQ|?&*|BLsD(O#c z-tKm9UeyQ+i^oPegJK0fF$F+r~%x-Seibf@u&ByfdSDz{z zm{%CU1QbC=q5k)03lIY208I-EIq|D^X2b$Kv~8NwY(6K&g1pB?rm}2io7T#lmvT9g z>CD-b%jvA%ngTb+O>5rVW+@u8DAfoWUp>EV(*nrT8DvGu-{$>iUSVo;Fp#XP#28UF zi9wH9v^?2n6t`Jft7`>FA**c02~6<*)4Y71hYpGZ!DL+u&9I%uRAX!QZ~d}3dQ6u0 zZEGqsS$|q{Tc!cj$jr}*MdS9WO4OL&3KlIVC#N*GRi;+8g;OI;xj_Pl)wq0Gv#MgI zHnxRFwu#n-*;;Ltji?J@Z`@4T;t<$YYD)9dBHeLld;etKFX%bUY(R2bbR^`exN&py zq9ttwt$B-pv?a;ryu!B3OfYz6s(JBD3K}R>dI;SiU|Mb3$kUp~O-qfNGOHO}Eu5)x zn8D^OMUAI4lWNX0n}Nu+*^BJSW-U*jiGqG4BuC*UHDUn^R*JZB9*V9->M^gIt(*9{Uc8adO;gBg*?inT^<5W%fh|qNgI$%+dpaY; zCY5VZ3F>*_PAOEHSqN!TEZnJ?Y5rU}4QUoLEu+$AB7jTrWe`Xx_QvEQ^5=q?%Qm;p zq>PIwD1tvMWmCgIoz$@HQnR|-oT?|a^6e`D$& zal9N>WYUhW^^StcU&*`wF01|~YmbgTdiqhl@{7B_&@!J-{(Rr(devvL=+gn8PXBcA zrP~xI^E1`xm!sx80g3c zqCfisx%Air$FxyvW%0_Im0C9$pPmSH6xb{s1y)S%#icU2WYd!Cmgrj--@RA^Ef;Ae zb8F{n#VvBqtZ>0>9L2M0W@({xa5`QfHQkcdr~7nSso$+@uG8~QFFXCy(=E2(jGi;9 zXWTQx^4N6w>S-9|p-druM`KiS+R zUR}y~5oiQuP?+UZYjTZQ9BHB~j$iG;`=DKTTl5aB3fCDs@W$+K1}?5Dwl#*=E@6Y z4C6YC-<9~MctN~zGVfb=2PG$TQ0(QxT$;2xj$h|_3%?K`ur~Y?M)QVt7kYS-bCnx0 zhd<%zUgTbj>;EDcJMe2j;f^oFU&U|4uTbGttdO^1m3b~J%UaDZ_haLrpR_{}{Za0~ zNIrt(?l*R{KPMj7j(2<|?vXzcf5wXZHc*(MPc~j69+Ts>gtlA1Tz^FWt;K1nw=A_h zZ26_-Yooid!1$5zduxmJr?#-|8ru&0IrbxtL5_PIpWqucGo8C#n_Pc)uXXRiCh{oH z6`oJLy}UEMKlXlxuN++M``SOwe|^9fI4|%;urSyfd^B`p=x^Z>;TywGg%5^LM5-dA zBkLodMkhw^h<3zQ#a@Wt5&u)7IB{9xcZqMht?srn&yu$^?^oR;-GAKuvmWUlcjlj0 z5HHwP@Q>uoE5sO{(EVr^n%jIN;~=t>T`3Szm)mQ>dI!7?JN6pSx4V!UpSS6*4Ut@7#0eO38Y+pFHF`d!sm z{ha-J_8ZjiZ`Ic79@XjUG1c>{H&$O){b2RW>B;G(>5I}oNbjVFZ9vZT1$bliB4i!V| zhOQa9dFW4uJ~{M_p@)Y4YnW%)EyIr2hwIDgN7m1(UsHc|#-4dP^LFNw%s0b*!%Kz_ z8$NybnZtiD{FdR541a0(f#IKz5F>&kN=FPCv2~<%Wd6whBgcS*N=Q?tqsjh{CD zyzxI6zj^!(<8Pagnou?&J>jPlem>#J3CAZ|CRR-xIPvC*cTap^((p-RCcQNI^vSCy zZ=Squ@{Y;>Gx?8`|2^f7sijjNnKpRZ;nU`w_S5O{=`*I!o&NO)&L$hC<{o(At&vDF2&Z(R8(41W@)h&ZsMzqXnSu|J7T`_mp z++WWw=pX+`Z7X zFtjjl;f#g1Ec|%UghfAJ9ACV8@$Z++T=L42H&(V8C!D$A%!|*w;>_J=zJ1m?XPtM}6K9=RF>%E&R$5lhU-`h<-Oj$^?7yvY zth#p9eXC=u3s#q`9=>|a>Nn5nf6hJUJbli-HN|VDt=YQffi*9#d4J94Yi(-_*Ve6_ zvUbVZ^VeRt_NldBt}9=+dfmh8L+j69e{4g|hHE#xbMEYo3pSpy@tlo!ZhT|oU(R!! zH}<@n&o4Xwi3^%8_~(V|E~>m}??vxlJow_Z7vFvHuP*-grgJy_?h@N2r(bf`B|rPY z^dCI+G$I zw%)&W&(@E(p13Z2UD*Cw$ zZX15vnA?7KyMFu3+h4o=(Cx?Wc>d0_?>v6j5AVKo+tojrcTdwjx8C!oduQBx>Ag?i z`}KV_Kb>}e;r)9aSoOgE2m3tu;LkEYJMU*ZAL{ndx`)1ec;my@JbdrNUp~_C$nl>) z^l0kQA3b{DvFKw9AKU)ezuIcs?%6K4?|l5G#~*t9g~z}CMZ+(~|Ki;zCOxtH$$}?u zdGg?n!W}Dj?0Tx_Q=6Z9ZKtvGx~Jn$KmE+aXJ$OJ@|hn#bM)Cc&mMR#{oK~){{H-g z=kI*}PcIC6;e{8czBuc})h}N0;daSHzqhWJje_8p<;lG^r%jLhk__f}zz45yD_2}!DzoEZz-Wx}DPu%_ZugZUQ)33gK zv*FDL{wMf9GymtVJ>BYG2d7dHdGyyJp{g`(EAm;l6*q?SH$^+auqe z^Y*&8uYLRRxA(vOmv`hliFf+F)AUa3I~(4)_MHdbdFh?syz|w5&;H{5nfd(XR1zq{|d2m;RmbigfIzmt|ad{h`CMO5cPxy}~EX;Q!W|@W1*tWYQhCT zsyz9z{`RpCDu?$D273>$EYI`_h5BSL+ROF(^$}SLRA#zaZo&VM%yUTW&Fg+$!>jWI z--eI>(G>ORbY%;OFt_D!OR%o;F#5-5b%i+O9i_i4)t<-6*m2^h=I6mrGqAX^v>Q+0 z6Nmz_C$mY{yLF34^LyaMV6m7rA@I^^WBXTeIXN!l@xn+!ce}-bpQ^z3d@P~u&Q?Eu z(*U38e&dv_&Q(s$*){QOakH@NT>ZrTB@saS5UbH)5JvmpT+8` z1Ho7w7~aythjjKSU5T073L}_#D8*wyVJ(hOT2J$c80p%S{z;|O+7C?l?ZlVI9~k>r z8L2!j3nv_$@Y=)!6OW$g@oMF(`uIQZZ9hZa#AEND-#;|FZt)_rJQo(ZAG( zk76{@Xc-zF+H2_Ap_dIchI+5VN0eGVg}UD5YsxS0Gkkb)T{v8k*^!Y~q0LZnQN|l? zDk@4Pi!;TOi#HXw6&pVMSjQlIqs%_p)@tLce=~M?ybuDABmg9kGB}k5f^~|NOhc-| z$?g{a?^>#Nw*=})?ey+y2yYvf8#U&N`07!D}fOG_( zzuS-yh~?`>{|c=nQd1+t(bxdIBd2J<@;jDXHDc9*nPq(zp0T1o{-wrmoqgr(^13r_ znRnIcI~FY-e$B9wdDqUZXy5PYURE%8VEfJe>uPG{?s1!1hdKA`*4)v8khJ5MI-^jGtHygdn{?e_~Xg}ypjh%DO)OfG_g!i~(h<0sdedLI>3g0{t z^&Nk;?%^+=;S;r z)E_y1q_Uo8S&5VXcSn>!4;&asgS;*N<45{caXrWdp;{G!bm{7v0sT`wtwvTwkkC{a zQl@0+|B^kpyt-dyYjwGNwsgj2v!`Ejdf(pDe=uvtrOoBq?Z@ByLN8nO?E;%n;54&< zMO=L01)GkYf8kk=tgo+M|HxTqJ+yAvuyqf~rekA`9mlm??!(M|IG0PwpW5-6@e1f$ zj?W&)h`TexOGfuD9dy+oZBSGG=v1$AizsgRVT0Dt6xM2LeU`BNDqrr)Ka{Tx&L5Yr zS@5kZt#^JnoZnk_x?~=HsXt#fTVZmikoN6xPJMN^6^Ut zOG|1%NDlRt){H7U{%NvqLivy-W$kaK2g;^!VQC~(K+TlZ1+}bi>=dv-Tc7%Jzq%{Y9$%c*bS*{>^n% zM7&=c|7P331lv|xCN&IdMJq|?>)Il={dMCRO}(zW=9t;`1xF9>oi+E}k3QS*mE60l zW&g*2XWRAK3`-B_Uav@H!Wkj^A?-5nkGz_bnDaK}}jec1kJiCj@?4Yyyn?0CHWz(!fuzI%f#?RIRLT!mJf#n%?U zr42hX$&44@<$ehNJdN*p{~Z5F4O^8yQe7=8tE+LrYzhYyLM&l*0x9`=`}OkdgK}m2 z4F|PF2j%Matq0qG#F4juE#JgWfm_VT4BzH$^B(dZ^;#;u^BMh+J@TS<89z{S-Ua6m9D3QM7YG!w0nT&ZW)he6c}<7Mkk(?&qIIF z#QOJw_X7$eL$!o_@YpfdQC^d*gTxeP5^a$~k)sj4GEyJWoY+h8i&ivd-0l;V9Mb0` zeC;WY&$?4Ro~@@kJLm=9A=Dd`l=seftx`JRe4%w=NDV6Z7tj{;wq)f%`gsFE_m&ok z4Jf_g#P8cb)e7n4p*DVNvEwsKDR$99_(ny3#@B77NQGBAd#v@@Vr%gec=bm(Pikk% zAzosf>RDV29TBXlNmt{GsYX`o7E>2kN^3X1c*VufT`;uv+!wC6=(&rAoftdgjAgTD zFB>qXBCH+U-u{=Dmn?Z%Mz?R5@t2n_dAa@1j~_dJ?D#h)G8a9MInBYG`e9UlQIrY$ zB)(@TR^BFMQno_-`KD8K!q?M_Z)OQgXaZHV;2ze4m-)CfzXk!SV&` zuWerb!20?j%dVQ(rk!>`t{Js{)!LC`r%r5oy>#55)SxqOnK$Fkn}0lEI~XZN9k`Id zs0NGEGik#mjX}~7J$nWmr7MN#zS1$Y`r^RWfEF-%Za6C?2c^cQv{WkAukYGgTWlS^ z#Rr!bjKX*!l1J2_IcBJRqy*~}^OdU-#dquIUBfBK#{`CflThQS0p_h@Vs2{sU;9m8 zGjjWm#;qURxPITP@)n#Z$bZ(XywdH z=v(85f-FP9b$kt049xVv51y}d*>2Mzz~E-LxFL;oj(A)P;HNn#0Gwp{F!hO=tx_(K z%~Sx3m;n;1r4Sa(Qk%m20d>pJw)Xue?$cJt?rrTU{@&Br{aW&326z#~czTNknN(4+f#03eihK4l3X{Qj(^ZA?{6g7MxS~)i zEcC@!8hw1U$}zXE$(Og*f-fxLt543NH9f77wfMO(lP?@7P*etFn!!1{B?KZfsf9U*L-O_H4 zC#UQ84_fuWSsR|ebd)ocAC|6gD&aeO<5{cmQV#0~?MVBv_QUv5~|tV__(9Q(3f<<70yt-~Pe%k?M3+sCatW6^||{ zGu+|2@$&}HyJh*nkr%YBJnOluC&}ZbBm3peoLw=#rbi+@PFt~j-;4KcY}D}f)qgo$ zBhP(sNw50yZo}3;a`uMjE^VA}*WW%asBax{=J~w_H5H{7PpJk!`J136Si4z8d8V5S zOF)bLVr{E-Hvn&e8N?4xtijrlqDADSTd-ow%)S$%E^h=gqFy6I%{Ojr;Xn$!Dx7Y9!_{W&Uu zk`k{TQvMt`NHtfXX#-~8b6!*LQLO_9ojs#}(+{3pv3}=8!~2e3GN|8-`l2xx+_S!0 zdVKZrWvSXxsc7G(boV`lb*1q{SzWSVU|F|#pFzg%zRj1-9C7C94c!aI&s#rc_K%hg ztXXu!>~ZI|j_qDBX69MLPrr0#-*2AlJ+dlq;gmij>#CyOXnJUqJ}_K7Fx6*hWl_*y z+;3R#)WBl?puMtH1zFi0o$2H3DUIHwdI@DW3Aq(RA;8t^dgMuKo;1bQ2C+5Gn4((N zm{s#ZQ3%eJh0<9vAd2M$tVznN=iFdQbCK!e=5(c{K#A=Q6x(3Y^u9`LJ>h}lTeD)j z9b&tAa=WFppdgbJBSLM4t1r24+ zU~zii@iG3J&!I2vbV7!ghC-#o$q#sG`!PbdNQyHvlOJ|J>(++2$Gf$S?yKClx^<_! zo4b!&cgt-(+j<`Ad99(13YWZBbN>~;mzqMfFZJT*EiL}zP5RCg7iyQjDR*p@M~}9@ z(*6l3+br*aKMi*Xh_BA%+pw7@#^ATjetsRyp)m$p?dM5+0eF)5y*GoS5p#A)V2Wj2DHOImDTIZSad}(pur#SH&fN+^DQtAWntynE8iZPH% zIMSMRkTzDs=WC_-Q6ud?%n=jqoFfLoIpViDImu@2(i0bQAo3aXGW2M>e{1_#G@a=9 zSYHR9rv#R0U?yMh7V4%|-_*Nz310W&YU(~T=!%K*+iRl%?}V5IdM{mnVs8K%4~h=x z-JP!d9Gys|&A!(y^XmAy*HZ<=9w}?6>NBX9f5N23yQeQHTfAab&64}h8QL8mRP`B< z?`l7gS2g_PcH?kvH;zqD8#lVRuzz}BQQg=AgJ7XSxxHdAje8h-yG0&Mv$yBOVEUO*cd!|wEpXAs4 z{>JJl3%YfiVj0pXDtFgoivHbHQ`m8mmAm|yJMaA;yi`fAu4NY;a&xD&(ecDl`ts-shGIV!WuJ(eOB(x;;&y-SxZ?}|-7svaJ0ztn=$CpUj?=zk|)}Xb@OmOPLMXBhJkqtvCT^zs zJ6-}fD}*G3BrJu5M=4MW4u!InmOx)2q-+H@gto5xJ%Fk`f8>=~;f$P`g4428_*DXBZe9{A>OzSW*rx1>5b++Ngn<w4n$jThW>uwhBU;iy`kQXPz}xPE=(d3{N6v6U{mX!*$ZHrGkp?Zr*SOBYN$ zlfKeh*;!gNKb}kaYZq*nNXE6mn}nLo@_ zt6l2~gkhho8@5{c!_o85lbPOu5*A<`O>KMkA zWPChQ2dToEsX|yYJyxwSWjFK->k&U;wtn@9%Q~!)Y{M$Z68YIQI{Z^SZ8-$k_Mm+gM`sB}sR0juslK$k-B|pBf zX1wEL%ofRui1*GG+ET^1^mn~Mt?OqadhPJTYIcp9b*Wjsnz_|1ivS^=YFLzX!z9`n zGoL04t_ucLfjPsZ!R038hX0er@q<$5#0Tu7v{|$vPa}OeoxWOmS1FBm)xw*t%eo7G z-1=;P_GtFQ*)X&R*oaO$e3$xR^UUVdg&c0CPOGu_F3e{+#yzIJE7&$Nr;3p9PRk znL!n16zkTWifLKDu+}hYV1j{V$^EJky)=AH7VFAl^;yh~KnDHQ;V#9DPQu|Zy=)M6 zES|D(EFr*8=Z+N^GEaZib=#8h_{dROl|lDT8Q88B85< zyfrwj`Vm(=g7wtO!?;UGQbeVq=_F1l3MigL_z4=1-mNNWj=%!Zn4RKl6YC#+RJ{Gs zM<3~v9_@SNk-qVsK7pO8P4}_C;hn5PWh$gb=^$?4)At+K;-2*__TBbT`@?pX0nm<9 z6M(|2ytDJei{o<^)dyMif-4WE`wUtpX6bF^ zeT}N?zSw>F!Cf_(xh4NzFI}iF4s%67KQ>ChFOfJpFv`kxZEJ^7$?j=ekK4xB3FNK5E>^KWE#E* zNt_5OOL|}Wkqc=dEl*3i{rrpP? zeN5wX`XW9Fre(dr=r}AAB#-GD>wfEJR>^A8A?h>e15bOlWvzduct{jQL$$6A#F{#% zE~1lkL)jyFUQsmZrR*Fl-@Hy7j|f2WVIeSyg)`I9cru0`Xg26077MbF1Mx9C4H?C5 zG;qT7s*@qyy_r4?s&9%br{700+gvs4W%s6!1IJ+~#!TNUUplZn+|$+Oomh$Iyhk4T zqEj5pZSL$USi1Vlt20lnx(-k66s}5@ut1KhgVt80cuEYxYPP_^93Wxta11%ux&^n% z9dJK_7`Ms|Q0Fm-y`Cn?j+a&I+w`Ig8ny!5+@f#OGVP&LpQS)d(V-pEjkp|Qwv?me z`;VTQo|zt#9+385=6l)~^teFbl*i@4LhQ%u(z_;}#G}e8Jm}S8Bkug-7i&A@zV5Dh zqqP&gc)lmPIs^0PH@d|!@`Z5@s&3)9EvnyA&b-ya`XcTd+E(kZ!|qY{!)}#e>Nk(LP*G=OV427own!$f_sQ5*&K&|a$k6ApKNuK1_Q%ma zSRw3h4Od>ZYxg2?cimOT_O)Xt-E#d)SEVHNh8>$X{A$f3-{_tAOm(nn$Ne;8u&bWL zjCo)=tw_~4R1_}2m~Bj7kp2V(K-u#DHs!lse&8D= z>CLG4WdF;=D>jFY&wHM5d8${N$Fx4CGO|2-F1*No+1_Fo?MBK=@Cjb#HF>=Oe}D

R+SfsQzb(CD>qVC@!oux^bEuEbUlHH3var3zVovW*KP8o} zAK9>S;^K*;s)NT~UwFxIyX(qM=hCNXKx>Bfgp{)k(RyJ2GGohz>1_ zSOl@3Sq<(y$H?F-=L30gG_yaFqjKA8}>b*uPPv+(gu zM4w}unmMo%)jZ0VCrQWVU-7exH$Ag7e)ih66^R9<_E6KRWeN1LkFo-uqNq<`&Lw-jZ@9_{cik|Drc*?8IVp^Fw z`q^4!`i#2897qPNRkc-5enLgl39i<;QXxB%QT+OQeU!H!j}3Apf@8rSFiY#)o_Y?`{%S!s3ybT7(A7&Ytwl z5CYnYhm)C!G4MldvEX`Tz%nZCnCWC2ydTj5{6%rfl)X9AA)^Ba`x1Ywc@pr=q_iI) z%$oE==~`C%nF^$kDwV}%RVi_?@xA8WHEV*wHN(9YWo(*F7+Wi4@T!7q z3q)4|D*&yY*Q+g+tnMm?O6N7zTdVh0%hjgp>KbDWbJ&>8N?jCMs|rT7>{2Z&(azO& zX(f-A>2QWwrBbiW%hXT-77IVU2x2qCh~eTw2{7c^PEI7H5W$o|5)A#0Oqv*Pm-#gP zLog`KQE^|FPq@n2s7hKf^O+>1?aFSn69lTWU-b2pNvQX=>5i zC-qWd{3U&|y|25);b`q$+SOo^@-k9}dyUDi{#vR=t95Hdu)qo6aK`QI90P+Ou0b94 zUSN5!_zZgtY>R=ZH4Y>VflF>03$WqRB3l+}t34trc9<4daLh3O0K{S5_*6|z9?czo zgX!aD07OywtCG{-Prr&kW9;YYbJ%ibVS3h+9ukWtelPw*e0t&^V$KA2RIo!Hz}T~d zZ7GKeCMRP@bu6xXL?;?`EUO786|J=&*-h+y5vAg6M7)q-J0_Y$fRp`k9Caj8@1?*~ z*&!f@L$+igYE0Q8h^fV}+VJ@+fMVbS1Lbgr5=fx2Vr#RYxSVBSbS>%smu_Lb(ty}M ze&xh-VwpsKA6ysNj}dBx3sdDA;U<`@u8wScMc@d!YK?ZQcCU7y_7U*qXyFVV&HgA` z>dj`0ve`PgFf@2CULfOpd6D?Aco-2H5qItmBN-uUn5Oq6xf*7MfCqq8E^ZhlpXZFz zp@eLLvVYtno;$H$dVb;-@v;}B51H`%IPK(7WLs><2sJ`}$|?*0P{Ta4-Alqx3IYM_Z6Fd2qZ_yz=h!Pw#}c zHlF^u)N`r>&t*ACSqAJ0fWv^k&=<{ARZ!{~e@H^M%(w7HtV=#7^{Rtlb0|)^Tj8o` z7+siT)C_C3P@10+79a37K;x8u!qe~23-Gb3Ak?#6yefZqpv%OTn__d~cKMih$;!nZ zd;a3ZT|N(9hX}2dmUkc*bB=IUs!`>$`$U}~*C6V2xjHdLpqAbw&S}eA7GD%U92etp zR@ffbGkst&F6pRqGN-M_V-kycG!9e?0cF5>M!+3C4-6Nw=a5JVGltJka2j5%P9`Vg z|2+S}Ze|+5%#;HGq*W@a*9Mz=&PughxGescw;t{7=(x7^oTdM7>&wT}FRyJ_nsBxx zi#w|FZY!NvY>Tb9YW1V{Yt>6zn~OugDyx3_`3a{8XU7X5xvkz;yQG@z=Y2rCb|Hhu z4@QfcR6vD`UnMrDUA3aZZY*rGEG@SR7JIDQq;q%z-OyO{D6njhIz*4akLT$aAP;ke zG-Ny5)ZjEmd{zShOrt=>6n7RsS$@O1+S(1@URkrEC1JNC%3DtUm)>68-XBl2m)JyW z$%5+D%a+O8JHP#h8}=UicBd0;YaObv#!Nr#^D|zsTKl~vi zbRE{~=ZF*eg}JFhorc2A2Ek*Z$a3(JAS(+l3T_EXwszI>fVo>|a&`+2F8kcZAO$+e zcaSQRot6RTxE+R>uTI)?ByrnCPhPuV;k8fhTz+8T%H~UwTSi9CU2#KaxUIe0)_mQu zTkkt@OyUqsTHxGbo6K=cQeu*vUwO3C@wEsWr(H?RIQl+6jC?Mi!r& z#jawmc!&0)UwwOV=T$$uV9R5d&7W9~vf<%|#OmcsOQMVWH%NC}a7ki$Q^9y&+x5S{ z@uolB)H(k@{_B#PQ|sFcvmHUl2X>zg>%=W!sYC4tFwvPR(Ydra$bvMPJY}ATJ)+6O zTwi@^;~-kVp}%7votYp(?BoMMpX0OHyS| zh;P4@KDvK@<(g}j4P0K*;cuBUxBM;X;_<7ci*M@dJNNpfA)n=qY)kjtHj2^N(l)sP zvp)}>20Ht|TvK~HYwrzs7WS|nI|4|9O(zDMcmU}Io&ri~0x#gfU#N{C@srQN;0vVl zu%xvyuIcbwX4g#T2&uWFlb9Jdo{>C&c#$%1ka;$lNB{>NDrGVk7s(!S!w+nx>P`DL zIjapeXKry#-b0J`tcrKt`o>Kc9JrvixNTLLy(nn67F6f2TwinEz74jD@?w2@z#i|Z zz4QBLufN{YSQ$FMrL`l~wBTBK;NC?3g5qV@k03$O9L}}7jjC|hj>W^bpIaMSd_hM; ze=3@-4HPH5fy&aTy>R~p{WqLbi7QW~FVz%qTG`oDYzS0I>sF79tnS}Lao9 zpHQ6&syud&$l8Que!(C2@9|5<>^A+YjLa!n z(Oow3-SbE%-GqT1$C#`@P0CW!nYkgZLyFLkMw94ENMVYKmFU&O{SAY@mP ztwxEcGZ&1En45A-8}jq#mU=v;bMx~XN^@BwjYqXRRvXI63Dw4m>q16jsP2m&p?p>l zPd${jW!^s`v|_heaxEeZUVU4haaqyfA{GaZzPCtnFF8(8Od=dqFxqZlD@_1tA!#2n zQWq6~YGFvh!T?yCNwCO(wWo*f*TvW6`>XTar9m4jkF5A+_32|y+j6o$#?^3IUOq5j*1iw&NVem;sT@v zt4weuO^6B_v~9Yj#%z=$m~9h|&!t!WF*Hvxe1b|2en?JaFSdQk*zJscg8{@w zg)->H$ggBfA8N~ARx(_|xLn6vCKGuBp!Mu9MO58+c2I4H6e)+8Q`Ttqlq z9~4g@D0_zBC!9Rn%aQp)_$E)3w99MKM?1Rfy60dEoGdcC=J)o`*?xD-?P}>;J!kCk z^shU*HxEqj26<>S))=)eT1KCr`u#+N{_DZJr*>Vn?6y=9qUw)PFg`@S)ApJqljxkt%v7{O?=Vbzf4$YH8H zrn4~}LdNa-6~W;k6WSfi1KMtnN$NJwFlZFDLArK2clN6l4c{Nyv~g(Y+>L|cv+Y+M z-nHeYS9i5v^^1$>t5|;D{Ri&7?}tCU?^}Pkxx4%3KYZ)DKit&Sb<-cX#fYNehZaHhp*BSSId&rKTB_3F+WNga_1iR{u&>89Bh zBdoH_iE2{pUQ8;cHmE9W3oWb2!L*hac=C;bY|L$mpiJ%=tg`TI(@QhMRB69b95lj~xL>N138QY&Nypd&fgk0`mo$oZOx@9KRXr#j2)&(qbP(;i75eYe!; zs%c#zZ-+4_rr#8Cxo+P4&5I_UlZW=l+R8n&kIsfQel13o6wXO`RiJ_sDTa>fBnpJs z+k_RhM{8NUmd&9Eha10})28z;ud&Zj#d@L?2#OY%Og-7qsz1RG*(!*3B6foQO~R@0 z%pv44#qG@?gORG~gyShdb;{y``G6phbZu(q{td~Yr9IK&!GRUwqPnozFlW`m1?RTr z&prRU!y{wx3cuOfn9M2eYG}WpuY`52{QAlgjmc#hx97WajGi!T&~RCPa9;2F_MRO* zkvVhzP%x*Y(B=Ww!7c9wvgD@oV%)CUhQfKTyU`diZe$OJ$uxE?s zF3)j~+UjfrqpWFIzeRss|B?O_E>=ZHQ%X=^yLTP(pBp8HS zQhqgVVW>8&Gwd`RG(2l~$MC5^dki=%1;u^`JcRHZs#c<4Vy&=IxL9~XctJQRd@g7W z1U_Z&(;v}`h_D?=InWFw^Lpb}<6h$<#@`razY)*{^Wq2gz znbh0yObO1&)HFlKKo_Mw3?Sg+6NCnDSY3%r8=&zwKLQ=?u1~%Fx zPBc1ZIcfQv;9mUlRrA~Cf0`vTyev4?i)qEea`EzeAxUWDg zxGl6FS-{#`6Za*=#BE^H5QSoOt|PZFSJD={i;Ie-Vr{NuEw9*Dail`5pb5jZS{)Up zimE+Td#glaRR-qGwU&nn)LejDjIG9)+T-xFc_fbq7y-nB+-Ly1)1Yom4AKhUfRqd% z-RVzC-V)}MrWBum=1P&mNJtH^LqoYtgrO%gm@a)M(PT@XE|(3sa=_+NJFQu`C_wH{ zA4yqi&B>K zW%5wk9NE0(9G|tJZ9%GBC%Puya|~=e$Ll_O+tvvCh)bgm(zp^Umn}@BR;%C#0Te|t zl*nB0c~z=AKrr%Ckd6FRP;C^DL&2yH4>bf)0SuE3-~fN7)NLofQkxxtR(G035#=8`Zm`8)Bi%{^iAxt^t~^=l)hK27enbsSntH^ z6VI?sX_O&hC*y>rot!5eNX>EO)#QmfB#(WX!;(47K`Cx3;iR7ZQO}C>wR$mE&$PhL z_8E>KAB3i(1k*v3+JUWsy@5vpzX`~QAKLBjF!m~A`^n<0hVRW7DwB|VfEls~Id7=2 zDln7s{4TRc50+OrQ}9T6Ktb8j^lT7QQlk8E>1W#B^lNf%%*y6gMBZ@^#W>*KmDgc(ax?Dua|47OM=p5+vzU(8};%;cW6da1S ztmRqjvLpq;#!CRsXYCV@h@zM>SUN+))P77K~uCMT;q_8&!LJ2yo+XbVkNvJg=atQK~W* zRwt_v0H&gdD)QpZYGg>*feW!$`D3R_-O?o&yrp)Rrj*AHG@sRY*_EZ8o8|}J}*>;5}w@bO5N{nRvFynZ|q2qq6T0HtLPLqraD&(IHq&h8K@#e z_N>Tui467+@e(scq?mlmA0+mI#4eH;!bQj|m)1b_2;hn^B7MGT;#sn*NC}`&5?WCC zD31>hS`*NBlQHKE;<5jeMEYJfbb8XiI5b|a3QwhHXNniF2BWY8Pau1sNI2)mIYoyU z0tdK2Q*C`Xd^mg*KwE5I?2*`!n3Q)uH{1izc?AXA$w2G zUaSP78Htw$Pn5lsIDss+-^ET0nw}k`Fap5G^0*2l0USI7F91$Yo=3o|r#XO)Vl}(y zA3%Lf&BmKoKU&z;-sD^_l}#2=a;!2eY9!I?Wz~! z`S18b-NR45Hkw>q7tKkJe`YDJ>#Mu*wWqe-H8O|fb3jPTdienIrK@4H4$lpC1+kgu z+r@-&zEPYjbxGpfyskWPuB*!>CiL_5VnRJ16&^W3DNpUv@mBK_{IYfK?Nurkrq^NU|`=@zv>U{{3F}6*upWtxHs|Dck*>E8ISB?qxUb zE;*;V=A77N-`-tyG%wK-iMCbcPFZkQh922l4x@dM{Vrr? z%62-`=i2QcF+t>;aDf8Lq!)3Rb1TdNG(eKso)Bgsy#p!asFlvly z%NIxyJap<0DKC_n2JdAhK-22C-er|=X@-?$TO5;tX)ZZ*Iwnjf5V^!B?raU7s2Hr^ z!D{5-(?m}t-{aVTa!A-icKR3O!UTar?7Hd`wrX+S9yw4$p2~nyB%T0>FB|1hd&9Ph)i7}Dh)5ThvS~6 zwz_k_vwGbl%lcZb?^)dGs$5*tzGKOp)|$qq#tVM1_Wb+XBK-raA~l_*R%7Yn=B|tS zV#l}bG#b4QgS~QfnN?J6n@|00l>6L%L!B2I71lC_N^mxiMo zJ3DtRol{hJ)E4rXEP-OTJ5pHe4Wt&YTitY4LY?g^D9H^}C(7L#PeBQ3jL+oHqBH$&fyocciB0*&q!YH&xv z#i>QPHkNB*($l%RCLJ?cm_=vN`CRka{HJ0)ApEF(%BOz8AiUt*jlA)@3^<%k&H(rc z_c-@D)dr`*S>SABjn7vg-GX&IUqIzmgZRq@0^rR_6RZfOq%`v@BLbd@FTK5NsOb8Ej|Tf4LS+ePf>QuqUtOYY%Q(|D#J=O7i#D zrB9yr+H23Qsyh2x^f~jz=me` zHdvOeQ&Eu8CxVM`kviT2Lis`J>xfDi+rT zVvBbz?60qmo?Y48c=PI(wavlwJB4K)ZJ{TSD6op-=hvk?$)&Y(msELVxv4teb9JC1 z(!RD4UPOar^W|F#3mlPTpa65xCk)90vW$91gRnYPA-%8ufQh2Y0>ez!y>Ivcx4CAO z(F4Mh#f4fr9n!M&vg$)^7E+!*R7)QLRrru7r}!sQ!k{d{>5kt_fPH|+M}%hUMpCR}?VQi9SRASZAE-7fIzJQeA5BCGBx+|(;+UdVC1pxdn-)rtbH&EBfp zgGzxM-2JYV0#5K&K0n9mYGEzU2c~vXhG_>|=>(3auk0q;Vz3QSBF3OJiG2$vNU*}8 zq&ZW;&;Pcc7Wv+P#^i~WUb~44rC|ihs zLxNBC96d0;CzLnD$cLZ7Zj-)IIwancVYs;|{UVBSfkdOM_7|9uJOTc!9hxWswUc84 zqLB55;0zc8{yT|ijJRH`6%V4OwOqLQ2|;)2y~i-%ILwyEXlBSF zB!fi~d_H67gdjLhXcNYSAK7NZiQ|cn5~mWH;=RUwI6$jRt)^ursnEoV=y9d>-d*0S zy^{BxqdvC5caiTJJg3iERQPu3pRI43^v9uS;J3q%z`=WRuon0j87!ntksXKMS`-_F z_7c1+*dd|GfHTsXXg5tWoPfJUQLy42i&rH&%UzHBwCn5hn!moFv(;3Xif1M0HJ%ZicpmR(%k*i`3~k9mAuix=nH zE#)=!H5FFO|3090o8WExgxXYovyoA}dMa7L?Q8Qc&C_~~9#0O19QBkP0Kf@&ITcMI zCPTKW5_W_u0sJ2sN{Wv$U6bkEE<*& z3kU}}hCPo|9QwnN37%FGlt=Hr_nwAj!{6OJciyghN5p~jxVrcAN2G)$vGd5cZhGdT z3VPoixE1LYASs+}X_{eaCht;)ZHX%J&tR;5g$Y4?<#e!soq7!!5eOC_zhPl2E)nMD z#BGsTS>`L7z_30l92Jh^!J2%#eWSjkKG|tE+Wa=rW>eX7t_NG=2?%HzkW7Xlz_NzE zAcdhoP9&&=%TWGZB$)tF2fN4Lv1>(XhtC*}gpIyf=RnVs9)De__lw&8#-LuiU&g(+ zo=~_p=Z*$lepv%%VE~$>1HPIGIiLkbi{Daa8MYj^d}KLg(I`YpZ)^oyz+Q&TJB{&A z0<=a`;w3DALZw6j#?UmEQaB-Y{0*2PQ(Nu!te(xR^sv~;eqn29tkh@O9X3tFZt|0a zTG&#DU`ttHO|5!DFe~~1`0#tFD(C@jPD!*0a^Dn!#^7l1;o#xm@!&^6b&z0F+nbAY z!@5xvkNMs){@MACYMi5UG%9W=(G(F6{AoDP49Y3Bc&K#g&d$~y%gRcZ>{{5eeR(|H zm28}wOwMgg$^$E|9xSH{S$vJh@pWYF+L4iS&cVo+!txo)SU!WPN-}h`AL!m!$yTI{ z832Sx;s?_EWt64r!1R8__7VOk+vntm&Wf^O0NBXcg&Bl-MJ>Ym9EX5{uWjY01WlFv8oZ=+VujYuTZ%3{}Y%7sKuQVk0Y}d1urg_ zB$`}nTnKAy#X!NfY69P?B%24Tl)qI%Q&m-_ud%Q8C0rH0F(Me=wMKG?PPCO3$Z--w%CW{4?C`i!gr7RkB7)NjP zVhoFq39HbYzF7J`v>7o#%uf~RbG@?|AOzeK8L*@*y_Pi=b%qTBH@J2qDQb!gVh|ix z(_|1FM9Nsr)k&~~Ou8s^5+X{LDN@O}XW~PXWDq?)t^1a)kF6szh#y?g;Hg=XECLw> zEBY#!NMsOglVlL}MX%?U=G!1+%RmOvOJopne?41%x&py$;X{?sY!?fG`C<))`KSIH zH>%mkkp5i=mt+5!HzaGqELJ7p?-|GsW9+)jD^RuBwG#3GKs_Oe zUT-BZein32z6RN1RaHP4AP@LZzY7^PLZf^u6$Yz8n~AARtPKgB5;I9w8P~S=o7G!k z05O|B%edYS80tuBj?va(v@_WTl1JPeJ^ZkaU87@NI##b^Zj?q)hNRJwg<5;#utMB` zEPsVQj35mpsUhc|ASSADr!=PoP#rL55{(kCe?Y2Jkm8=O?D#(<)rHjWjz6AG+>(Aq z9F|JGkwU)um#}d>Z1zFsC@F9S__CuF zuh!=>63xiSR{|H4PFjAhfQMznSx%nbg}sZ(RK#}DZ% z%kVUqaGI@8HJkgh)(4w{Y-KL1N1C+D+aE!_B+D5Ic#OlYhuL9voJrR(wgpxn!?m20 zVV6aMDSC%$;acgZoblnq55f5$^@$@y_wWd(eh`;lPqYu|JJRU~K2~H&b)AOxI1vhH z@bu5%A7lxu2U+^>F>kSMrY!M#Vm`lQR$=vorM$fu<@)K)vC_(a+kPj);fj8u7c7XD z{kztXy@zJ@{^?j*{TbTR==o^S_NSTNW9VHhsXIe!l2v8wn}jj6b{~|)Bq^vvrzXat zZOSVYX~j{rndzl*`3`u0=ciik)3N2!Es|)L!crB|LM66Jd%IT5)fVHX5J{_L%aJG` z+SOro6;BXYCEPBExyZV#6Mz>m=?!#9aBVh-r-%8KJCY!{%P0azR0aGagP$T;pJdDl zB63&;?6&l)x3W@Jeg_Qf(p%C;)31C-e1(l+Wxoe>HrOc8kUa05s@ zos6e2t12T*p;S<+z#rSwvA^%EK`I1a{oQ$O_x27Ajt9!v3$17ID)4==bZvfboGQaJ z72yp#hQ2YvqCewB;X(hFHCLRIe*MtccJZ$%m43ML*lNV*?W4-A3H;Pk|AX@n}i$D9;ckh zBBbvmSGCf9O5Z_&%MbAJ&*kIaDfDN?qs0UCX-yhjWTTwt&@QB_sS@6VY^aV@iQ35Q z{dYlZ)+61l3F&5|C}dEXvo-x$Bf0K1+2%FsZ2ZvxdZI#J9zZjlFj3j<3C^WJ;c>Wf zuxO~BCupaf@2MJjd2?dN;p?v>Vu`!IHnyX7;)8(yJ+KHe<&*eDTRAIl7jDv@%ysTkX;oO~6*!-Nb6`@A;T-k;_JDfv7-e%47xp{g)((RBM1J!yx`qOo42B z0LDl!n0DGTz7T@%JYXs-2nJ6mRx;b=|BN*)Y>K(7`fAI&syu&v>+Bonx>~z>^Ltn3 z6m`yRT2|#KYFyA*G;-E?=cbQ#UVCK6_MczXAs;UL%#ff znEWndL!+m-xIDig)zliT>S?U3YK%7ZoVDT0+vM$=@7`1yTXG4>E3Z0JBlSUO!FsEO z`9BcIek(JR{r22gWxYOca=p*cdMDUC$a1HYXUOWQskQ~x&1YzvGu5^a zrX}@Tfqn}T^Uly#o@^^@Lgb3uZH;EA#aLOl(t1jwl_z|3vOVjCi1YT9)E?OaGuuNa zp}qP6)ZtY^a=L_@Q$xBOSuc3scy(9`Gby2|NiX!OT<25z*WI0ND$^-~h1rAii zmlOEMp&&r&fSc)5B@zaFB9eY!bA+o>Svpl_6(ZcExB;hC?>Utk4W(#_7m>{@=0l`| z>YLpsk<|aq@Lb-=XOP+sQG!t<^QfNTWFbX zn_b>;hPEVq$|yFWEtjTRk|upIZV;eROiJIW-(swP;G-t;a*-%ht?3)An->^(h}?VQ#A4Ya=j^_Yc% zGMY`iJz0=e%nQbIYD~_bX#qpWcVgZ<)FB~)Y_grH#n}Z^;SXY1orgu+k0QdoqV`23 z9n}uk?ykM7R*ttn?Pl)fHAib$Fsqc6_Uz6Z&ATg4%7br*z(bGCku@x{g)%FXnFlc$ zgl)-^Nbo=%6{=Pc8^Iw5P94;kwgM4(g;YU&UAS3OZ+F8vdP4xI3BW^DyrEF z`8~yJ7VN2gbL63p^V$nKzVVBlRAex3#}Ce0b4|eRUEBQbT9$T}FHD>_=!C-EG=Q?U zxbr}MYvFZwY-+vp;BPLz;ZL_MYC+ZBB|pDnJ}6XHez#`tof8|%mN!SPzoBVEXVDKJ zllyS~ZBmooq9iso>r3#p&Eso3G3GDT&phjSbp>CoK1G6`<`Nv>68zv;xWu79O@c>e zwBET+kxFX5C=mH~ZP`K)sX~h@Jx`295@%>lqvqpaeUM?a4)Jk}j}=s$p*6{jGHQ}| zvO=Nr$qF4G3p6V2GghdC7{u!UY@UNIb>jB=HK}CIK3t|DKkfQ05FHn55WB_8#Op;l zTZ|#QqLkQ+BM-jeV@6+-Z`k*+Pxfga+-qeZc{p+q0ZFUyAfgH({Vu|GMQ)9Vp-3Vk+9K?;LUz*6 z4*6M$f39E5^)pnjB8L}Y^5YGl(dgh7N zZX9Hz>hve(uzll@SWY!NHp@`|md@8kuS4BVu5;0vvpZhCYWY0&EB6oYOO>a4vNQ*< zV|eC2m+FR)+pYD=qC5W>6(SfaZ64009tcflyw7uB`dHTod?R|v#daf0g%Vbrh4w- z_#L(OqGw?eiOb-QiVYZ>>bXa+^b8YFMA7u@p3^qsT%GE9v4mv?swD!q7Zi1lnOF|& z%OLN_^r&HrMVP|8)%^L>tvIhI_ofttY$rG=6fCO%-qh;_u?$S6prbe+q*u6nDYno~ z;mVA(Ly@y1fe1H-xP)N@r}Yi{n(zT5*eE-^D5d!%d zGsuq*;&JHIPsTzn^=W6b>hFBq?bKeZk&wuMbjYuWt@U1;S}&fUDIy|pG|;>5ncf)i8IhN zR3T=MLlK#R|7W^}^fN&F%I~~0L)tLEvc1I4K#P$CErzY_oB!_{*ZlgrHh0O~P&67^ zT#$I~?z^A+a;d`Gkl(Vd)!TVNcl3L=eCHOj=`r`R$aj5|&waNL%1BHOR#ng=Rc}&L zqBXbF`L6FEt;)KwV6=}*us8L^v02tP@0ss4KVafZH0&Z%z=JJ?^>2xixGV=wssp558=vDq>VqT@;;=& zmG|ipUdX&pDc+~OB6^1Rp|w=rr{~8wtsj@pp|{z9H~8Jyh9Tt*CP$|9PkKw~e-ZmQ z(?9T2)*r1nL;tj%)IZh}v2U^-q|JB-d&EBaqH{7G zV?9rs9kC7tIhc1o?5q)Gz>__a#$9_n^79KF zJEUXxBf8X^Z8c`Ahn-zcmhH@TW|<9=oCVx&>Xt^+355I!_(F0VEYGJA3qU>>;w%UwT4e>OBN9SK{iWpX5)T`|=ec?UhTP`z1coSB-%Y6p>%< zVUZoRIn^%ZTk}PGHUpOhPNO((L6odckCfeJ%F!e97jnwf=$^{kX38D3mG~*w!AjpfJPI|XdnU$aYvEHbq5VBv z3oE_%r2ndnU7Hzu4lsZj8l^dnOSQPJRQg{mKoAsN`Q@0$qO`>fZbCbOpV(ax6g6AC zMzOz2OKmpZ9oq1D(2x#L`dTFPDtk)N>R-;%>Vz4ir~&X2dN^_%MB1N$2EEI2CaF99~0Dpb@%7 z=pMnJvPoiO*}PNp*x`BX;dv}Rj|JxO*U<~NcZYPThvt;z*GQ6~tdb668slnGMSj@XUJAQP#)$+Y^#n9;6N@x|bCD<8t#TEJTDb+aN?%Ot({C-DPu zT$FX{V)Y-@e^q~hyE>q4A2Vl|O_Io{QOgb-cEs23~i6KrfX=uLJr8*AhACi~Ox?IOPkWV*6g^%Pr| zHcs5c?&(WEf^?VHqN~AeGiB@Wm4H=zhfcjUhGb~orDE%1#L`tWdaXfL z7`KZVLWGoNt!!Ox7b`uJwD6wUB2hiDRT;rsVvIXl_5<7erk?b{Bqa_OGfGg~J%u-EZLD$U3cqS|Ej@u;@26GYyMmqfYu`~zOqzZom+P6Zz&hm(-QLKIAM z?V#9_u%K``5i-N@WM6Pe*I=yXlui(q6%7|LTydc2POQ_t(6@AhX+-!=sun6nmhEo+ z0%Wrgw?S|ye{GRaWGYG(^%lwZI@zsGw$u3yr`YafveSk-5h=&nhC(jlIndz+wjujS zG~}YR8?V;Y;nEicKR2*Lup}Ik-7?7pHLS4p6OSwAFfSaR2w8cY49O{K%7a$vP~T?sD5aScCgXV=(~ zgw5*h%x%Zr+8{K@T@Q2}tn@{m;T$;{9+s`S{JI57Ame{Cfk;U82|7TLZ=vLnQL1$? z$g`_wq+3j9kP(lM5`jsY3kx-t@yAQgs+y#LuRgm}YMsg{`;?L`h=PCaS%u*>+U#le zcYU^U=Zf?qWmgdYzRfCKXR~wU{R52-EI%>CqMC(!QX6%+D@V&zR$||@N)3f{sC9YV2=PahNfmJL<^^fN`m>^(BvQ{fnQNt6uz7msio;s zilL|!Hsd_Nm&jbr2Z(kiXBJ(}M=@Ge->&C7nh$Q9T51atX`o| zO^)YGa%xG}7qun=G6>Q@Pib4&+cU+YwWzzNhlgadc3(fmKPk3m2)BOety|SVY?YH| zk&d55bX72&E|)2L!_W7|U&s7~+1?pC8>f-9oXhSq+IhlG_4HY^#*=SRtUpD+(^&-m ze(Vh1H_jqDxj4EpHs%j2{bKiTOV<;_6xvar8dx&c$up}6r;*ZU<}{iyR-8sbWvl=| zu`_QNEB4PC>k^E0bb73;i|0CU_>*>hp=Z`;IS)Ud3FO`JnaJdmvN{}gd+O$8%{;p} z{}k_=N+vK5IJD?YuE9}vc1@FiX4}(xM%Lel7&o=1o{`1zm7ae%-7{PG#B|T*riHV6 zMl>CF2VmxuG2;T3$(j56SaY4yFJ|s+v;$if+RFpkMyhYk^q9ed27zDSK4YX^a9ioA8ZZZ{`I%lbZHr*jg8LsMAb$ilttDe`{BDolqBTqDE%Uy_ zll8PZn&}ZZFUtYKhCVOJ&9zu~pEyT(pRg{BKpk3+n15pyx0qSnoHC0>GY)1Ao5*1w zHu+bdm2D?L!@O8?^)eHTq6r<}3^q=C$HR24<22UrWY^NtVYr>OI8c44I4X_&N58zw6(BN->Q?4}l@I!HFnw?Ge8h~3J(=o;Q6%DhNGE^#1>4yh#Cdw+1VNAde`B*X7MU(?IlO`-vs-B?= zB4sJo+J$W@WUCDVK+bfUsr)M?Bstvd-J?Tth16SN7<7#B(qrKYw-`b!=x|o zEuNM8ro;{@%Ds|ghxNg@CTXPLJVRuDW}K1t&Fu}P?`~nA(l=7aVX3CaT<)*-&Fu}P z?`{OFsBa(o7Chds_RXygrSBf$I;C&LW*#5Q2SdjUjjD{BkWQshwA})2Mu2FeP|*69&k}aw#8F%T4WX6tSa2nG4&LSMF7;?OG#fo zRtk5Q<_9ux2N07Hc_=e>in{$A?XY`=GR)GXM!>H$o47`(#kqex*J5-1wX$JjhqSzTH|eyZy`@Ng(7I^qo>9Nm@+a=`2Z%T8WyH$Ht?k zY~i02X`#5WSXeO~H>S4GW)JWj@3}M<)Fouinr)_yD1A?@50+2%^QT3elAlwxcm+wL z4#OGNnP;JE(2>$+{;Y#&jdSWlWh^?3W#egWm7WPb<2}Pq&tyY0L~ofDOc*oeR_U4W z2kMy+^!<1k8iyNw8&7L}+NfFAsb48;MDQo!?e+{}k<~ zTBW&yT#+Y)_D*DfnuV%Veikun=j2$ASlMAKGg-G<_geQ^Ww}kY)FO0eGw#3hEL5mt z=rL$8;sk&Wo+1J$6dUTx(?`Lby>yUsXRAuP=YBaLKQcv|jfWNnu`cMuIs9>=0aI$a2|9E!53?||;QGeqoc?AyGIg@V8151COsjf%(%Z6Q~TqA;3E4NoOGJu0b#ZYr7PA&ss1BAc@O|+*>r5Y1 zh3Zz+tZWDd8&-^;#e&9#t5*4~$@<2sB3=5pe4WV_uSE8irLwltl76i;ktmHNL@|N* z0ncf`S{Q^Ui0*$pgJhy=RaIi|d}6166KF%TvWX|HeJbO|9SWX*m z>Dt@1uS+%=0=Pi2*C01{84O*`lDZD8{P{gaCR4J$MT)#_t2SLXA`|MB_@>64mOjachd$)vL8HMFFq z9Mz}YrGA%d@@o`LE-ID+E=&e)l`-zF6yx(M0590!H;zol?#^>pG2bUF$^O70Kj^eAL;i z@$6ev4*=%~rfdwgr6~||NdmjUC=QDsp<*3x_#t@@IH0I(4{p=OiCa|VGExh)S zItI<$ld8RX^3`VIUJyd^zP>I0{$fi2Ymf4{_#?fuhe3;{69{Iv;t~Q&2O8X91jo)6?QZRH?MGU*R@)9Q`3BkO90ms;Z5(3dg2Zu( z56l_uTofmSl#EB>VoE52#}4?z`tPWt^Hx?B^>i;R@D~`qqb_P*Q5o&+TBvHSs_wn8 zD;$UfE2|e>*c}c=C_F9PDIb$%Xc1cQo>am?wAsQE;ve}eRfFOFN%ethTqQlE`h`j?QO#9#slKNAmg-Iw?z7Itb{+ozIr|d8 zsLFHg^PO|%%)alFWG0izWF?s-lRbnPmaK#%Vn`s61q>jF1X)F(pa_B+sC8>?q1J2F zw!*K7xLm<%wQ3cuRcomQ>r$x;wAa7aB{}(@_nZlfdVBBv2a?PrvwYuo-tYb1<$0eM zguVs|xy}J;SOUGT)i_|}jkK`iy{Dj>(5V&6sxWboN@Q=Lvz{5S`_N3#S$rOxaY1L; zJ?%#bIt$$6;0Jq8I)E{Fxd^u**)uVtE#t0?Ut~O)p()5p_nZLO(o;v-EH>E6Vqe`039 z5lEp0HP>o3H6@cx(;l{G!27(FG&vk_syVbr5BVuSSdRCsP;#sEdd)7pK8GvZaQ4-CXJ7qs(&}(X5?-wU zbrN`kZ@q)?mNJ3~+{ig2sDGG7Kp66f`tdO#0VY~O81u8^ezw=o_W0RmKO6S50eVyA z1`Y$lbtNb#G4>oXFdreufGoz$vt!G8m@fk8Umi`G^YRRaDDtI?D+Vf*d0}Gb%9~!&$fFs+c@D?a66ZnH7F%qGeAqj_Y-47yK0RSofq;#Q9 zb+azS4AI0o0cApp_%IZ)R_GOnBp&Vl$W=+GUM6wbG9}0-@}r-~FKP~sabLG0;D~pJ z^&}pGd`diy(A1|<_Fp1oA|5NAv+@{Tx%zkNs*b+{H-??8WVf(xYW2l6$;{~(VkSa; zD#;Q^jC^B40wcmaJD!HUKYyd$tD z1hzbNe$7}R1qGz65Kus=6(dxOM5q>85v;h{rFBozBw0L`9805R ztwn=E(bErui5T23r<2WCp&s*MGp{$-n0bp?Qx136UTtG~o8QLUIP0Lo^DkO$Rx5hB zCcuZE1iP^VTew*=dZ3&an^-yM#_7$hCX>C+j>siLGkBYkd{|_a8EHkd-~nfYq9Ciu zymZvyw>TY@uG%Mt)wn%+Wb85T-V-_K{uG zlrc4D>XeQ-mz-Gx!UaeqPmmQl1gLMl0LEJ*H!E48(=ll=Y>EU-Zo!D=L5oZ~aN!5` zDLs_c2FiZ5hcam82Mi7^_2)g09Ds6%$QvRzM&F^?VY3Qkw?gt?=ILGpT~Nzjfv?-ty+-eg`el3$(&zYWWJ|pmP?LTl`;kl@P+J3-1fc;}@|k|VKIZW{1c?wSFMtjn zdBRsf^$a^g*%hx~N%{(@Z#<5>cm*R+WEd&-oLt5#LFy6@+uPYga<6c+e1&6bW=bx+94GO@j%^9J_Pr!w$Ryj(x}IZ_N5;ux)3DrylL zWosPKDHG(r4mpFq5O=Z|p_^hRaK)^+zb^fK^XFz>`n{P6zcl~5nb&MF?>6(R(JR($ z_DFrv#r3D_+2MM&x1J5u57+a_dSIRD}W+;Yt&?!s# zrlv_rH{hzk#UJSF8&Lj%l0^AgrqIoTrd{PVV-;{YP$P}fXabI=YGA}j#LbjeF_dDC z3$L4ItZd5(H!N+A$|qgRe|gosn!uEuuisS4yrnn2zH>^TX71KsE_cZ%vzwPTWaYH2 zoMB>5mdsi`b>gKLmVW*GyCpN1Z@994(X)5ptmm8km>=zuz*u(8YCpbU6t&TP6n`i0W2Q^CH?yM{Y?73p9xR+*)4viS?#~t z&r5#4Evs)gT8c%J(Y?_l(bG{e6pclBdmm>Tw5_lSw(KURnwlo)M!xV*Svi}%huK1oG}K+b zko!gQ3S%fO#2d|NX8x0G_I5T~ntes~1KC1bHml2K=o1|PCw*rA+{4uG@B7eCMMXs8 zeo4`Wq8}CsA?3sYGQsq|4vlfw>h9IOsS~H_ShX@6h@7%ri{b(R!=g@&*0_PER znc-~F7*RU2KkY3`Jgsb_SRbnHl^e8UA#E)DMj;=eU#9RXN+GD1w!KnskD5@mj7p2& z*cAdneq`TI0+SZCjb6!CHLsmn)OGLw-TRZz@9iS$Ew*lS926E@v-Xz_J_`AJXDPu{zJ@uNT7SR{`yZ{G52el+{HZ<4Ga=lZ|nXBpq4|EqXE zp+#P%$PD`)1X5yMjY?#OZ%1k+Hm%hYKPTqXj%?>&mFHfiK37sB@>38sUtT@QS9s2I z6&60_xmT;tou)n)Wua_}KV(!3U|>IC)ZkX&KU1EoT2Ec_e`0qaOO=i%9~yi3fWxQS zPpRnruCdR=&5E^kv+~}vU^u00txpeRmTA&x900?pwKOk_mw{1YDtBEn4Os)U$x3AE zp?aI{h_m<|1#DFT>ndOchsF*iC!1Pq1(^kWLBrmLR~t?@2tR0G%Nkg318ZnDwS*dC z4LsMtsJGU%;c0094gYvS)tu%UpIIOFkC^;!i^UtX zTXJ-|%-no?`OL{B4u`v@rSEu7$NDal(vu5a(f*_LrnhdOo?LEl^+zrYg%_;bK282j z7Pw8d!fDZ<)!1^AC0X^w0rG$8T0Vp9M+UUks$`2M%rwYy*xWWAv3eA4Q!kI2#sST+ zX0rzUMJF^_dg{6Ql6qdm62~o`NTa`NqAyKXHlvn)!R60zdV({c5XR58Ox z?9X^LL;TRp-Y~QK%q$1Jqj)zRn9MwG>7~2445!hU9xz!YByA+28gv4W*&tkWt>}Gg-B5yKTO>5I{w%4r`KfF z58pL7`Le|e;>)^z*byzuw1g7qNh) zbmrO%N-nI=+JTF$XicS;-2X{lZiq00ht*AB;I+AtV{p_tuKdnIwxbYS*Wf;QwdQmU z4@a}S`5$5SUYPwV{5x3YVRmQ_ypue&2%tvJu;8AX584&O+1tXz@53VkX zZpK*X8k>J!En=#wSl_6DK$$6FU)Ly`KoJvwW$`=+V#tpv~2oW zf93Lv2lBe7+}d3{y*y*(27dqREz{B`WZJF1knQtGL2T9)(1qe}r5NI#485kw8_DA+lLU-tb9I27E2 zw?x{Sa-!NWo%4_;Rqm>wl&J#AqEVy{efgg9<&*~GmoqB!eWt8rdEfUJRn5Hq&>~xT zb%lM56MX9*T-TgqicIONojE)$BU&_f&df;eh3yRiv(M``I+`#0;liz-9ebf)gM#Se z2Uq;+{+l)~nb6u>k#2UBPwv3nl@k?mXoH<;JZ=xqHTq@+xIjr@OF*z18jW3k zt2o1DGg*yp!r-2Vz@?3YtNLxot;cN_YNmJAc2E!AlWGIflE)80x2@W^@eHiCU{apz z=o?=*knK-a!vf?7oIs6+!4B3$Bpzm<=+Uu^g}fjk078fbeNBe$tQUN22cVyo4MAQAW?Nb&;ZZQ?O6#yPR|l~VsP6wjU!iK!lf_E*{uyRo2rK&z$Dbj@ z8}@jd#7L8qBQB`k@XWPW9{%2>>MNe!dF7EU37K0oPb04pdY26KN^GYzPcS_xzxB$c zm%hUCpL~+#zq0I-m*uxc#!i0r@h9T84?g_x16pyiOQ7BDTs@i%QANlK=N2UU1#n3m zO8TrVHfM>Gx1s3;7^A_%*yXTWMI$EhG#zJO65yGF6@^S`CwNY)L-ty-0u2r)s0|L$ zb&H!k=}dD&LGiZs!rMZ93p|Cd6i-2i6~6~j-E!`ZWSJqCeOS&kX2qG#D{jLC2m5JM&9wqk%GqId{SY$GofO175Co=jG3y3b<-rt*$Fv*Sa2XJ?{FW>u)YS zY|YcjLR@B#v(mZ9DY%^IQI1ULdh<^6N%NOxVBRe~9-F7cv&D1TgF3U+lDQ>qqqZAG zLoT-&NdmNNL#IGmEs|R59ZoS95`;cysx6>U5q24%QzTY%SZlZ0H2Qc;k(c76Z$YsQu5 zw>2$0IBjKLli%R~-r}lRQ%W5OV<7Z;{CAm&fn?#7BJb}uY?#tns;biBZ>rwLOLmd8 zkWNFlVn_?3S6FL5V%9*1p`XYQJOj%4fJhkC_Z^nQh|XAoT#)S#vVB3eJIFQ%SxGP% zHg@w2?7BbPGNUl7usC<1NdBvs zaqU~^*nI0Bp3RtpJO9j9Htw?&9p?V9XzL=Ao)urAbkZXPo~k5u|ebqsb3h06^Yj zwv<7l`F*R6&-t=Dedp6_yC0Z7d&(76!$a9q`jtceJLL4ULtosMD9HIJBl_$!4Lubh zi?edt%#z}PdEL>1o(r4PECHX_n4&3ZS;E2vZA0U;|2a<=Y2uu3SzP?wefbpCwsanc$ z1Py~iSSh!lz!|PDuBW(W+SSi&S^d*IWxz7k&&G~HW#Cw!-Ux?LVN%fqI7STVRQJghN>Ab1Cw#~!z_ z6}Bz5-3WEjH8zvez}eefuzTp}h39}YAiVD95ZF;|TNrZig1+kE6EM; zug{C?faR(H49VIr4Fe83}Gf?3nR3&emUJbD`hKAkb$Pp8{VoIOOwWYO-ciVH5#qrw2qNd!@ z*H=7!!v*2`S@Cyr>kB;5$vyGfMK^R^@{9G8`+oGw3ch{HnmO@~`J-P+6Bk@H;$$bx zZ98AQu4m6p+Y`Gh7GJt%TF0u6Vk0juxNTv4`VB99Z}%T=?J~-lkj=59(3aPUmqM>R znY=MSgXM#sF%SswrnK}lehZWb;DG!>J`82l5l_tqtZ-B-ib%2^Cx@UK(z^box8&(@{x|W)-CwHM-AqMx7XKS>D1LM{gC@ zut6YtOgiJ|ChEYkOLj>*$$_Z$!er9wWmX$=+PE!{%x2g22-_54nn)x~Pc4A;QnR@y zI)Kz~v;-k-A-y@RD?7sJ)2uA3-GM#|8xf6Dl)0a_&ni=9Ix(a_7- zPY^2FRag$Y@LKD#rmUg}3*<*<-+6SM{K4ff-8_>;(&{g2L6^Pfb%hsh9lVBVZ`>_^ zx#LHFy1qdx=deGDlXtxN13o_b>z?)Pd6I^@u~HsMYR3MrC+=%WV~d`M^3mpOx3A@c zY$m;x&3>N!L^i)Cn_UG~!z-w#s;#8CrYBL7NG1jog1_0;Jt>~;M%QUXzerh8i=4!> zlwBfjP9?&jY!|pc=->i4DY5aKg)3s0gh8=9uA|inD#7{kGipP;Be7t5h11}uY+aC8 zcK5PMb2(Pxf zZ@PA8%MSUIJEw1$QyNb8O=P+9+Y|ee;nLYxwA{h`J6d*Ld(+H~M{m6lR+FH_ZmHf} ziQS@`pAps*F`tDAoPTKSmIIEGRQ4O;TP5DB#&790O8k~vTBN>$_+#*j{|gSlR1A0g z6^d;}5n`1!kab1WC^fOGP0q|YuVPYtcZz7M(cvy6;|Mp7=dxI4j{452NV0N8mB{mL zxWGUKoZ**h#$c)cUC9cG(mR|)TIStt@t9q%08gJ zM03E=yU%yn$6xJZ1HNG&8muy_FXrQ&KBv!Z?#+z4-P!g58$uibt=~Q15u6U~ApCAP z%7|Q$0r@Vu8n!iwBf~q0<$MZt1)7wYPEo z)ipuw7n@Hjhzh@Petlvrm?4?PGuTdb2NB1=!oSjD$O>fjW-ZNnJWHeXhpmfq_UEuY zIcyL`YpC$j&Gj#eY6td7ho$3^utQ?QDEO9Goy7bS(@~(+$PEOMD|Vd^8bFi_`w8|c zZir~v6`ETHTSf~Dht{I9%1&l>3OA6QGVO%u^o@PBdOmmbE#txa<~+Qlq<_KUy8FMl zyS?{8)Q4YsY-niaz2Xa{^R{=(4?mq3l}B9Z4*jxcnd|<0nfo`xRV5?2RBNo%xS?iF zqWldWe-kb6|B=-peh!9gI^Gi-1zOZL_KCI=QdNMA+U@AJ9is?5Izc#fCRei_#kdD8 z&tblR$Pv1*!Q^bV^yg>W@JG1e|EIqxtY5<+x z@DW_0WguVB!l)kbISU6&NF-9Zs*24}B#!)nl*plA3#Sq4wqSOleoM72$8%)F*bk>) zS@JWT$S3iRs#IPPCQl?HzP4;9!l;vX{_ZAu{a2>+VA$rW?cF-Bpfxj49tuv#4%+mg zXuea3byd$vWJRaVuTKcurmX$x{ACZUnIsm5|CdF7 z{B^Utq`kVfwE%$)gU9h+iO`v5@pEfO7lK@D3Poz#*KPh*MY^!4IW#f$Anvq#BRU+Sq4y9d;kB z3rNVvlhfL6b<%PhF_E(atm4w0&u>kDjl8-y5ynI(CfN%#Nn$h792|XyuOB^%iOat~ zJ2R!iP|-7Pt}j`uakw44Me5yWI&9*vHZiKj@bWEfz z?oCw}8KEugM#ougfoF5@$p5On3D5p_dNyCFFux%$2)22g6Qc*f4REe@IV5*0xDF$? zCfN=c!wH`K4sfG+R)PIPV4C+)SaM8Y|AyGW&3L$8*eUSS1Xe)+B#j<05TH}27wA6o zVe=`oqyr4ZWRL{i07_C&5k}XVGz$s7l8aEV2Fka~5T(5AEH;F6Ebt*4PFEu!1yR3$9KtnOKBSN*2zUjAi{|>sY6jB z>WKy@AhPj>%W5u}+v*qiXXH0Vo|50-U$B-p^^~%cj9)nlqPgxDziu1tVh_mOQvcGw z|L1>PDm--V*a;JdQwle24aRQg-gykl_6vj^ZOxSLjM@aF4);^}1+8)){EP)!;x7Io zIhCHryZI?h|S_#8(4Y6^q4g(83GQ83`VaYA5G@C)E+vpC#pbc3gf$PRPgQqwox3PvMeFm&G3Zam~`(`qo~&;+CGs z+EojG(RNMw@Rr->u6$(U6mhWS^4T>e$xt(AUCZF!)ye!E5WHmj%qtdGOfU2PBT(8{ zG=0wG%A?V`0#D`qZ8US(Kg5UwDc_cyV9d1mnrnjb z^V|HH{{8;behmev9!AXGLwHFyURLR8^zfp`<;nI4dQT(v2uYL;FJ=84sPqhGhs%i6 zO9C!KTv0?SR}8>?SfbQ@Ld6k#3fQOOFu(O=MM2_cvX$~DL=K}H z{e_I7kGAJzf=--D@`WK);!eywn#{Yp@W9|&c zcxo*ySPKJA*Qt7)Uzd+!b(;bE1#N%OA!dm77TD-G4kr>@YhXhL)?k>0CRnKYGq_Pu zqT*YPybkzQPlR)jNq9os+N>5j3K%riYWx@zwme4KMI8KlYe3CwEowI zje2#yg~2?7+{NF|Lp`Rn99Dpr*mA`(CCmK`T2Xzz(tk?=N}I0!dH6rNa&#JF1;emJFSI<**bl+Am75T z$2?OwMy$&!W!}*K=VA0>&+B_TlyWfwxvF<^eE=TXkB=r|t(#6tY!Z5&fU)kOH`=-?R}0SgIap!fnl)k~FY21CGr zgdW7tpYRW(3}=sDwDy{OjsdOKgU;n7gRnz!vQmlFUT*} zE*+X*)_2RoN>nJ-FC<$C|F zXMfSN*FlhTtDbGwGhv0Eb?JxnJm7{J)+;Vl*v}Hx6XnD;{SrV*==rBmUdSa<| zGOjariyFsKfQV4|Q1GO(Qvbwf*pFD{mswbyAF*o2iwC{}q+KzgFfzGYH;j>4x!uV@ z?K}ys=zITeW`8lW*UcE7nQaH?bcLC9nTLQtHJkOUw@#cc&IN5bT{Tg(e{N?d?Cke; zc7!+!%k5qEA^Sac4QFS(saHQ_6FJj>-XU2G>agizD*QZ3d`8hjxT5EeA6I#N4(DEE zWgfWDU#>nom9LZMUTy3g$Xo>Tu>oT>2n3Cl+!CX`SCVvIxFqM;f}2B9DCzJv>vUuW z8d*6C;*CrPjHA)68_>fHB)b5cfc`ob_O5q-_O!z>XV zh9aeAry9MrS3I)IGwRy)K`r_aW}NS0sTM7Q$tgXnq@&JE<{MKXQ4%l3 zbYRr7%5P0ZY(j7K3Ux|2CC>M#Mu`gU9J`!mH9I+Jd`{fr3~NS6=`JyhUbg!(4rd(C zIE4ZwqcWHDZ_b6LqF$79Epw88Maki~Rsu8Mn83dn{C_cQ?AYd%9hMCp-AJV2y~0xA zaX}OGWM<4YEzSw$BtTwuDn}GOi=x4SeWAl}E`%K+HXLGYAyyY+{t(kqDoq<0usgW{ zP`QyXss0W&Ex8pRs$dNADgY-Tdy818JZgtNg`G;(*g#}d05Hqs*$>QIFmz(e?H}Jg ztNrf(e4zH?1^p#U9-edGA>HU7_#7cNbG7(Fb?#RsRSSP5fAsME@+Z$O(>u~#OpN9| z_JrKMeV&rh1nsl-d7y^_z?lst6KQkp27{T}yOqRBHka@=Q?Gd_W*pdOV>@iD&Bp3% z%x}Xv57L=T9T1)a9?>G09okHmIiR7K5yI;Dmf9!d4pT}k5y~uuGeHD4rIN_3#56VI z0ayxMP+;l#);s?CCGRpIQ;RzqRUqRo1yRFT~>U>NG zB+ej?L)(B+FcXmw9Db|-jBVvM4)TC(D#h~zw^MQp^}W!knfeSOXSzv;5)}gG&}JUCoz{9_4pACk<}v{q0MzD@*xnx`*bkz4O9%WzH&OZzqG?YyN#( z3vVxIC`)tZO)f5+F=>L{UE0O}_%RkbdR4kJWRw3X+3j|%DgT0P7iUZ?&75?_qgU*D zYgcpce#YcaLX9iCrY@VFpHo@q?znwT6O`p%T=g4}XK-_w@JN?DqA|LSJlG{aO4h<1 zP>4W;Xt)W@#TKXeE&Hjn=Mwp(Vho5ijoi16UNIY1th%E8tZ?@}v$0 z2%POX7+YLs3REH7LtQo}@j^N3B@jFnm#!GD8<-j`U$KAF z==*%2@5ier%OB02{n{HjiK0Np&SOt@bqO`Sn;klB{^YKB^M*NPVt=q<#pvr(>f|r1 zSrzP~MekITb%9w5i!e(KSN!M}JUW7zQ%2X0Il}M|8pSS&Z`W8w0wF0EQZb{jFR8_> z9VJ_6T_^T`Fmesv1ag!i4~w5G@8{-z{1~UfCNKlEp)u$1mHZ;qx6rmIK@i1_8XSa$ z%)fH5gAO*!vCzTmQEu!oy0k5OrTr+ym+s{5=N`j&8nNm}l35s$%jMnUWrJRz+hShc z&|)-t_;!a?GP*S8c0H{w1uP(SIBsb-(O6F^MakrR)8?vy3qzub_-GWZae1(WD7FsS zvxvtCq5J$jGlW|C)6sVMv;L}C^?64A?R$>%KX_bz=;qPg>?V1bUoq?GhhJaAPgBHm%lq%E^+> zK_?$`GCMNyrysW2%v9o*bXhD|7lG58I1{sIjc%I;#rbD~6%@l62a_pgzv|Q#o{dx> zq^5?}uxN2g@~M$jAQ#V%RiI|=HI~7avx)Ln_EY%@d5!!Yz8+`y;Bg(F;6tPD;_IW) z$N8$!7nH9?-iMVUMD7PbkyLTplXG$kDhv2%enmc?omZa6*BMz2yiuqh7t{FN{-|H@ zS9z*(LqdzkQ`Q(d3(+;@c31l=J6@_fR>fak#Wq#3W+ch0>_zR_9;w|Fk+qiqNU78(TE{XJ%P5HInZBt&R!}*1Zg#L>WyPe) zBVS>l*bB;-r350yzr$9L_{z(a`VpdvB4*&A%Yicm#U}Wln&Cmb(7;VfMhzljbBqHq zJvy`tHlYM{%>v@S&=8GMqqfT^xM}#5e*XJM#MB$>tENz!V!Mq;&Y+GGtP^5)k9;pg zkQyZQj|(2|y{qg`?AJDYs)y@*jFYfPCD=-pLL;INEl;?Qx%t)ZtKEDYJ-TyL1}gL= zKxPnJr0s62MdwL@G0}#b#E6s%`64GFMuj+(p-`wAHkDx!5E&KQ|TKN3zi33g%qKjnMh9?JY&Zw$6=d6ropNv(ts8W4T<4ntPKlb+HuFQZ-E5FYkc+i#MH1VR@o#A|l-78$?zHrH!D%r%os2pC@ z6&TqCA&OKE4>a2xO?^wtnS%0#ybojM#L=D0OO2XYaOq3H(tQHt2Kq)rmr2+DBKsrb zTM&~23z}O{#92-JoG~!SwIT&I{*S%Jma#JV75V#gNFjmuAcXd1IgSrX>F#r}h9tke z_>-0^O#1moHVc)gjMHz?^O{DfODDE#trB=w$XcU?QkLoL=ZU>&gM1%-&ewMf>y`76 z_5?63>y-21LM5(&^Fry3DRGTBD!_4v&*YTP>`xZ1MG~Y@6t!P-*g=dAW2z~zK^#gr zFvT#A({uX$`d88EnN9&4s#T8?ZVPB4j160ave9(*DMy@g-chkJI2gvy>u`n0$@?)- zFy7)AVr-IN$z!(aIkV~Hf-|t6;IL7@lxr!>b(CSW0tYAVRcb$PrYYa?S zgafQOU)%snU-Q>8pEIV?{v}3*0ARp64o8d9OUI$yKC#O0rOBLG%h&9|CTJ zh$lftzrw5rY)+dEgjO>dB`b$S4H90|FzQVBijFPVE$7BHw%#LuI&wWLWmmG&<7A(R z{d8F&D;qF|1^7%aB4&kJW20dfBHtzcEq)kO`@Dy}$GxY#V_uE7+h-CxY<6b18+Bf) zSU?nu^qLYPLIQwv0ZI9I^a`76Jfy{bk*t`$bqXt$kA|nu8mPSBs=2T;<$2ACyiE2U zw%U`T)SdMkADmwPeUzQKx7%HU0yB4UJI$CQ?W=!WN8B&lc%fkDk>d z1gEDFA_k|?GYY?%8#%hTySP0RhoyZB2N7I%opuF;XtNk3tBKRKt5+7b>iDqfJcF4^ zbZV-2qwwPF=+C|2G!N;$d*si)Dm*)hb1u9(6E&8VkC|Aoi`$YV8er&ojp!Buj%Li& zI6$E)v$avvlQx{TC+%pOV0L!k59W4@)zv{lp!zB2oO8&kE2k|S5iq%^;gX88t_gqJ zv!DKj{1MqC-z9u8d-g*I$rph*bpG^b7hK&}23<4CPp&2R1MmyQztWt>2u+aCG;R(u z=8{`NEu&lDJq~7W>?D4BgCC_e83P%^N_a=KWt3#_oCC)}y1j$r0!FK&!*9T7RR}=p z92h^DQ%>_a<2^fEm^Wee+BKiNrwq9jYZ;wAd(CbNPYx9`GVb3^haJkTP<)dU1?wAC#!G@}B zgU#k_HZ*1QMD|BmEYcAfjtI`Z!V!V*fLb?nyktIR=J%P|b!N87%$iZ{2uikg6#c4H z>1TqOh(3|D((!k)uu#SJzXZbI9w2(;jS$^TYqWRZ95R^UiudHj@;dSc@&ucy(cG15Xn)cEM?2p_x-FOu zM7_mob_Z2RJw=^J%Z=ldRK`ze~sqlnG(Sd58cWEi2Lo4UsyXgYU z3uJ1(Y`tL9zg@KS;VWB4FX|fX@1ifYhidJ*M>dejA-2ccoW!HuSi{GAH_ z1xW>LSb<_n2rl88fy;zw zt`=#2zqhL*?CVSmrsdjZ6zoeoOe$+%!Qq0V1*Zze3N%~+)r<>i1!)D|bPmlgW-`ybWn_V$FTI)KgVDCGcg?*zr z#zV`O{}-*pMm{E*)|3Y&EK-n=FDomzR;QvSsb|-P-$3!DEJ++PS3aVpE5qK7mt4nO{5}`E&c!yl zSTjPKu7JJWU<-VE>#Lhy2^aLmDfp~z{Z#$JnF@`wI6u^@@|Ruy^v;%Zsx$hAEbL+pD@ zJnACMGqj#)2YFmLSQXWCQsEWEa*m5Aw&%N$%yAg`cX^X%&R!y}rI28yU^)72?^4`> zbM3PI8~4zW);9QUUvvCSW`lGfPgc(~Werf*&J81TboML`FfP#Oc*nq=BQ zSf~S-C;>Szce5?T>?q0W3L5<#j$<5q5j&c5S*?K%^VyRb=Y>-I0?nhO!IV@6kTBmm z0>|yN@sqkzOr$0wx5&?sqGk2thxOSbQT6G_zf%wE$)r_qN|RQ}=2j$|KvfLuF(=hv zFx}%cHkxb}rNf}P)8@3HpI~U8?Xc~rO`vql(ay7gEn*;G}(cdAVcGSqETRO z;`%^=65aH7>yiKeMuX##mV=6(_&xRmA^1?Lq~NQK&=mDXhgNN+P^cii75|RnGAdU& zU-<_mE|aaqW#j|-p|fn|SU1?f;#TYiBX>p8sBifvoW1u9Of(!C``bgF7X0`uS?_Ln z3gJ04loSjOM+@2{07fFsGAsmm#DI2MTGe@{CR@AVz)M0SNA^0i>V$S>3ji_|Q(S1A zMRW?o+Eq%83zhFUgU@ks?0a#&;oZo0P)#P;w_o2a53`#vamsj#h0-VR*vpfdV!uWM z_9%GlEA+cjVA;!tblL%4NQnDDU`gru7!ney=MIDW9JhddCcnrpW~R|+GzVGbC`s^M zoXa<9cHy08CT&8?fV5fK0}%94>69cPxTX?DND?w0CHhX~1NZBX=uhZR>-8MG6P>o5 zM~^wRy&!<$>c>(z`doK}y#|3k&Kz=5>}RE;ec8T- z$MaFFYU&L#A)z>II{q<Y8}GZf%2K^r=0tm zbGiDtsbjm>ew80jfkxO(Aee!*@frrfSK%o z@F4#K_$c;+Akjtt>VHT54~r4QpA&VoGlhBVz=t0~O7KkWzkH_lfBQ^+Y(y><+Q(kU zr)#;Kq(|h4gZ(jye+-czmdQ?__bf<%O9x8t^F$vKC;P5*@Ukq3pD^d*;GcRd>M zFwQGH%?JT%;u?}=R!hhdvk3W8jnpDNCW(^v_IpeRO#E8YcGGPpA#R##;-e;}GN3Wj zT?7IJnXiia`cy$JI*GCq#5mfh#gbcG?muSDNb~4~r#+QdY}`;?fA!Xl)Z_2$r%p|l zratxOrYB7NdectRohD(Tsm;V2OaW7YNieb7bEHbCQ94KilI}8%e<*#RVxclrr4fs4 z6}!c1$&JPR$1L=rnuDII^_#A!o_O`u_)vUmLjHoi#C?Xjb|)wAwd}W?u$;DtF-yY2 z|J?Y5kza4zX}r@YOf%pLPq*PF0bXg8i)#p-pQv<&Mpe|d4P1^B*-jaOeivHFTl>#ICu!{9T8HOh7N zbC)N3t!be&KHpK}XmLD-8ffS3_xKL@__%MXk6-KC?z_z=Xnby8)F=4N`I;I{i{>$) zt)$!UF&;4TYmM8Dw;6@FajKE0q-PY%v=__kGv1~2V~l^QP`uK$!5CHPNDVe68{z2q z9d^=^cScI&kL1ufLL+}9oLRVy73T`je=(n*`=0Re6Mbzye!Xv}?@pgUeE0=4hud=; zm5xToK}>ZoDlh)qt9_7W>(JcgGeX#u`HWxYb1pdc)%f++jNf5*pCf?G$NqAj9BB5Q z70B~slPB2}eyqr*pZi&I>)y2epdLDrb~;TnfC$XyG$AvsB#l>Qn3|k2(eIjJhjZAu z*}2Op+Wx0gJtDD=6sfQ>>2dj1ujCmKSG@XhX+Kxo&rbh*x&OxW&s@z-72flA1Y(iG zy|BfMU`@$29$|*3q$47yEz#}^ASmpD{m>Wtg!61904mR=gmaSX1900_lWnjSL-q!wp(N?;_Zh8 zNd}KPjU+W3YLN74*{HYdQ_{RqcWO+zRjGlwqh5X(-FqLYl22C42UuGyM&GNMw~Brn zeSGae(Pq;;^JLHbJJKO_q z%@)|;gWL*kHz$Pf{1VL(&8wOdkY<=92dvI!jg^bNj0U;5lrJl~Q>~jHM^+T`3nt81 zQeU^Ey{M>tNnQPt858(Vx-V~wMA|Ozo^|<*Y*hPW$+$IRA4m&W4aPxukfq7$;B77! zmv>6o_)8=;x>K2ylg~lrsOb!;StokJqG?B%_f;NqTxo0&I-fLQQEU zlh6KUGJezi&FAcjP0n*T@+QZMk_Ap@L9*z-c?^?`ON@P{e+JlkNDY^T3b4uWKL@$5 zlg3%ZNl{DR`r&^+jGw*ahwE{tlYX0^M;6?vphu_tCi!0p8Ny5iVqhbEk0E| zR;(#rkXXQ)56pOE%7LDSgEJp(JvdKWXgXLQd^AUUFz)gLf9^w=pOPyhB-rncz?3*S zg7R0;Vx*dTRQFY*@5%^xya~u-8=+G9!ZSDUWHAxx6UqNbw#CRvH7LypXPO4 znflY!vy1-o^7CIsf10JfiWqY>2S@nLn>KFwYQv^wKVO?jto`{is_2>o(y;ITHT&cE z?|(s0|Hb&zVNq@q?qzo=wSdUsy%43*|*q1Z8etrR(9)rI*=@CAb2-1O z@uxidloL)V=MGL%EIC@F#7D8dPUaPyXoAKnj=lZ%G5ICFo;|-#zDK@i9sBjS-j&{w z|3vuMgCd^PyGrN1>q+c0N{};_>xAjVFOXlNw`CQ4M6O%M=COI}B6JIXSMxlybZs)q{lyIp%wpaSFK;pY z#b(SjmKX<(D~uYWMf||=XVafJ!f+MSh8mS`@1sZW`0a8zq zM%yb&keu3ksPO>1au1}*Cz(_JR6cs^twQ7I$LzFhV}~A+zhcru0vZDDmla9k#3|4_ z6S(`5mlzS=EJTzOO@K3)H=R)#GjBCImghz?&Gt(&H)QgeNH_VS;bdSCyobU?zO6n! z6NDbT2*_cYx7ZQ>D$AN>iGG!1%o)gHR$x(MIRikWB6y#b!};H`@`K80D$}3Q{MmK#4F*=m$df;pApTBp+mX|C}6CT1XF?^@yrIM@X{H#|mQ|F_sl$`j|du zFG}$}I-1kcDmV|2seK$W1kvKo!h(Xl!a_#~h+C@_IBthvCrm%3oKGU`Lmea34v9cR zkt?5C09u}t6jWBy?1;%xf*_*kL*nsO5PU=fk?I*sltNW;>X}H)2<+`iTeq#-+{s^3 zyY210arrpA^oEzWCD~sKo3iuQHcT7tD7@*u*>{eNI5P7E>Ebn)Ui{+V{_UNkUuX^{ z*4#g`(rG*D$q08`HJ?pdw)o>uUz1-B#=?kIF>VTwF1?zk!9H?*vd81i@$&iQtRT+( zaim>Qo2s|^t-MtXmwBrsyT{H;f=A%(f@OI)FEfZ(`j#+qWTCGzEtyi@SNTGIEPqcv zpP8STpBCp<$FyG8>NG#1nE*qa5d;XkA|((JG?7$fAG?#JUja8N3WK1^kO-Gna=8KL z!`)OlI4uvC3)vt}!%7ko1?fw?lKfXowtLx97)^|4wenkm>sNN{m{@aT|7rPeg*$syeX$SQiYrd+dzrMTYn!eJ~zH55$v!nz+hZZgz8oKBrRy|?%wmA!~?aA}| zf9UXD(%U=ab=~9glUJHQ_L*={^8%=mD!BQ{iTVlt3HcLtP7o)wgu{YZm8jZN#g}<< zyK}ea3c1Z5Me;`qOQxQUv$TYMP;be znpT=7JUzL!Eg>H*KsZ*UNSqc{0?su*EXEq{SC4UpV<*T&%%yt6JlqLq;#&rND?Z@O zex&?>FHmP@KESA%tA7j3|NU+O5_lwO(p#I|?z&iAqK*d%?MEo>vp1V~J@9i%52!kR zIzN|xf`5tEpgUC6hxw0|emJZ|v4v2m(c6sEVKQ&>?DlDl=X*H;TguUFpGoVJ_nUe6cqbrpSE*F zQ@mF`Bo|t=KoiQJvsU)HjqWnTb$qwGsB2wo!)iq$Tc@p_RVq)1L{?QnB1P}?>B-#_ zM^PR5_33Gi6K_cJo4#s&@=1Pk&o%v}rTvh^?IelY$0d;@&c=VBR6J{u7yI2~Tqg2d zUI)rS-7W4pSV|l2S2`P=-3oo=>EvQO1{;vCc}zh6Bj)lt4Yud(M?rRRN)m>odnCR@ zN=luQK=f=!(SHRXatTIF(C_yB`iPh9Lu09|%~`v$_GAfJM2((BzV%Vz6!3&0yNq+>z^Kqos)9j6nyT9Wdrh`=`8_iMiVc|P%PTDTDGr~kS4fz$WVJ?TOI1AgMI zw~ju`+ih7vza;nbugN@`T__SUje^E(Y@8b&Rd{P*15#DMJ78pLhQ|{FN;4}G zw3o&l4nT=Dj#w-a@TeNmd;<8`ec)`f8J;@ofi(6Os&&X=dzHs@j-#Y7N z^i{-rS|<7;{XhEc@{9I!1)k@O(;Vh*?A&m5P_dwI2*HYvP5`Y_j-tPll0--mA}irK5hY+o_6p?v~7;bi-q zY=e_s?POg}HXZ7lI|0r~G`So^8Jiuggz!Z-^(PUYC-4oQScgx14Z1IfTZ6TvPyB-H zYd$Ib6Q4-=3W0B>PdwVn_O)VHe7~GsUCvgQv%zvUtsD{dGw*xOyY?#Yih1z$(tq`? zb;`Tev3+%{j(tDMu8y+RQ8pN5(@=}>o$opo?|LV#4xd2Ana29#)L5UwSSKd4G0YIX z>tR$S;m4j3+l+hcYLpXG`5_AdDW$wKEdz#&zC)>%fE3li5?KHnHVXL~c#Mlcd(}eY z=@s3VVJdVt9f7?9?vvq~%{6;!j@D=@noQl*?&5Z*GY85MsqH+NuQS424zj2UyIfx! zWM;8(K0SD?R4Ak1m|Yf8IRF$<^QxTGT4;NvunXwzD&;Z;C~WS;>{GpeI1MsTS0>vf zJ_nT$jr>|3ps{>b!&=ySun5C9^kbu^kZ?6sCPx_0J%mdYihv0M|h7{pf(8X0T-Ug_xk#%d>4)f zBFeDIg>VhKnf0?>Uth^DK?g=7khNx$@D8tgNMrcw^Zla1SYBJE*O%2+m`1+BHM&=> z(oiLo7XG21&6O4ckD5f@>$G0v=b~Q=wM0U(8cHxuBG0DKX_03}Zco@Q8b;ripAqkt ztE5d|Zq;u7;!3<@KHibXI~viQWwNC6z^fYK*({!w@+=RF!W$%sGjtjT4J!;HP(E9L zDAjsU27v}GdJkZEoQ~%?EjFWmfC!ls3!y$1XFiZe!x~Ki6=F)lnNUlV!cn`kFgRrS zd}8!9@y1aT`)u?}p;@kaK$yaRdhf{S@Tf^9D|$9RB-(@o*4Ork0O$UfFx$>a1=vZL3|jO4L?sD zFxi{2m1DqR#}ET!REHg}@yBXvQt)dH8jVzhoeXtekIJ9#XALj2za6vi@4hkmf@T>- z>n>v(G*w~*_yuTb?k7pBQJ1DG)Co9xeAzw$w8MW;B2W&pI4txHHtQdfaoou*tSW3O z6!L1TYny9@oU+QY#xfy4QWI&32xUH9M6}gDz$IIf)9miduT6cB;bcscumX zY&dn(62ltH(x!;B0NvG86?d&}n*IGm-7OuBYrA8`U29ur-ZH6f*W9MnUBx5YiY~~@ z=`71A4%=;^627zNf}B~g^x{m=bjJ9Xr*7!0>h7J7wR!WBi{P-sK+IEZL$vBvB6M!kYTB^pT+%^RI;k(2c} zS*EkZnS?#z3}p^yGH##WwoeZsftXM`V)B;z;xDA!V^r)Bf{5zrRj3>gM?`Gub;HYf zFg~$z==$#J`2~@g`E~Is+`qIta-qi6Jo#&JXxF?6ZkKHJwKRxd;6Y)YZ1vK~Hkm~emX96#s}kkX1pYxj0;rkQmo{uW^=nlo5qiA zGnAYt*@-yZY_oGBGYOK`AfoihcHOCmskd&;Q~?igHq`cjaN$YMc|sUFqo)yCan_@g(UI|+6qI1f%h14fKG^s2`auq?Ch7=a*C*`!3@I5Lv4`W zNEs~nJ(;zrPj)j#`+THXI5fJ6-+JsA)3JlQ*{M@9DrHk+vz;AVoo2e`63qsUsMq+R z1W?AJ<@7p@#!xG@O1xjnN0G?cv55`9H32olk{*XKr)pEw(J9ekJoLh1RRW7}NaIdHaEhIB{Ytr>J+tzO z&p-d1KRz1fkMn;S4YD7|i{!7dUo0&W^{~ zkvQv&E1^Zjj7YumZ|A(SLwRK|>0Y2v#XeDy!H3^r~xqa#2D~OuW0SD^=895t7Rr`mS1BUN(Bwyy~_Bqq(RR zIdKtn_9}2S7H~5;v`9u|ABV%(s=QB%}=lApuh$bXOjiPWfqmGeZy_sS{5At$H96+0=@ z3Am3xgT&g*af_))hyu+E2WfO6$sQKRExbp^EeE6M+)Vpb#6H**djeLk2IunphZ(Pw z976fk`{@M4(L!a?K)*2W*eM}{UH*<%8#Dy{!FX^icp~_5@C;aO|LA_3`y*JUsbPa= zMla)BiDjMfY#xP1f4-c4AyMQ>N=nL*D0!q{{#9oaCCH)37@FAFwgrihb2A&*3R<>< z{fvJUTGqxaO4p@q%{JEHpyjq>nTipGilO!^%f6#glyQx4bUC}j#?v7{l-^azZ8pxJ zc#AupDI`IVhUWXq#IsPUB*hetlCTYjL5e_^1QG8;D-VT&{cP(;!Va?IgRR0%V1u*R z?W%3;$(wJ!jh#L9(xJl9gf3QGsDF%FTLa*HegSr4h`CCvQ~e!u;toAB=jd6 z`r8?dhPOTM@}l5Xfz<{FyBHdx@J&R7B#^3P&&>=?PiG3mxiw7}&x@Ci?3g=wbl;l1J8j9? z{i#@dukhck4HZo$Z=TIxS>V9>*FsKT$NI~e>U3284uTcr9bQRGtmDctvE z4eUY4sr)$4{*ikNTd1r7W5_I?m~VqAVk5Va0im0{U3d(C^5{c1P2sTO#2J4RyEhN0 z^hV~9v?fZuRR{foNU#{hgSfqurqlmW`q?!5v#MvR*oR7JsL_Q0AFturg>hMnyHY~@Q>?!zta-4;(YFO|G3q*zz#uzkuN^40=au_H4GCXjFZ^Q)q>%JNN?g7U_~>ZPsuxy|F% zg^lI;CTlD;D_S*B?Vb8sadmZZVXakWt0m9Gy#-}9wap#0dE=1u820sRh?+z&@3Yf| zro>66!cgHygOss~6BQpmtTO$gpROpT3lo;qTK*b9? zDeGyZFiILB%LIorpn|BxpCOiXm$2+>g%>@1y{E&ONY1-xwue*dqNVk@b>mHulEKYg zJy(n-g?mzsRkgmj-=y~y%aY>{UO%W*JZg{3UXU_J+@@&TipDu>`%B7~-Lk!PcI9k~ zFW2I(D0DM+Wl2K&u(4%UZrRoQ_DybDzIN^A@y(M1ZEb5Ow@vQYz;n6Jwc48OD8AUW5l?T zn7%kNi4VE3X3ZD3ZrinM8~to+XlQG0Y$SKwvu15^aaD57;#ambmP86lYdaFr+;XBf z2CUJ<))iy*vR{(Y$;Tg`6n_2qKUflfV$GT-gjeai$c4$tFOCqjARvY>YS*kGhw=U$ z^sP<!$7cVD&nKLiZq?BozYUVB=OGAN> z_Yb$lqJhHG%Q!w#26C8-7f(RL4G51b?uJ#!K@#JLfaaqYYa~!uS_po%!optEE<{+5 zMgxLsHXJTR6Qkn1JkDt}a*Q*cgqI{PB37A*Pw6v!QVWefOq8lPo~}p*Cb>i+=y6aF zpDu$!PHlv&=7I6T3EVxW2Tl)ie+_nB(4AO#<=oiFP=Bbu>GGhpi8UN^0VXrrD`YeYL`ev)bEdrQ6%#9iO>P zu(H3S*k87idLE=p_zOG_ciKb&PHD(XU&9t7#tV z1Abgy0Ay(|Diu>qb!+!NN>(y=d@fP8%t^GNyey`h)x)5mBxa1QjlC0-85x4a9aF*g zw2_K#C*qc3-G_(~kaFozRVP7HB2JsAt!N-z>~hN6?N+2mv!TpsYa%;?68n5bs*cUg zv_hldO-Itk-Ki?5ZZ9aS4fR}3ZY9K3GkW#?>$cr764bg~_JpCW_U45n%MIrIhT_Y& z6LQ~w-P{ykdeep59@*Yy-p`$wzjIN%s=9cnDfXTs$LUmz-gnz}v^p5w*pONoEA&`Z z4~EJY4>w%h8mKDFdGCK@CW~3l4qyAD;kL~~iJ{wH-~KMO&F~>R%Kr+k)%LXSl@LJz z5>1e>0k9OXh7hp_2p=GU21Jml9g_0<8Q-lsvQI|}bPIH>8!gOe@u7R9ly;Rtq5Lui zM3ltsV>oZX&w0(Jaka>Z1@DxGmT>;TMWRO@4n@FBMDK(?!vO%ufs{r@fJMwQz&?TV z1lE!PN1`n00+C^NBGwYpL~RC-$7i<9?r8T4FA9yMj~i&ba??ez+?qU#PX8{aQraT! zz?Sd)bY$u^HqIfr$1+Kn;f$Vur_{rFJatT6XWk5QF8mT6l6%mwAUf&Qf?sU$}t8=h1fj}qvU=V@O+`M}U`1zC4mm5FR< zUJ%=nZbrD3(5kT2pc#4hml_y^J;E19G$X4M6{wigAHU z$x~!NtS|7P8sQ>eRAZWf<3EV2KM`^Ks6s##;ZpJjM2%J>!~o&18&>>UM>!<4q2B(g20ywd9nI`Esm`}35G0TD9a8}2) zzL~!vTnxSNKG@K5nKC$>3J^E`1HVy|Mh){Ej$?n_Nse`rzD{E7BupogfLvPN*{N1X z@8~9D-K4i$gv*G=8uBGHaRiwfo;t$zz+bk&M%eQ(V}>262VVzZ2WD#Ro2j+`e%gr# zR;Aw3X1&UQ3&+6l_X=|Y=CF&BsOsLvl^P-BX zg|j1(*$b;ui<2~6U{)|#KU`HgT#xTVRmI6NCD$o7LUDz4K8*%1HysI zEj{4@g5a^|(GwC-{Y`h9~K^@nfJ{IqC7n1{P425EH&l~t)o6Q+gc)IPNRe$RGM*xRDZ;=z_!n;^y$|M`cH7vAbKlD( zn5J}|*@Jr7g*IFMLMlHj1s6lF`4*~|m3hqO;xU^+7M7U$8eXO~w6uPTCaOgWB|I-p ze6t=_Ycq$5eL$I_#9?9r z&)ou|rz8y%}qb-mUoO+*gLQK+Ps{)Yv=ypuDcJ@B5}gpixqnvD;8pE z(;@jnS#X4)7;#*CzxJ3`rj0m9>=R+6?i{iZ=c9a)Ff?9+^9pXH;@M19{E}qO-aY&)Jr`J8Z`3BE zfsjspgjdRClk^^hej$2hE6xhtPt=S7!OF);{Biu{jE5`obU-DZe#2E<7Y@}GyWPcg zp>SQXOZZc)CS)*#YGQ@eVS^z|k-#{O(OCz5Ay5ZRb=;gYKa=X}v|^`+BS%d+NONWw zyrk>-Jz^gT5laCNc7=3(j(Gh|N4=4=%;dOUCbx)B6P zg@rl1oPu)X@|>LXND8$H^`yQ&(7MRDygRihu&is=ESn}>U*A|W=FV}uZ5BQjD;xeqgFQZf;qViXwkULAqDrGw}?QY-) z!CF^HxR;E@1)d_4B;+*Jd5^CuQDnZz*EMf2fA?=dR`kt3d~5QD9qo60?OT7iv9)90 zZ+7Po4s`l1GRMlQeDxEpxrOt#4itBVNJZnsz}9&Mxvdw-eq(gFwXZw!y{4rP3!fjp zTR8C_8{0ZN+cy3O3Eq8}C?8&G^5#2U*Sa0X+Dq@-u<6*&mOLNXD_qjtvh&!c4fkDI zi(QS(w45^HM3`ICOKysg+d|~lFxecwHq5RJliF}+cwv|eqtjNz7GWcD#?TtHg<#SBEE;Z6$?a;tmr-nCQa5(HVjfWMV=g{4&%5g+C$A4}g?N zP=W1&NDe|>QVJP-eFz^wAtV1#nxL6XiZ}*P6`^8@lAIH%$p9TqNxfasgLFS~i|L0< zwCX`;v8yMxowwcVPT28NS5|LHxN2%^-NZyLI$!%&vQ@Ye=OaF3N1>5v51YEQA8+m* zQADl8F=8_4!eeoYxnd0CRoz@iX117emq0K?kvWXMZ4R|Krd;a53D8xhpiS8n$#`HytB zSt_fIpfb1vLwXDGyMIi`(?VG!4*m&%HbKr)ef2dLDnEU=V99W|pOE zka#h~0e^?N?KaK}Kl z57oCnxO0K#5y~z6gmv`~|GZynN7dJP*&?*8%4IhW+_17P+mq@nv+&h#-acRKOI197 zEAnBK%Z5JzE}H^oEM1<93}ywq+*UQ`<-GFTT$?qf;#+`?w&nB~j6PY9yA9APl^oP_ zHh?X|5+MhiK53wIkSFmB`-G0K49(JEA0z%*hW){ZA~T0ZRStE6Mf|mxq@b8|*}*r? zFwWzYS>d>D-sN|WmMtFa@C}w;(lES8K~@Sk%Yv1iC3C;g*mR5aub)XgHrs!+vRLo% z7+!VeuK(H}nwQkOOF|z-1Jt6&2fq{fBMrEckELsL3^AE4j0He?OFKjA7*fCx4dS0H zT2WG zUHp^y0B0T*8R<3gB{Qjp3Bpmy2y;*{$aEvpLP1lq;a6*gkLzC%US(xu3oAeU%!eM8 z+vVWpcDGYS8$^jsq8|OCiJKU4_b(g?1xH5vY2O)q$SBtj=7zMU_cA)Y0Zp|n8jIOv zH0XJarCLMWXeX^9|Im=XYRDs+|J1NYG-Q?LTFq@5u3fW0Lzz)CeQz|FKzojsms{jH z*po7gJXcP5IeAb1nVkKtoIEWjJLNaY!Jj!OUnb|u=?`u4D6*W+->KeHvCpW;Ar(2G zB0C{qbhhVWwxg;PI3`sNO!oUq@|^Mw;3$j+bK9_zbkH_I`N}FKr?gnub{AHHQ>Ybk zCt>(LtbtLR*7m_F<+WPYqBLj}EYvw|jzedkE(ClBX(>+9g`nJQG*BaXzv2sY3D&K{ zA~>cOW_oF)pJje1EgIGhTlwq?0gs$nA}$&iJ}WT6CXb3wh#11~lUJ`2)d_Rij1CQ83{5dF5^`8i1v=B%&pD z7=}czV-L~@7h@bTv7FnjTzo)v7*np2Q69dDFaTnjaT@wf;h0}YIv``&TAXYN2E^X@o|q$|vn|>!@zJfjo_umz(lN=?^O)HH($r7C zD&i?H@l;`=o$2&$KzAGb%gi>fARm#nPmwL;Q{kCoMZzb=$AqU}Lk~l!Np|<^7T)P~ z$~nE+0@gro6FcXNrtB8U^isRG&fI^&MA%+8r>U+4Z7W&kAZ!jwDQiJUqI;Y#?<#f)U>c|B;GN>cXI%3yV=vW@4gvCCwnQZ@vzj?<}X&sA5b*>~0CK{Yu<(IdQhz+VXoZ~_veRA~ErR-eJx zgM$zVyklvL#?S^$Pk0Mh$mBM&9wesO6%8xs&lP|Ut3;TG3rwv4n3L|r95 zq?byk-Pxt3TI}rFN}5f4DZ8#%PC)j*yq+0IC^P9p9^mu@e7{^j|gua#s2wR zHe2CxIpjRJxRldOs;>wMLO(@DRUvI_>TGxBw0AXI=_(>}!v8liv_aU8tJC%7+=wEi zagMm;uCSVF`iO!{xrj#XR>#zw!iDZC3V>LHOpbd@BM*fbCHfFW#+01POsQLFtP=*d zlx?DRNiv>ED^Y}}ICGG58jeU>5dR@GKjh=kg*U@k3&qV5OR!*%JKeXmUU&e`+ud~+ z%uT!Z3eT=G1oILB;iXVne$cR*-20j^OrBbB^^yiNd2P=gA!cq^a`ghCmh7nPuZgIp z_Oa_!k?Q^`VH>vvHPS4sD@JxVl}-Er&qC)Kl>ud`lH=`4r5)|>^g1v4 zfcB_l--jUi7&$;?fj&7}KTDSL^b8?MCruHJkJHo}og*qR(g&Tb(K1O1(^u%60n8%K z8BE!8=d3blT^(INPY}4zgfIFhb5{#OzsBwgScT6WVYfpwm$V-cUMC}4ZwQbzt5ym7 z12=3D4wJmxiinLD8pyABYosz?c!Rz7B$W#2SEW>KTEM)X-uqy|?+V^4;J#l#t}Y-K z6p-eE`2}pafLIGifi}h^mqaz`6JGdVpdDyK5Qj*RuZ!kua&4k zCTE!+CS_p~2@@7rW{z@l!5UKW?Q*?Ft5tYivK};RUKSy($T}LppmbX<*_%tY<&v-A zjuwK^Dz`hA<@0e{3WLX*brc(p(M*TPlnNVz`h>^>QTH4$PT0eA(Zp5D5ZGk)0$nzd zK{)fv>!#OFdKG^~v`N;93z=O<_>(qNq}S&SzibqWi;v4DgCH7OPKAe#?`bg zAn7`eaHeP>z-EAyi*&Q2pv8|<-5O82;6mUb>}5u+leHn!?iq5L9?e{f>5dibiLSZvu3x6>AaH;r!0v=E&5QRg*z zy+cbXbE>LSwuh2SD_nK$!}3qG{LQ>#u*sAjnM{AFub?I;>dYs)u1~b^(X^#8tZf1p(T~!t_B=#gz*b;?p=NY>B(EuL#0bvDlY80uxmlZ z;e4_)|E7F4FQ3SvrLHj$m7xHowoWIa99(;GamCOIn+<}WZeLJ(VehhK`HOpMy9RnX z=gg_KN9X$NcHefbMkDWY8uG#5N!5`l>3XRQYcXTlq*a5|!_J#tG|{4_e$0%elcI|> zA_c8K4xaZc+5ohxE5%|E-0%A&q?Ej?Qol+Kw&TPYy!xCXkgiLx^g zRAS-zKEWzi%FTF=z%}p>nI3)A-h|bXO8cTtG&G7uTu6cx#$ydJ)-@K1@cuD_%$iAs zP}aJWz+>WUpr63q<%^JdDAi`0kT0bbm&F9(^9&{&w{^!j|fyW3#2W_WPFG7@@>otx-D9R{j0 zkTC{8OcBh@JvYHY6CDCOv{)-_(JvkxT&yQMwPWX|Ho$o+L@&Vyd;7YzYta<~hcT?f z0TClmmj=ug4rhUaeS>&hyp{%tyELtC^O9;WQF;m3TRusr;TsQm zh~1OxY4LCe+=t!lVHa8MBG+iiHEPnz4zXw?0Ne>tyWM85hes6{{AG{LV(&JCxrO$$ zz_>v1P7PXVVAP1Eiy(c_vk2xov?XAbGsY*zs4(t^pPD_$=jNCf*(46B`fqe6h^s&&`0REJRKZ;;6A;0t z?0Z3pv2WMWs<_fSGv`fzM|Pu#sM(SEoqO;S{T-jg*mvM)s)#Y4{T;f)1gqMNJUQhP zYGLk4uYI_j++9v?EhpEOlLh4~%QuyCo#mvuoVdyh%UM-9d9Z-MD7?9V>?|M~3&^sJ zX;@J}qM~&uFCZ-y#l`uly1Ih=eBVNbNm;R7Tgy|$EiL)=>F&B}cX_@cj6Lhj?pajE zVXo;cOJ*J2!#MTeK8rIybJnx7Pq)HXH};panls|h=*UUcfK=Us?O(|cHy`-u$dL~Z zG~@eSM?N^ve0s63b;Hnt4Xs{p%ZA~hOWS-h9qIn5!N4N=rPeBbOnQZuS+9LJ)#1x4iPAUPT&R|gLS4+psmgBybEV34#1Np6tvKBCT{ z1|6>_v!c-elK8>)z=FWa0Ot;nKtSHA)fO|Y_Q8gt;#5_4dBQy_*H#oTsJh)ouG=Ib zpy(oGwlXv)T>|RCW*6Z+Yw)j7?w|vs8-s5AuS`7o&UBvj>6r;xs;@Nv>wG6N>DM3Z z{rxw)vng8WF>>d>nq!(>zmorxJb{y>hFO`ORb{oR%UrHPez7`&dWJa8l{)`I!?N0{ znp8)MHKhD0HdQv}u)1W;d8C4-N{vXBMheH!s2dUOmykAi4#L=weCbnsm$L7lAt53f zt)i_frQo3kso>=S$4U=s;O?j%1VcELRS9_~0ekZ#`2;7#pXTg-^?E~VYOVW*|G0L} z9Q4F6HIxvocwBZqxEa$SK@$%_cS-yKaFwRa0AG z9^QLw)8@yoA2!Cr;ka@5x+gZzT0K~A%!?K0`S0IWzhYjU(UI#mRK-JgNtTD=1Lbw7 zidqWP@BQgz{`K+o4ePlTE55e<0&>Cn^@Bs5LwSMRzFampw>Fz$w%69`hlYI3i}cGk zCl>jZZTi}!D_4Xsy>w{a=+dsPh9S~BbjQ%gLuZC$LqlOcFOMl2M`l44mZfVe#_Sd+ z&6Ge9((V)JEGT(Q@zHfqg)c#(;>M>@Ono-JDe6YJQuqn|Vtg(cKR)^#HZ9O~Vxm(N zwduZ-Uruy_jAUk>6QW5|55Srs&B@u|Dxh3jt_WutO_Ib8Q3g{G{W$=nkm5`-bhz$Y zebcGXyE;1Vn#`s`=iXK~Je>$F=)0r~DU43PzZ1O$x;FIET<8L0$0Z9}>rt7$5H`dYF*)Y^Q#8Pp%PZS7#Xh>bI z*T*eADV?rLZHxxIJs=1BePBEUT-oZa7B+m~a$R6@Zut78Zp)Wyi~?4iFdny$lZt z78#)v8WEuX=|3@UKts|J3LM_g|6LIv`wGCrG~$7?0SOb%e5U?yTYeh*5b7_>fFIob zm1VaksuK9@`#)`JfFNRivP-x!oXDae*vSR=EXT(^3$RWi9)drF2v!*>PCwoeBGn-h z%iRBk6&C-s0g=tH5P4Sl2ydP{^b5%Ot-{J#kKZG`+PLJmcaMpz&!E{>3i z2$>fl<&mZc8;THF#0n@yk|J<`zbHY%x-b?iE-J{&&o3(F5|ptGr$NHzmM7`~pFmC{ zp-&)>>?vnSZX!`uSW=WXBjdRxj z-^OgP;eIS~S!Lq3L?v37{d)io{?PC}%kXi}F!k=>o5)@T`XGQxG9LoYewogXBwfh1 zP_``Sb&Uo5{(wbi9Mh@*2EtyUJXG*RsXBZa3==S5OB1q;-yfkymzZRyK@<^MN5z~S z`~1$Hk$VYqI0G42uzR#LwqVcr?3)^e7pxaONvwArCbnlMMVvtMj)&K8cyQ}%n_-G2 zzsDV-9~qM-QULYDHBH&>(3DARsUgbc> z9!=_^T%ILb$%~&34$s*x;%OEBaCFB};oTPEe_HrsEAc+K?Lp%25Z)#CAKr3Ec&3BY z9@=t3)fXq~E2`V@m;YP#x=afMQ4SMCr?IOH zG=J#GaX1Y8b}bWky;z1p(wG2k7eM1k;z?->i$x45)JYMxXXnPXHN_XqO+BcIm3UJ1 ztqU*dF!HzO7Dx3Jt49;H<;EOuj`3FvAuq~)#mVHuND@^6KPq3ZArl(XteFpjhn+_7 zMV6X46QeOv${EhM4=C#o=`P1izcl(OHt@3)F(X=H6sJVRng)8wO9QZ&U^nT#MZWrV z^OO98?F(vBZkN$)(fT|&%0VtKJ&1QlY6Dy?^xezTehG=k?0iT=Zq?kSVOKyhj2eC) zDq1b_eZVhf-})`Q@yVBCc;~O!gMjXT$!z1le5$%r^i)+MivBq2?)Hmuhg#I`T)=E( z_Mki4W$D_L8#c`D{x%Pb%o*MP?IrW)qb70p*01l~`|ZoGx#k<+{&shMU0pW{6&t&| zUDoLQB}?!NeG?P-1OBosNP0*f6Tic*#xsnFg8#tj zE*e4MiVDk@o`3o0!T+Cs&i%QptHQ_iaygM=7uX`LTqi%V{5-F*KTLGv!amM{3;pq+ zh3n!kJoVmrUX;Cmo)^!1CI5p&SA`#c6L0Rs-xS~ci%X|}y@b9fz7fCQlWdE5Ll!x2 z4*Nz{{Nr!lWNXY5mYy$INgQ7MJo|iP<+;zeH|g`~-xhy*_L-1F|JL;L73V&aBxjpq zEB_l*d^u6wkz~>+?HXa0GZX3ff_d|bx?5Yzisa0)@o~S-VkxhwiTd+EsXZ`Y4!B$m z)zvxXg-e#myINW_a;niJ!4My09^)I;WYdBJEtb6uz%68}X}^OcN59Y~G?$G{mzUz{ z7y5)&Hc^Ou9wj57Nfigpbi>AWDCos-y7DSzjcQLIY+jQ zD1Sq-A1JZ}^Rx7P1YB=)k)19w;kv}d&T-9ivAM1a7i)77&P9NqqUb3!e*lh(EYy$= z^p@6;LJe_>P%Gm?gFfN$<1{vL_s3SBz3U-Kn=qXcag=+M41W*NuzGeY)<4A zT^G#JNK{*<lNf8#bpXsrikdr-l%W1ot5x;rZN;d5zs_q_C}<=c+VSmApN~_dM|L{J zseGK)xZ%_vl_pcl`AQu!GxLe=r1DJn>a$aciT(0alIf1tB(`5TzI#SrYo$u0a(Q3| zl}lSimc4?nzU_p?_v06+Wzm;a#-tE%3Lj0Vjl1*EPX_VWRlp@eoQ&3lp+7EWL>>x z8#4PS>JT|>(a=o1eHhDSFJnJsQO_3KrVan5+nE7mdA8x#?Entf3QtXUz`UJ{OARpj z)QJ;M3k{jRoRg*)u`hC8gm>TN zBGD#n_n` zw1$@hD-E82gu((%{@Y^qT(Vgy$qC)#VDy2FI86neEGw(bt8_?-RM{F^No#WW=JmxF zRJQ^Pa)6RQPwlAJI5gF__7`m2*2{fVv-ZNF(AKqwH0liNv+yIfe{w@=WX%c@EeHPv z9i|~|)v&^QD7`a4W=;}Kk+NVi5NP(z_pvEox!+&e>K>}yUQU*QT(T%xmt>R4LL=JT z>IQ01{1o(o4BKGPx|8MQ@_0An4+O-(5L6f)9|ao1{FZzQs5XkO5Xp&X-m02{VybC3 zK#>8Q#(?ssd1ArFPP1|p<}Q~egQMXB$v>K&3-*J`p{8;hJO_>!Uimzxw^g)`R1RIg ztg3a^;4O=s<(reOMOM}Vf+f&=4Bu97o^Q>`PkO?BSEWIym3Qo?FyxX~D z?M|hVyD{3at}{6I^7%#Vw#nh{H7KTnk*(!0`a6<0O@Ry%-q?%`0%Mc*9z2rBV85zc=8 zHy3wM=FN8qXuBbND!j6Lw`}p}Z~RqQOz!+Ed6mBRLjuF+VZ6l{Z$PQ!^A=g-YA}N% z4?I!g4~_Yp48TylYD~`YSs_0ujTgWItbKOZQs!<9mJV5r+<`-rGTC9N&&F|N>>_8C zS9l(L_Mgn&m}uO4<%Xf;$blzUR}ObIhZ`<$Z=CEcj;7}=T+BKZ@+sg01p&&#JA1{= z&+fSM@86rpYt33>bmUZDxOd)yZNn8_6&=GtK`raT{N>Xz`28MB8&eoWHHlK`87Rm> z+Y(Qp+iURHRQhfuoCxauiklTxW#^6|D&BH#UWR{`2ARX5%&1TwN2OHO)w}B_7tX$X zwj)(t?Mx2O&JE02(dH@;USa=Bm=$UbTzGVMU(-#m@0nxw5{1^PSBASb4m7RnE0PPS zA^H4MxxD>`-_g5fgh6;855n{LR(kv<)%R6wg=(4VQZOT^Y^tb=yM`ePn3W8h&k*>* zD!FNtV-}c6g_#skashzbk^3^J)f&Zp6nm{(bcY6vZA4?UTa0vCtY(8&tHxoWkP#8z zLk~_^lwyDuoxv#C4PK#9d-@N$3a17R4^e?l8zlr52lfAhctB-2^W=mui!_k?@$&s7 z4e6>RrNV1Rga+Y+kVf-_&)Hv2)v-^CpN)c9v@YJAa>r$=*Xy&w1W)FFU3Pn-?oX;>h3a-O$O3tAQc9Zhme_p2S2>Yu7x_5#eu5j z)$PZWWDGMwZ8N7@2jXU(++ranMUPgiH>p%6px}v!m=Ph-G)yT?1+9-i?@Z9SpoUtu z=O)s-+2(wcGvVd2K7ogZW;Yz{^!iW2W4ZdTtES+#5!A~u`k#Rex^qscMyz?GjKMvK^Sp~*r$Fgt zu4}|~rXLfrbzb}IJil})l`Yu7Jngt)L}#NCy}>}hO^UX3#B4X_8d)A)4dimIazr&@ zq7M`bl^zhVF&=zx*y9urPI397_aU8MG>V7QOvKniP@vr;VG#F*iL%DZHV}{S+EL;D zODJY>GwC72LNQT`D?dIs^%?BV^eg1ksWsw$os|6v>#t{)q-$SOkzFcsiHcmPA}y#j zkh5*vfPtZM4WVw|2gW&;K@=bW;yIMMunL($r(f7v9=VxZu_(Qg z{L)1OiR&f8ABhLR|5_{#cS`t(t_5O)Gge5PK_F1fm_ZAPrt4!S;xQ3$?0c{ajKpFj z#7K(KU796Ymi#9nKO{dVFA(lFLOKblLtM+IjY1ShR2C!m5FzQMIuRc}PU}(_)r9p0 z)0-ytZqp+sw##(8iLEuE4#v!AK)KD54_NXxOI~EjFIaL9OZKqeV%f{UbvtZmA7x1| zOX~4Nh8y^U@xP4huZ`p<#$SnC5Wh}`k@J~nyuipNjI;5QPN&tPM~PmBe;@M!7Pe+R~3cuOL5H zkgW=`N?7O`pV%)@5gx5+r3V1&u+_REa6Aq)J$vW>fGW@eFMJ zjwr;3grEO>>wxe_D#Tkz-Hty`y+8E`QQuD{HcdT8=ayRQe}XJqnLE?Vp2alSf2Sq8 zv^Ue%j%2x(fZ)zS`#KV>K?T*Sl$l1%ar8TcB1VOl*#`flOHJz4B&H@>wFi!xMx)aj zT=ZI_!a6348dJt*BWKjX;xy~bYL=cibYDWmXmJlT3C2DxPcVebUZi8ErX%>LvjfG0 z(u8RJ)AlD+tKdJCsIUya$?n}*t@65XP}DQK`S`9~g7B26S56;ish*J~vLk*-tiarp z9xTuj4aNonYv{e4oqBSqp3K*iCOxUplRPRI2qNlDCM5&^7GsuKTI|FRQf=1SrfRni zIPf!-*{n5MZ3Hj3mqgUh%y zM%h|o!X~+h+=~HzvJq{=`SsuZ?lZyz!rdUDb5HFe_x1~iWB^pbdVqd9h&9zSjp?A$ zi0HXu1EdoQQZu4u=y&wm1$x@7ACpltwG1jFrq!J@p9H*W4!h?ljWVfH^RL zb*VzfBXPcnFs6@9WZZPj#ER#eQ85OrU6+>BYKc=zl#l~0J?vO|(t#44+V9d4LQNl- z0pfWFmG|4@w7?ZkH11~RKOV?+;Wf;Nfu3{ZQ&ikaha4*VFh{>)>*<{#R>IRR$p)}w zRbz#!cHzETOHjjhde4afq<(I5*JiP@&M-c(qNMt%jGV zu_78~nOigd7PpzbxtVu{$K+LV5h){9;UjPqeN%WvD#gh}Cd4uvI%~kYj$qbw;J`?V zMGtxnH*$jgm}SRtvM|gsxXk<*@QK*;wPHv@N%IdZrVmLOY9KTm%h-x^!s4Tp??VK- zetEj&BUrxasbaUtj-Kku)OFE`616`68_biAX-UUeWs6J!&||6LAbQumV*vFkC?WLf z8MC91g9TTspg5m~bT~G$csTNby8zUIbnqR}dR3;fe~(wwy7mLGmEb*+|;|RAMO9 z7andLa5c=qKlgtqm?gVrvJX0USIyaT)&=TriZpCH>jK3Bow>sELY45mtQ>A1|F66t zt!nBtom>n>ls>im7R+h^bVDSBlpqM-{cwtgVv{lAYw-^h=5$A+K5tLJ;P%<{-SCO9 z3$iZJmqv3wpGc~RrZX%#MesX&8U{uFv|x^MvU%& zn{_Xn-!`76_J5An(3Vb{atp?y0a;&i%+4#vO(u(7#5U1lXsWg;*fSoZ+iLWr-4VaBBURRI z)9}h(m|S0&$p>cgrkOl%CbygKF+XbN_L#|KX0qB$y3C8v@xlfaQr1p@Uq%mJx{A}w z_>#B{VXD%ggs95tGA5~&k$oy2)0CNf#*${?j%SNfe3?4!+oJjI z!G=qQQ-6yV^yY_ii^%DwwZn~e8K+eJMx`&wH(2H#cuhkc0Fjx{4u2fGwc}1AZ}I=xV%E+Vdxg# z16FdL>rvupp!osVoCL8ATFoyV>@daSC*P*&^6Aqdn36HV{Zfxb;eOfTcc+$7|D4Gh>%a@0s}GJfC4US%X3jAXz#VPu<)B-dDBWNk(w zgXP@-cR}?qA$J27OvoNWM#w6%nQ$pQSkAi@E2k~?>fIL{DUaoJ^xB0mb3*cZ2&I2Okp&r&-GEsM|xsx;6wLiGFaRW?rC!fW@! z+`snc!jbvhg&f<$kxD2<22o1A7ERoGv^FWOD8*OB;Yh+K?n+ucNnLsB`%3{8dIc_^ zGl2&%F|bgGmWaFwVGeX6JB3@w$RocXBf^dELrs2o^re@C!)z@&^WIPTrj84T#7yHV z;Q+=0oh?Uj4I@VGKsiF&b+8TCGx|l^n`u~7G1AA}k8>VmwPWa%2+hraSpusf2Jfj6 zMB;CcQq3Jdd3oD2qJ z1Ir2Fw0c=fuVPGbhvGhktU*B^o=|+OID;&#x}8DMI;&*$J-or7;Ce8JT58bKWP)@* zqvD;!-+uLZiY-DY;Os4hQ`{nf3?m1K*0`rz1gf%NGA8kK9toOZj*L<63{lu>^MZ%qkd#L1v<4tIv)_A-Z4y=-S2312(*(G1__+h!m=O5W+Xul$clAIS;o9dq%v= z81C|MkX+Kc6zT6oz^pV++508;q*I+&HcE3Pyb|o3KUOjKiiKq`wimTE*^)Fc=8JEE`v@&HaW zhVgpYF=zu6&D+gZr5OC7LQYqdLY$<3*a%`qkXqdk{pV;|Bx+JJM1yvE6-wB|wMH{6 zQX@m#pJYxh)G0%Qx z6__P_2Jkrh{YqPblQ>%(^MjXaNJ@hecDR>}(x^-$w`Mb&4KA;jVf=os*I-1VQQ3^gIjH}F?k;%jycH|rKwmYRenjhJ?IX-Yj?FyAq9Y7) z&zSM7{Lc6&iS`2{!t)4Qyg=o(Z0Wv5Q-@gD zs@0L)sdaeYgP2Fk?&e?;X*YwZb83|>s(~DZtQQ#-pNTb@)CLvOI1o;(DHTld?LQN> zNcKJP_SqZZ21SXaY*N$GNDfh16ugkirmP$aNMcRh!nj<1U!2?k ze%HqFMpBzt8102wVLad`5r4VA$$yn!=3i`2n8s?Ik%*>ZtPt&4#^jm|^B48jUljKa z#E_=FP9o&`GIbJ+unMEJ7#AEgV!~2#2E=Z$Vj5aZP*bu#+jO}uGJ~>)o;z;X5H4JC z)uH9z`rD5#)HTfAGOxhn{0j#{E|nwdE-+7g@14Cr{`}i*r}Oyo(QArZ)(<9m_Qp`p zwvPg()j7gn+{wHgN(B~~GhSc2qEPM%MUCb_j(*Sa+xjP85>7nOy677hR&d9Q2QQ!7 zw{@sQniW0_f31Y6WY(oylWl67O+8d?s3v9F7RCTckH*N~W8_$jd@uHs7`q`x`eNfT zwkbwZF_MQ?5oaQPZC_a)l_^t?&1H}G@_+Rk7*Cm%q!Tgi z5+lV+cQNSPlM+`nIw#PAX3}Gvf5lxBlMig2Gd0LY=Zw`~cw{Jl?#PN+7eBUdSlzvO zpxADCNv|m?XBGXcm1HNnYqhcWuDg3(^_(kyvH6?n<*m6zMIYF_R#pAhUu<_)%&#jR z4)`k^(Si>y-kcn45P2eS{!uBZ0>9*rbgy=iPG@OYSO!rkBR7tf}|F#$B`4qxZa>%yk(Cgd(ZGoZ^g;R-2R2*}7ReG+o-Q^0DOJY@Hs3A!zRsj-- z7LmUfkz+;VdqqDfVmB0#zM}CWwyB7uib!4&DLNAkX#4V+WRi+ijvM^&wj6tDR<@`K zh|_=`UoTRVBkPloo+Dt=Bz{H6=y4#<=f5vz_1pS{kLK>YpicSkidi6{5VnzhmflU@ zTYf%KgHPCqfXSPpPgo=}1;7VVR4ewwKf51lTESKzYTi#-NF5@>>6xP*vq>#_*Kn{U zpHluyc>}Khb>?~_{sg^VWG$uF>qX9S2G>))4{XLF=>1}*J)H|`Fr-~5JVUF@;xm-m zap28)gn&e(hEp|&)5R=IS1H_N@_*yO7D1A8NIp!gHMUT^9Fn8;&5!I^Fc)~O} zhX}0Ll4TZ0htfr2-w@v3ExhuUt$N|rOIJ17%Un4{1>vAa%b89{(VWkO!*5Ik{#&K- zb!~r=7=D`FS=6HPGQ;U|w`GL6&`-HUl}g8iZy&g+{lqr*6*5tWCx=t%#~_Ff(P_vE zqIgn*?jv(bW+*?tEQX@^i3U1v?cDp^)x-;YieMgYu=Ae*<%Ix(#AaX!cH) zCgWr~xq%!bpAb1Arh_K3&xDK~`Io6Yid#{M`8=8`%V1aNj-bgYYLDUpjRGc*+JT(t_V_k5^8!nQ+1xCo|MzO4R>!~Ml(6RHib&Q4NkTRyo?O$WX5sF$4tDG)YHzG zZAPtED0qE#&c%R;=mlkNaNYD?rs*T;zN9UT$C;!a1pWB6GZR_or1dbT@OwqS&5aHd zJ~+K_cUk5_FZF=!FoQJ&F0X71@ij8-^5PyK#5j$OpS?}fopAoCgeEhF@VPE8LSe7{ z&$Rb2?ePkO>`@Z?Xa26}hqXJhm|)cl(1_|oa3_ezsB5YV?W+1Yb_-(>15zOQgv_~_kfXXC8vd+JVM zl3jZ|>v4#lFY?KXKR_yj%#MC0|??!l7N5&2$0=` zeQ_MJkc1>`E(s8#5Q_Bwp1JqEC%KTa+5PYTlOTScd+)n<&XjXz&YU?j6UlB5s_1cS zR&2^3Q8B1EfBcZSCk&Z(iw+mSwCbF;bRADw_FfXE(1)xBV7O9Vk*S-mfp0~4T%59~ z5Bx^IPoM75mlD_wJX<%LI`azy_qop5uxjGsh4o`UU*mq_)4SN()b{xAO`S7;Vb+TE zpDODnv({mmaCjDbu&hmGQK&2jO-L$BGR!1Bd_?jHBP=>8+87Z%Zd^j9n^VOb=&z(X z&Hi@w``N}F*<5+EH)Wei@eK(pCVJvNMaiz_7?HR%&LfG-OdR!*I&b9LkMWFiN8YL) z#q)6^M#QU*z#T9BI~(gE#jz#i9#1s>bqa|B2}y}EvITq;o$i6&&dhZ7b5yo%R=vcf zyFYfih@ZRT#$+UX#mA{X#L~z zj^-7qpIr^dWR`bqY={{>_w?okS0Gmxvxn$tgWhTZkUW$uq`S42@dgBpK1_ z_<9xlG1Z9{$P6d@+#BVi)hRVbDf{D;1y?b+%0xYSO!?$7Z7&YI`<253zj%75+kKe>Kh%>@jxXE)Eyj!H;RvJ%F} zMZ%k^Mugvtx23k>x1(yuC)1cF>~>_ZzjyNd)EF7l1kXjX&uxI?jGsx3Yum#ej;j)m zGx8deM-F=*j$_mW4SUq2ZC9fvc-pYHmC{Cg?NL*Zg7D}!g{SRt6JN-<$^Jq%mEsF~ z+!Xxc47jjI(NI3M+V;UeseBmvJbULVfA7>awr_3lo5e`ZJBo_<*OHH~+WS_`6%t1V zf8JZU%674}zo6Nxf=UYgMV2Zs>WoZ=*pzD7@K8NTH9@YxDPrfBIs2EiRO-hi?-d@HM8#Oqu1~LKHe!? z8}nCn){dLF{Nl~q%yl~6PcIHMht+i4ykXPbdurHWFf2JMB|2^DY2Jc)C1WMU%wnd{ z!e`2e(#1Z>n8PzOM@zcL&5fGK{?VFeNoJ-Qm%M0n%os_xm_WZM-8eGpveSPs<-?rk zCE@L#A2lx@*naNAXL=>!R&Oxf=}Rwd*{1jF``>+WU|sZv%N{;`%hwJrTB>`Jvy!88 z=W?{%)&-N{O0j=_$umIxtCK|ZMcS|I_Ek@%5z>-VhMgmFCoR@H?uU8%--L&G`!cvi z&H+ngn61YrgiZzt#H~0*#SO>*fVdTJnzJK|WFOD?X9<;S;tERPSdBqv-L) zcKpHj)&7A(K`WN@K%v)>sR~=BKJT4WAF0~V;5TZ|KGljZvuTVLUNj9_QIW#Wdedem zMu(&d1Mu)&3RhNF*t-;}{R!=@3L8={O=YXXuVg)yWw52hf-Jo%OV7^Ili5}E#O({| zZu#%+(`^mfZi`N~+1dY_T?{*_7s?ifm_)*59?#yzko^nojSL%DS-9k-@khrS=Zyc- zcq4m!`FMl%ELCIlaL#aPE$*l%-5lHx>{Srp4BdPene?>7Wn#qZcO27l_bilug| z_?_N~HLf9iMY`tGD(+X@{wwF3-AI${=LZpK7vJv9s5Xz=0}wjDQu4|XK1u@X9eK?{ zUPokP#tqdN#Is_l$g8$Na-lE!lP#_3NNd!DG|l!;aV%&OvyxU7GqN--Agx7`g~W_% zJMN$)so0eyso1sczi^~=iX=a3!VEk9(EEyltg^7vzFfOHKp{gYoS9K|QVN_z7%adI6BIYJ>KxjZpq zNL!%%V$~Y92(6$xnWL`_BPwh|I3vQXkqiJ$hN2r~23V{vO55NF9TX1s`KAYw@n3rE z5m})nbDXTe`fQmj;()MtwVKz{dqil(-_Q(kvtzDOBA*xTuGdyXx)$l9h}>S8F)VU+ zY6wMsr>vCHM-Tj#6)tOPj+ASQ2k&;1IxmCU}4`>!&L_Vf7xv9rYkCk;c zF5Y1^9`D?y-nl?~`h<71ff)B$^!(YJ&8*@v(RQ`bkLhp4a;U`5dSl1BqzX@$_#y{l zTzKO0?s_{u<39V{@5{T_@@|wEeK}lK=efpiolj`7+F*6MY=TeW>S19XS0a8zqdifH zY|6n&0$ro@X1r;{(dbJNBO6BTi_lvm^mP$>Rm8jqBR@h<#bbv5qoenE^!1)IJ;qee ze2B=@X8QSb0XbYGi8Q|*3*aj9e#Ekwn zo&ho;-@^meN&O;Pe?0n)Xyd+U{l;j$Ia;raUKwqaM(Y!!S-!4EzpLS$g>o=Du|Z4b z=mu@nC>AoQb2{8C-m8mP8R3dJYU&S}`dafA(}*6;3kmY`a*i)p)w{)DJkzsG^fXQ-fruEaf33D8pqZu!qN# zAXWqMFJVmumM`2(%3ghA;4R0&9f{WuFzjbsK5RM6;S#oijFKou{~18?_;}G?63T zNL$I+!i^IqBu(7tj)@_W(HoOEBFIUk@}`hEDba9b{y_Bbx7j2pm}2Git88G-LRNc* zKa>fM2oGe#tXsIaj;a0K_qP;pSzQ;Gckk|<4|G&I`AW{8p4G5Uf1>fh^BRnzPror| zcJo>Kl>-H>hc-`%&nlfTi>yAV&xkKRZD!d5Z{jR^5b?~lJU6k1rBJKJ4{&0BazjE) zS($r$ecGIv?Bq9_bCDCZm}!e5WAeR=v@wgav$>zev?O`L|55xFBx_F2O5SGnC$#$> zUalqC>|PNx@iC|j9Q?>$dpR;dwwJ%k8Lq~vUEkPWQ`LIin(}oGRf&-v3R5qdznCmf znYHV_mKhrt&KQ@xaLxLx@`Z&-di<2d(>ASJA3y)vA6<3L(d*}@6imy^nUt|8U2p!h zbwPdeS$`UMR(>)kT)g?q zw{AFx9Z*`m%jZr@zBPAC_r;6a9yzbh)v<8z`WZ2v#IIaCv94@FsFr{6}wNBa}o>JULb80BTr8W)`AMo#>`5bXPV>cQ@q~j%=(EdtIEqGqf^S4 zWK~qerY*`(jPfjwj&*kMayXW(!potY(snvW+=nuvc5s(7oyCD^NL4#o*Kfb*%8hMV zOP4L3xUQhF{k(ZAZ#{eNSsOdgnYV;0E||6J-j?PE_S8(QYn*nC@wMU_5;ZzC_KndK zlA<%`?OY@quE*_ctb(hZnw>bWV_w;!;-nvtyA=Gf(y7ZrM#&iyvlA1u-J{k;j-z3T z9I+v4V%nzce3v_MQ<7<~R(AA~D%%z8Z8o+ShE~-%qz)ZD<aY6<@QX5B#ywTIBwnkbSv1X_hF!V#x1jTX|Ba8oF#^ak&1n*Q6lSb_# z_^nvPZ0iI2YW~dp2v~^4O*(EMalZsBvlRo0pnuE*eSO8p!Ym-zLAx(>;)5m1XjJ zf_%kho@CN;-eMXPr0TwwCZy_QQaJw;9?A)0pV_)T8VrGmcf>#bcB#Lr zcYK{R4o+q5tmSE{+CQl`@M5gmpdTcHm(ur{ym^(8X76l4?>jRR~ z8v;w?K2H%I3YPOtXRcBcl*ovT$8V?A$|H?gd3n(~+YRKd*IOn}SRdV-pOCsSHgBW& zlxkt|v97F*VZr`~wM4c~K?>1&rEC%M^aOjO_$+(nki8S+6ei~b%S>h(IqAmFji+W^ z_q%_&d*JiOHg0)Fk3D?RueO|-v1I+WsoM^1_2zH5wrNdgO{y{QC9~|DLj#{Y*WUOo zJ>|&5dSYMe^ukYKGslfybnz3dZI4~pF#U`!{GFA?Bzw9~W(KZw^5l_vQetBMTzxf1 zTaR2-kW@8RAG;`S&t$y{2cE@ywFk9tXlA+ODuPWUvKK`N(>sbN))8#$N?STUXCqy< zqZ68*Y;ZX|TV*WfG-f0eFWYx-+eQC+-Qp!T9lPSJ*B5O_savvQ(u(%kV^XG`QCoY) z)YO4bj6Tguc_QH?2!k~;8lv1Sv;cpV6~xUF&j%M4H@;wIWW}rkz{vfwbo7cm#T<$oMC0J z`LZcyPXn_OtFJnzt@M(G4{z<>ow@q@ovmk|e$)1g0hyz5y@Fe1Mg+$R(IdIY2Mjut0Fzo zRcrQ;cd_38O6gFGs`F!FHcA!bSC!67Pao&5PabD1d8y)Pg>i0$UQrP_xo~lQcFd^A z#W8WRs!ZIalv$nzP!2m{Up6*xl||gLi5B@n1s0W&yl^6FfYmF?(4L)@exWshi6v&_ zwU_Qrtz0{EM#tvmX$`Mlc*%3;P0g9xG^4F`-g)<*QQp37W(<;t2bt&r7UVjt1O>L3=1F1RvVe?z@@fjK|$9s`A;?=5qexSz&) zWzSu-zf8YP&zw3&MK%tA#X_ys>R zL;9})8s^!qk8Nw3Y2bxt8rM!JK5>TB^>feu01dvtxFuF2$GrYn#rzZJNQcqbfmvdZV!g&B&$&S_jQr{{3`t(w^} zjY*Qz@B&U!9cE9YG@H@O}L_gR)UtuEL>DW4nqx6D25{g%Up(7fEfqSeiFkm$_5|Y z*!Ua_fS>n9Cl2>#;C*KDc^?aJ@O^0?3*kU_UTMgq0j`yu28}Rj@$A@}SuCYILG&1A zKH|ol=qpjHT01-LX4kW%MdFspiAhyMyd{EhZwkasyfIGPqlnvx89zMTv<$VLk#@R~ zpJnMXx3Y|RL?u1MUqCfQ&tF6OjWJWE+u0aWPPD6rYFAZGXeD2=rH3t#WFF)Wifi~R zg;?kQpxRZH8@>>`xsruE;Rs)GolPWQjUW7hDlKWdZ5n%A-+_kAEhP(yBZKGl<|GZL zGWep(m$a)kl|8N}p(5>Sxez%rxTm+SY&acND-Wo4)uyvIlouwX483!*Q!jy(DZTkt z)vnr9_J;B@N674$@6=833sv)~UA1ZKbG;BKuRNhKvN&&eP85w=B|$cgeJ8*Frqj}Kux2BVo)AXiqG+cM=F}l-#WY~d_ML#KJUPs zS+4l}_s-jxmW9vtaOU_@<8UHVdJFNx=W_;@DKGnMMlE)_IA$#*p@YXu=(PjO^#8yr zoXrjf>U~qnF`?HOM>dWO4)i8xXhXg5&!!!^$^9zttND0(rAzG8utW=uXHu~}YwBnu z&6GK(=kd18#7ldDsx7fkRIv~Crsdf)@y`49Jg&3=cI?gW&34Hclc|^Fib=y`hnu&m zlCfiNcD>@HB?}47C`>y^+#)Y3Zu4yS8k@(Q9_^sF=C~POk;y+QnN;y3lfm95O?d2z zNz;b<5m5S@8O_|JGHHm!QL=8II@Au#JobTQo*rp~oYX50kaDS@NjWljX>alL;jz;O`P^t|PU?fLO0jBHw)PfO z42%CT??)@GrBda##eD`GA}#1R>4%duqK3AhKGkM1gRQM`-j;cBc{?pBM>obyjJ6Bj zE}6sBeza=K?YNuWMU;%ZjV`9gW?rIa2q*gB+%m<9o1OPBAa>rbAo3%F+j=JzMyC&XpR^B)zebxe zB>sVyc>fFH_h>cGIXh?$JP4;dQ7cZjV-|i?DTg1WR7eT>Fe%CJEzUei%)*Z<ZGj8FHwjt>0F zlg>I4&e>$k&XgpksI`c&QKJgOW`*q!yP91S++o%6NewLSP7XhSuWMm32RzG^rg%6r z=fDg<|6*32;?60L=I~b9AAg$Up@<6zg$kd;teh(8G7BuCeuUrvQUzM~ncO-}Zah4x``I2Tim7)ZL zT3F`0ca^l2mTxb)E2XlsJXxQXTwYa?x;8#5BQ55Gf^()FavjZB;q|V_7&ESJ-hzyb z1@r30J(rm8tw>Lp-jYv=M!Svg+=0aE825pAPScUYvq|==$0s{b#!hnObRCuc3Jz!CfO2y1S)rZa>B;4l z6{&ZXY%ec6v*fNdH;@@!(U;&Ytr(w>Ug6D8gde252mizK zF{|t+vmb7$%RK1zRO8j-@x*EeqpCY%ua<@OIXT&5$EKwmWIg1;w6WRA2VzHFoq#*Z z=md9KGMV_v_logfhb z36+yRXPRe!WM<*msEPTBIZ;tXX=j}E-IG<5XVbLW=o#HcRBS?2!g%(eGTCA`_k{W) zpGD+zOjr!FK3?V>OA01uWMq$bkJREu#ziC_Oi7t=aQyh}@PiQ%6AxxzCI)@?$m-Dv z4I?Asn2yMpd?0(g)YY5C9Gg=T^J>2AvT5fNCbP4PT=3_t4bky8kqmNDicIAz^DT#^ z#09ERu_4F94pd|Q|yxw^e#*CRYr#_?ZAdX>n zo;{vt)tS1psxu}WjE+u>G}+nE?T$)1m}nl@A9Z!q9qeozRh@d}gv0}!t^_xJkji!} zN{*fl zDXyEsyVm5*tH^S@KhA3_Nl31!C{0+r;M}#v-ZkefTD?4J@~lb2(wNR#g>;>5P}$2u zOFWpA6n(HdJu!W3_yHD1>v!lTYx1rfs};&_F{!UAK1=0nllSaYl0sWDDAb9vJpd`A zz{OskGoW3RT3JyX|7J?{*nwAESrzm1^5<7(xNdZ@$=RA!2RD?u-ESt8R#YS>l(glQ zOqw-0DIu>qf6;ksyv1wJT@XlRn1>Uwrf5yoQ$6m3Vc!aWoqc4gBVroD!$)feM^uj< zJtgyCR#wWvDVbAp4~!mlb)x&a>hSQm!~^!`GiKQMD|5BN&woncA}y)!F}*QVTnZgQ zIbBJL@)vPLB_t{C<8xLNGcG&9b7th&%=oZr&5)y!uL|e)4&lGBt@h}bs@1b!Fyb8CMu!9 zZ-j%VhDyz6C$BTZqh!aHmWa(8j*}gakx`U3a>V$ei8bwu^CmCZF}n!K2^*c3vUP7j za!#9;#_UbxK)ik@J!X=YQH{r8Pn0=^ZPT>T3D?Aq-Q z8(1izmIIf+y14$a?Ab+QGiRS(RXjf}epXs$!Ou%~%o$rbt0BK+#f*%R5s!MJ*-Kw$ zP>fu?kg`p#j*MyWj2z{OU<*t-S=>zY!q*VBIN@1)nX%#c3B8nDQZzYsLU~5&))^MzexK8ab7q(5`v+Dmx}<4pFn&2a@$VV`s)6%V{P>08FFk{qt{Ak8s_F@| zt395q`q-7VBj=7STU9e*QR0|6qh>`dni`X*E%GwI^=^s$KkHqb!JdCNrvF{pjoI1o zB;?`c4lMBv*iG^h9~RBF*$K#qMW$#)q5Yf@6DZ$AE=9nNs0Mr zVo~OtGp3D>_9l&)kU4#Fs`!nuQe;6&!Ssx)8DHm;WA-IP6RS|#)jquoUK#lfO=mPd z&ar#)ULiZ=k905Oz17ZpEXLBJp3q&HsnIT_kaDkSWAypdll@;QfqgB$qNUEYoNzPK zxi(qdKF7Isp|ve?uHEc<%!X1b8V~-F+nnn#Z875<`*}E8)bq}DB9m?KN|~a~-8sx>(n$=#oQMqjNoi>t~$nk=hD( zN^NUPYj^9urmbmP8@n6Rwsh>=+u7Q(tvl_(v|_KfVshHtj*gbLrnH)l&Yc~djoqys z?Ne$yJ6gA4MWcG54>g5RuC zZ+1EHr{SJ9MWrcC+pO*4sl+Q!i|7BMq5dFc+#Lm-DkbF&Q^lEQW;O=(cGYe23fJ*_Hl-Q-~>_s#q&=@d?A;tk=DcCI9+ z&6I=G&@Sgoq0{c_{LYmaS?Yls(hv&5udQ()KJIKL8m2TlsDK9ApNqK-wqaVxvF|ln9o@)s{w+WnSv_y2RWPFxV z@#`PUm~1@Oh%_x-%fOpHOPi==YdOry(JMyyN-<=V(^ORAX*3ld z?djSKddpc_HN`cDq}P({dc>-MjLg>-kfB9nW{I{`JB=BF5$Ue~^-y{f&Yy-Vr+ zK>NP-uiC#L0`F_rYX7eNPpA3F-~1vWC) zW7)qnPLF3h-$Xr0PiFmXDl25ia(vKueS-F}_9s1!wJsTYrk=(6r))h(pTy3%d3wG+ zSufD1=!Lph^Rq)yFvQ!6eV#s_vuPIUi}c0p2l|MlzCvHgI-1q`8tqfg@dUc(I3?x(|hrhx>bKd|2nI!zM((KNj*>N z&*(hAnEn&}P5r0(f9P-NZ|gtPf3E*Re@FkN{ww|0`n&pn>c7z~{XPA+`tR7q z<^%mh{rCDu`X5;3{73y`{ZINQ`ltG5`sez9K8Ucg;>R!z91_@`HHv_$kiUz z9y9WceC-MC>)P|iWUW_wTzf&gPNqETQ>(Y~pD%P7>IHoV#&jUuDiC^1Tn zGNW9(Lc7DLFe;5IW2!MtJ7i4PeA+GA@3ech>$Kan`?agJ8?+m>Zx}O-nH*|WZOk_2 z7&S(%QD@W}bBzXLo-yB8U@SBi8HWwa zqj8gQvvJ6{#qe>M(rw0i1DcLn9*xIZaiUp-8f==!+6qo%6Qs%#`vc3E#uq9v&M5qpYgo$g7Kp99pk&k zOUBE_E5`SXSB=+<*NyKR|7!f3@dM+B#v8`J8-C+Q#!=(P#xdh3#+$}ZjsGy-GTt_R zhRg3SjCYJ*8ox4rZMF=%RRLTs?4%w@VwPD?k#%?LBnj54Fm5#~s9lo?~jnxoA)Gu})v6U`(u*-SB0 z8CQ=r$C=~J31*s^Zf2O7W|le8%rAW&yjX6q;VM$SgKX%u=(=EH^96 zO0&wGYECn!n=?3gc$Qgh&Nkr^n zE6gk1Q`&d6wS}Q;d%d%3BRY07n%L6O*)(z|%6rFF^lmjQ2%Ej5aSN(>Sfd?!W^e9n z+TG-7R6*G6j+T!0rZdAD?J%llOKazrT|1iFn)XC(30=Etwsv&8w(yUqc1t7CdA8a? zEpaz?b0ip`}=mg zeA^p$c62dx+qtdDtZQ#Eo7!8#mN@0m;grJ?yBs=HFk;EJUF|K6ox66lHSX#j(J}PS zv&>FIr=5mnL&!#V4!Q9xv(wON2g~iRx>OLgJXCa1U7_pf6+SB_1YoVdqdZrb#`9&sUUJ)kcT4o1uxxg9qlb$k+UT&_G^v7%dpvX>QPu@ zlM17jbhR~hZL_aCLf6sDhZImW?LtsQJa+co-5u>6T_d)(Vmjzz+%I>Lv)guVYgCsJ zjqM%XjOtq(qw98dwUQ$BIJ~ag`F$RutR6)#+0iQHY2U0I@^a*o9ZfCvOR=rIK8%)I z(Q?gc>TYz;Z6tN7AuFjW4Rh$Z*71`GJ@<-jT)BjxdqLyQot!D(xMTCyMq|+~WAQFy zO)LDWQeZ4?HJ5Gca4&Cd+0kgOXxtU%q{dvjt<|gnOS@WaGPA3qCB8t4MmaAA?jsw6 z1rgmeBuC*S#4aAmkGhKAW&a-dR6TU7?_HaD-Q6OYb8l^G>uwBl;&Scd2UC8;9zxb6 zGWVG(Yi%lPb|UB0811`^J*{CKcK*!HZ5+FIoG7MBFB%8G(l#lfr4ucg6fWx=cR;8jKN zsxo+06}T$*2CsrN$^$ftN`vtg1!E}+#!?iFr8pQ%aWIzRKrG(kVET%K@f8QtR~(GF zI2dzrFy@kA%q78?OM)?%1k0c#NTVc3qa;Y9BuJwqNTVc3qcljPG)SW~NTW1Jqclh( zR4%1K8l^!Rr9m2{K^o=3RFwz6C=Y&79{i#__(er9RTaUsR0Pvf5ll-(Fy@M2%oV|y zD}pgs1Y@oY##|Z9Z)K21WspW?kVa*YMrDvjWspW?kVa*YMpckTRggwikVaLIMpckT zRggwikVaLIMnx!=01YI>;oTx{;MXE=fJTuwK%>YTpi$%v&?xc-XcTz^G>W`|d=zU>WLTN4wJo8pndRDh|Hlo&@Z3nAWkKj351re(Q%|OK2fh*5i`^CK~Q0Yg|y_F-B zp;jr9TQ|3jIBOT(far^z7;!y2TH8fM>1x{2(Y`gJY0nm#E8dD|@7kr5&Q3d?%Bs>L z&(5YUY1`^{b#|zyNPkB*ES#d;DS2r40chlAgG|?t8u5XL(-iBsmUw1_{ zx9$#HM|Y8ycIO9ot!h=#fa~XYi=@#cEFQ513w;|#W7V;T)2+5Ob#-lzQQEH^@^^yc#eAR zEvZ%X2^D=pMW?8)q)y%^RPhwm+36)z?-$jV+VK_FmqcuB>}qZ7*wd;yaq2+jfUwlP zWLrmPySqdEyHfqTOa4_UDY0YpvS)*HU*g)<(Q&3!+2*FUjawJscNT|w@&@QLa@&G+m zE<9J|f}4v&zrvwk;n1&e=vO%OD;)Y24*d#;euYE7!l7T`(64alS2*-59QqXw{R)SE zr9;2cp1L^lKdYH4gn6hklJizs8|o*YaRM_JK`;^b?DbR^lKgZ zwGRDShkmU?zt*8&>(H-t=+`;)>zw@8Ir*=1=+`;)>m2%ZPX6m0`gIQdI){FpL%+_U zU+2)TbLiJO^y?h@PPmB;_4*hzEe!WA#-l1Rb(64vs*E{s>cG_E7 z@6fMz=-chMx6Ek=%beD-%hX3Dxg}>UYAx?<#%VtMn17 z^bxA`5vueNs`L@6^bxA`5vueNs`4RJ=_6F>E2^{QlhC1W%P02^eOo@ccj(*l$-P70 zmQU^-`nG&>@6fm9lY580EuY*w^lkYpsNA4_YQqqKDl@3 z+w#f1L*JIqqB>hX2_5>jd~)y5x8;+2hrTVJ+&krO%P03v`P=fzy;J_Sd~)xUzb&8K zJLPZ7XHlIkpM*|%+w#c0Q{J{ba_{8Vmd9eR(+`w*>*GT98l^v@9Bv-+Oli#WY;@>7 z(OZstO?G;Ku>ZVc~sF6{YKJZsq2Q2E*LKz!73&}Bwd=Wxb@{OjV5YvX_)38ku(<5JtDviz< zv0~)ZQE4%r*h8aVj=MAd-x6FYm!~F=doq1f=5;v_hb^0Q9e;vA{AeQsy& zfk}sQ2lC?i%gcA=r-m)d|3&_XleH1*P`lX^ER8-894$ZvB`8z!G>A+uZ=gfb1{@$u?j+j2_IzjcpN!LY{k~;n* zoRezDQsa_vPMS-@)ph&Wpc)$uBQ`|Eif+fA5;z*Ltu0@H*@I z=Ieib!|ofb8<*Yqqnozhbm>hm->lty;msc(I{%jNTUOoD>)U;6_^tbHegC%l+wPon z=*ylj@A>jKCmp(7yM3gT$?XSjzxy9M$m_cnaH z@4xC=@2&64w-A;wiBVPl;vtN;Kmwk&C~? zGCU@7wfez6Z7yg4^9TLfGQt&LHNUL|>+sarKzJeXTm%k+9&jPDxE~;n2f;(&E8t=9RnQ9_2Ty>ngCpQc@GZW37Cc9s&x04iOFVxCyb4|i zZva0y3XXv{fyFoPgAcV_ebiu|9t+|?0?5*q>8uCU%e7{`0`J92uB&)&Dj{W{lYe{_ za`l?Q!}>sfT8bBWP>j`flyovA@a4YyS-`+Fm)9)jE zfK^}*5#Qm#9`=}@p+5rs$GLu*-=5)~{OZqhO}_LW0rI2&glBJppK|@5;63mOY5$aO zKO_8{aDZ@7i^maXnZYhZ#-zc+#u~6`u+P{IcJQo|``y|MV?Xy7aDNf#;rbGA8TbPy|XqIp0-+sbD&o397*yPz&madoGyI^+K>1ECukr z3E!Kmz#6a)Yyf8f%GT^4T|4;>{xCZUy9m1pFM`+EECOGge(fCnZo-XPHhh@}ia{x; z81!kC$W|5MRQP&2A@!i$0B!{EkajaT1bpCD-n|Wc8Qc!;;QjCN{51e?Xq311Gw=)e zV0q_kBIJIUSG zD1pa;e!-=E$Y~!jxFlgqK+-<*rJXt>e!-=EvJqx>e!-=E$Y~! zjxFlgqK+-<*wW+4NfvELHki!47eJqSwy0f55eE$Z8%zAft8qP{Ka+oHsJsBeqbr;f?xECrsBeq< zwy1B5`nITVi~6=GwI1r*qP{Ka+oHZL>f55eE$Z8%zAft8qP{Ka+oHZL>f55eE$Z8% zzAft8qP{Ka+oHa$VbaMxIOE`>A_Bb?>L{{rDW_;y0L!O#7*C zKlSaWzWvmdTR(N{r*8e!t)IH}Q@4I((@&lGsV_hE-{LUz@@8g+R&&jzKH1&C6PrHinYH$s>79e-@ z?iRhfMelBD7I+_gNWEkstF)SMvDBBJ`ts}4r49{!7N`Mm20gUYV;?=M)Fr(m;b&lg zI@HMZB*HbI6Ff-E^Eg1uppN^f<34&V%Qyz!q+XL~S;i4g0O=qTOawU~7vzHiPzZ`Z z2?+6rAO7&eAAb0QvVlKlz#lUde~h9XiUk?)L>9TOLWi0Prh@>lT*&i_0Ch^q`6)R+ zCFfTqcL(o1$My5zMM|Pv=`Qi;E%B6upOWxX5`Id-kA5J!f#?OI6U4(eGvJ#Ul!Tv> z@KX|ga_uMAesb+6$9{6`C&zwr>?g;5a_lF^esb(5$9{6`C&zwrO#7}x!*V%X z&i^a&Ep7MzCK;EW%tue=`+}bAFg;n{e^XB;GJmR`tdBMzps}2)C+kD*`;hxSrzi8# zlZoc?|8Gxrs#e!eEl8^?I>n!Bb^ZTPt!^3pR0%C@i5lffn-u8(XHZh79 zVWUl_or3pleSs3E|MAoR_=k-UWmNYRd?tECVDu#;t|23$zk1ZtK^x`h8>j4j{~A8{ z$Lf8fMgI%xdz7Qn^B$yrPNw6bujuLY*URXym%%|k_97qJU-z6aenTt4eiEjTe&7r=|)J3z*tFA=^1UIj81eVyH9d@L#9q^*kELeD5l#SUQcHvxgqeg{=s4M+ zf_E8X>5S=-${w9M(dUDWK*qPNglde-yL-7l2b$*-9^g01UB`ZU(}O*y2YXHr zXaDr+*Ap@x$DY%JJ*NkIPLF;kv?)_`a%ZeeoG)`vzOmW#V6*Abf5LCrp|IKXV6*AL zX49kp7JSOH&%q!)lnxA92$LQv3>!)mn8dhg4Ok0gyuFEVJCHFq=|^wtQDg7@gcop+ zmWlq~haHEN288en;{dVe^r$iUm$;U3`IX#1h#vS5*N=clxtB3Ie1L5y-gtuRuM?6d zY&-GBlZ4L@Qh&ye0eLch0;osqIx@Bkjpg6x{sZnmBxFpFou|k6nD7%oZ;VZ+2b)fh ziA}o%iGkR!`nE|L{GYd=v*&qi{M(CwIW**1~lR*KP z0t$f_6oFz;0!l$Ss035NbTAWCgE;_RQMQNqgkpbKNGLXl#e`yqSW0*r;W9$8N30+e zo5U(Yu}e^2jFrST)Wdj5>_a__nZ!oaqwEyap}83w)K<_8wt?-S4YY%uyo*)B>;@On zo@CPc`02m=YMgcIvDC0})3C7+`e^fdzHr=p7w_B+?g96L z`@sF+0l*0F1pD%1(CXzmBfk@D%un&#)8HBKP4FD=^nvHW3*bfY9Ux=%mk0y4XBoG@ z&ixy}4~~Lk0J%S5JnunU2nUfs#`cV)Y3syB=cldfQ#Ksrf_BbNJLjj3^V7bGhS5h` z)<;_=t#{Prjz zb)js^loxGFA8kt?ZA%|*OP{hC54Bl{?f3)U|B&$agdZUzksum~9V3xYY#FJ9$%j4?pdPpZ3Ggx=}Z?H<4fzJ$5X};_2~Y@mikMgSnsq%tw1!3QhydxX1E_ zbo$X!EJr#mv=Xu9oXR3`Sn12B8sFc=cXxw(z`fu;a6fneJP5E-pq2R1O8jUgezXz` z3H2kPek9b7R^mr1@uQXa(Ml{N)IvfnB-Bz?kUpM24_*K-g6{y))n6if1-uHxYWh0i z8^8~+cp#yEBvdSJ!>y?vdi8J+3BVHsU`)LaTXR!*j~lky07a zi%m)_cNS9WN87NFQa@7aN7Jy7Qa@UTA1%X=hT%s_{Ya@F?ZUR+IQ9;t)Q^<1x)YFY zvPMUKqfLmEHlsB(2dz45c_w4sO@wd=T7%fU#7bxx`w5|ql!~>`LQ2JAXrU>H z)zG%)UdgrCP97x``w8`-tVBO1gg#QLtVKwvSQbOp-S@fwfcp;#e^2-koEZtCK>}l# zL_)E-q!QA?A*CT}QwG5p0h2&3$OB@5nhXlS6i^7fpa>L$5>N`tK_$RW zh?M$~Qa@7aM@s$l@?!C{kW#UFT1cr_J}snFte+NADi%-+DHSWIg_MdV)Iv(d8fqb> zViC3I<;5y$A*Es&wUAP=j#@~mpI+WVN-d<+LP{;9)Iv%vq|{;sYrs}a4mEP6k#dbx zBb63XX(5#&i6Vv87xsM*@H?XzB*;R7EF{Q6f<$^Oq{l*fETqRmdMu>Ja{4U`sj!d= zvARjWWg!(7Qehz#7E)m$6*9+gq8)k^92*Np!*y|l@r2YWTyEQ@_i_z~!QH~y7MyLt z*%q8_!Pyp^ZNb@Au+I)-MZcnaxiEVB;2a!@np*}dt2PgU9Bp>a&j6(Zp z-}~SyAMLx$;QMIb`)J<}qkYNf)30sdTeMZ$c^{gX4^7O6CgwvE^P!3PoYCj0XE5&K zox1@u+_dvP+Ib)CypML?2bcQbQXgFEgG+sIsZV`$6AMHG||D^3%@EpJOf#<;s;6?Bq@LkgX65%W0RbX?r56Y~Kl- z?LpfK2WS(t_o9*c;BueCG2^wKKg^hj3`Bl0wYNunwt;JP3)hdx%rSNpOUB@yw}O~`8?lGcmem=KO713 zITGe`B+REI>`VN91@B+U`?i$%94YfLYP1+JTJ#k@G&&!Bg^#|%heqc^0%hiRs08{P z3G_J<=wq~KF)-secX&yjeaBk?{*;(d<9`{+OV=s)`CKleBN~WGrTKlV^luW zELrfmsoGz32-*;fJ#GTIqHj^!`CWu}gL}Ze;689a=mRf+@9-t>q9uyd+qqcF^^d_% z;FR$o17v}0FbU*=$zTfbf?`lgT#|Cz^0`{2T(u!Xp3WQcw4CSmd>^`!(&u{#9|uo> zA$mJ)s;xuE5sL0i`*BLWS9Dyok3i|rUfDXV=&ho&ioPnks_3YX0%$5dRCLb|!AGud?1>KXdO$zGOz-Omazt`1N84otAHNca-2me?*ZbECwD%*lfGyV{CPvrhh+q| zmr?ALG#)U94vr)X*a-=K(MmxD?^F_2@jKeKMr(hSgn{x20gqgAK3 z77qd+K7P~i@tcN^-!yva&`jb1en*$ouLU=NyP@HS-Ad^c4_tCJG4n}&?db@n{@1NXpfH39v%BTwMXwb?a{G6 z(;gk8J$i%o=ndMVH%`(Xy+M0)%xRC_aoVGIoc8D)r#(7$iuUN3(;gk8Jvw%h_UPD< z_UMh{+M_p|_UM??9v%CF_UIVx(J|ViW3)%dXpfF5i;&$Oz471F9vySqqhn5cbWF8J zH^NESNx_K0e{$0Bp6xH=B+p>8;wH+_5D(EbdOUiFpqJgy;|f z-Qgtqfs(zyK?lIkA)xagpG)bFu??KEPyYWQcWKO+oZ4&kIevQ{yojz>11Nv2J7S&r z`^~bh)}rAaW(AqQ3HjF+4EAec+rzs7P5VSopK6}TxaC6Lxd;fyF_yq~7x1_Jt31E7 z{=t4_?@A+gj2v}l&d{p=a{t>q`Q~oopk&aP|M&Re&KWkN&bU{b0cyb)mE2wYemA%W z3>|+z$9*3Vo{(`ke4)nT)5taP>a&3G3Gol*6*W$u1kbDiGEVOVN5PN5F~FD|ib>GKI0`(WX+$M%JUGQKYYv`1LD)Hq)+M2?qf z5%80EIYl#O8^K8ML~o~%jk#d(n;J8sjQs4`3dN7?z{`p$<-J@@9N5ORdN3D=?Rg$r z)_lT0XMYZi5{KHMHxVB;(tjjdG;;S%{qJFq&f?_FY#^TDGU}}Ywnx;d?bB!R{$57K zC$~|H%_d}{mXWd8sbzG0ysi3f^6(J9F-p~+0#6g~%iIsOS=%G%6YSQ?Tm4hgDjw^f z6XLb5M$|eI@jqeDeo)IX>`}MamO^&z$9b+s--PtSct+(YJNGk$|DCq(BrV4ot^d>J zO)DujZ#<)NSgY&pz*>w^+{J>7 z!CqReep;=5TCIL|1dpfH>c`sG&rDfAYh689H~X2z>Sq?KpINMa?P2g$&n3u8YP#(pe}{a6_LnGxw{Mx>t^k$z@G`k4{w zXGWx-8IgWwMEbEn_G5wU#{$`p1+w3y?65%gV}b0)0@;rRvL6d%zj+2AJ?#8`d@T&M zv^G&&!`IOjXm8W=oZ9C2*II)D+URli#Gu|CPs{a1wnVWbiVd-uR!Zhc{t?#FO{LC` zpf4OjUwE6*}apVe^e zB!5`n!2b5*M(g{Qe5z>pb`K&6|Y(!P@b+iSt*)_b%W4hVR}Z{2gnt zKhW-BSN$W}ANl@I{Qemj&|YPOi&u36xU?gra2fmDzp9VX`uXZ=J(IoOCo-DK0lA=x z71Pz4NYC3y&fDywF@u?!0;o%Vhp%TUAbkNY{34F~^W62nZ%tF6X8Wnxerk4tQ?t#d zsM#5;|8E{rv&|>1Rl7!)IW>BYQ={ilqxTG{(T3w{^d4$-!xz-(In?OedMvd!hS09n zSE0~9X#IhVVz+4_^((z{%Ps> z`&v5w>lThb?}hi5ST>}G{~~WZJYn$C{_pe16AQ*8&^X?D@%8@)mWvd$jemOTg{&4Y z1oh7t?5J38wLB0QPn2W7sN}vL%moc#8CU^q`>6Qn{&gNS5Af}S03Gr#@(>^DZSxY} zyaHYY;(7Brcmw#sQGlfyE5->PIcfww3Mq&Mqd^>y(X{wOjU`M2`1+sVp;N&#<~D*O z>b<r%kDaF{30mD~qBc^>8Z zG0+Rdo+zF?;>Gh8_iuxrgWrMo!3W?&@O$tP80ygziB2C4hI;lSav$*QN#&Zc2^O0# z@>;k3#uo6-La+!d21~$Fa2kOBlt&OesJwz!5sGKf8n70u1M30fCFLb_2H{4q2~c*Y z+@(i6g~Us!8-6ZPTrQkSsr=o%>Z0&dBo(Umq{gI{{wF-^qV&y-KE*23O2~LlS%&bj z)){;0yTBfn4w|9~EC^bv8m2X-AJf|~uo(h1+Dy7 z^Nx6?LfQ_ze^}>A8p1^ufzY6l`zB$QcgbM1Le8%89Bm((AlqK*v?yj zcTYX>(i0Co@y<)8q{M$Sv^&NflyerKhr&O}-tEHXNWa6879458k(R@eL2HNXdV$p; zxLXAjEY7BMQiQLi@_>;G6TX1poc(O>%fDPtnl+GO}yHX6i`EGoi?H z7ZPAgR}a!Pde0vbFFmv(4JTIG}6P^a;JJ1Z7!|Va4(!wdEcO&{yn^I zXp#OhFPqJzRNCWKa561HGz2WdC)@c>`IJnceNG2hvRNr*`;g=k=7R!I2#P=nr~`9> zSdztx43E*K_i657<#z$p=*_jf;0OonIHQ};+E!L<{LOnG#*?1_uS@GInm;uKUkCR< zR4cM%{pBLC1e^wzgOy-4U<9RBTb)k0k+gh2s5jVF?-R#kq5deevZ0oo*MqsB0n7(W z|8IL|1FhF|=JCDHAtK@{La>r$QlGa(d`)DGtCmt_%`#nP#@EU+lu1n*H5bd!Mv~$R zDi{WJyG)dc$jv=E*vRyRGN&T3q{=fhL-vl1-nC(J(Vei>4dgsk$7Spftd*;I*$+N|ud&=5TzOtPf zt>h~*KoEr$vsy^!Q)XL5Uj1KEMd@YAAR)a>86>2aDT9RcGG&mEUZxBZbv*3KAfbIe z%8V<$Oc^AkmnnmU^fG0T(7qpKkdR)cY`Jyz7b;_JJw277Nh9g^?BXaMqW45 z(3*3*odst&2RIK6Dr#wHlGq|F*PGcvEZ-Zo3b23FkYEO518L6x)~u=3ut!8qt%g0K z6FHUWEv#FXOTlJ0TDWS# z!ZiU3XV#`JKM5*lx_GUnrOReID=beI*BUKeW_gm;%i>$3)vMIWds@B*V1vuC6hygP zI+?6?8MHUUMk1>p`WRB-kcuQL?5ulxZ?knvj>b}n?LhMM;9&2*lJlzoNxfzf>uwFJ z7uK*kaal#?C*CIu@AI!5Mfaik;VIYfB-zn!03=~*@2}Yx(Hf`(Qd09e@_Xr>=*t50 z=~l8b+DSU1GtbF#I9gYtyP1CuwrAyar-=@F5yGYj_OD>+^T$WLIl z;;it*WQC15D{RD>+ak)j;r-6%i5gY4YCe~;1!1_b`Wk>SiWuuQjvOF7L7p3N5BXmi z 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 literal 0 HcmV?d00001 diff --git a/src/java.desktop/share/fonts/DroidSansMono.ttf b/src/java.desktop/share/fonts/DroidSansMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a007071944f7c90020e798eea53b10065e2b45a5 GIT binary patch literal 119380 zcmeFad3;P){|A1SJ9oBZ_L*$ROhytBBr+nR$k>tyCDukX5=2B7TePTpLRE>S_NAq$ zDvB~xBetTtKAu{tx~rs{YN>QnCAs;%&z+>z=Xt)rzkdJxUaw~+cjn%6=brO9pYz#2 zpL;_nA;d&x6HbZ-3{Fbfe0uc>LTD*ki^e=WYSMis-$+7q9}r@Gf6Sv(-MyZ>cM2gf z$%HUV$)s@)mtF7%2npXoh*mRhRM{jV5iOzbXXE;iaSzQXS@q1Z<%A^mBlL-nOUI5X z{;_z=K%BdVtz#(~j3d|@jMoy!ElVGsI{lCPem#lfchH~Vp^0NgRqh?u9;f``_~B90 zCuy#;X*e(XcTX7g@YtEZe%Xr9J-A-}*QAMMQ^zgtKakJ^wS+VuI%&$-N!^cq`UD}- zfRX)!h`C}r*Q~#z(A?!WV$`95kdtp;9U{KpUGeZi<(>MA8n3PlhkC+9D_*!p`>@iS z5a~VTorawnui8`aT=0{M7XBnzMr>pd(cnr8Nh0~U^lLf>xTSrzDIv4)OGZ-hSwc6E3)Dj< zHq_EB_|-=AU4cPw;J{hr zVZb*Tqg9ca_{BUT;p*L3p&<1U%t1mAgK+IloDu8Lw2AeoYPgN}HToLf@6y*m8CSu@ zwd5N*lk`VlwU7eK>2lIQcG9kZeHyMQB0BJ11mMfTk&PHhIB5o`a=^bifGLb*LS6^u zgMhF--dD(c`Xl`c?{peVbMZNmwx{Xnk~tsx0`SCIXX&Rwxe8zBz`r+lP>y$CBLxJqpI;2nmwXyT;@NVz(S=&c0U z2~z(cP-78(=fLmQHEuf^ZZ%vK8>mUVg!Gdz>!zN>FDGMd1qBBwOz?}43PTz+C{_loacppGcav}r?+G!fKLgnq?*1WaNR)GAiXi+RKYE8;an#oA;*oIti= z3;|ga9Kr9Q|91SBL~Hupze}*;q@N0ZQ+t!tx*O&k(9+$<|84)jNt&j%CVY$U3i2ML z+);9gdO>;O?WJ$i{d7N8W|2Bej!&^QBUBvAKjR2{x;i4sAEMzYSUfV`|Dfe`1$~|d zz!?oJiXCNdvv=7g_6w(+b3He6FJH(P^XK^){yzUudP-w&L0e?BnAhTu=zHBpx6|Fi z9pjF3C%b*_&h9SmUhZ=DR`+)IZjZ)e_qaSUo;XiC&&U`SBgdFyY%!5BEn*U5vSW&3 z#>W2hj-)g+)HgH$9ycg|1>H>d0*>1(9B{k^I6ej(mR2AmbW()t{?BTYskhJ>?0dTwwO=ysyK*dW?{-Lci=$bED?R zn(H;+*VNQh*L+s z@fLZTyaPV}Cv?caz&B^eS#pk?C+|bbeLyaf4fL zHTi~o3t9giw8;152WWxoSf=0qlXa?=nf<{v}_0SmV5jN zv8w@pK1$iSDGkplx2Jd%$}Ex(`z16?%ZaN-OC> z*vyCMVS0ofrN^L8kJA(MBz>KpqHoYQ>06LE??A`?lb)vkqVLf&^ejC`&(rtm1^NNK zNI#?>(U0jT^i%p7{hVH+U%>9Eh6ef)I`eD#4gD6@>v!}jdw_mVf1uasb?DO@;QpWJ z&-54iEB%c{L*+cAMHi1oKlh|Z7g_W_X>=E`To5rTI8SF7OlReI6v45~~Hk-|1 zPq4Y{Nj8r?#pbgGtb#3Mi`ZheggwocvSn;JTftVcRctj|!`8BO>>2hfy+!|E>)8hO z9NWk?vCZsxwuQaGwz3!5HnyGZU@x(qY!};ra@eaJq7 zeEWob%06SCL*jnHF0*P@!@gu+v9H-T>|1t)eaEh{@7WLR8oSPZWH(qX`-%O`eqq0| z-`Gv|JG;gHV7J*FR>$g@!WtkeDQA$E64!8-#e4Hip2f3yAD+Ye@_zhY-k%TPxqKiW#0T>s zd?+8r@8fxVIM3%J`2Dzl<`50cz$MOd z$$Sbg<5T$~tQqUTQdt2TNn~aaatkU>)pt$OOl@lNVw=A2I{CNV;FTN}fd-mU3#(8M zE6YeiNGL35Gdx-=EH^tW2PgckFj$EZBoa1AGt!*2fED3}-4Fv?qa}$Yaj-X9!NO<_ z%cBjfn|83bl3|IY5FhCP+oU5&Bb{Kmb%vGI1(sMhSZ;pO9d=+(SU0_4!)1|d(g!v} zU)UD+!gd`1`(+?>|6o`VL&-35AFR9Ku--?&4lICuR|tD&6y_u3Z3SfQN=Vg>kfB>3 zMYlnYZifur1t}_I=w3)sAwyq*{5${&S_K(;6y6Y|CkusS7jl0*GefRF4_W^pb3@8M zz>*=ypJi=H8Eel{pcSUEc-ERF&?T%LG{fV}137&dl79@Dz}nCrEQz&(zL>=#BXlE>&^I*|7JpM3*6>wosm-x&Muga6q#|FduYXW#tKzWM)| zeM9`chvy9)GI-Fy+yVXX?bkP_Pj*&j?_NE7boXa;>)Pd>&gq@fI;OTyPHNY-O{@60 z*p}WHPjtA$YB8HajRw6=D{CaqC~4E%n_1)z#1#dkIB#}#TXF0ig@#dgH53KhXv+Ni zZvt*{-6)*;+b{k2Wy!z&(jWY#|Ic4ii@OWy(zcDex7Qtbub0b=A)|{DLyEn{qwdcO@KLySA@99#;rxI#F_7Tx6-apO z>u}(4Y@m&|SMNZg=(X>lKga3&*N`-ziM4p$3x7jIw8(q?8s>3V%c#Z{Io9$U5hpXT zQVSPmdfk}|ix!TmYM4FR>$Z3o?h6T7IH@-MFlb!4-Z(1N@?fD$z~4f z8?X-?kr!aGneNh2m_Gh8yq-=`9xEoGA|w;n|M$}bhyXf(Q;$bXd{LF3jK)D=_Q1U0 zv73yJ+E4sRiNgb|NSry*bjCSUoSEHp=FiKEyjab?gYy;!q}V>i-rm6RqEUg_qd`v( zh^6pa0;Zc$9`8b%)t#OM81Y*-fbLT~-W|}y1!Qs6-4}og#U%^zfkiOg41QgY!T@nr zn>*c$ZbU!5y}gSX{~j$3$B6E>Z35Ye!KELP7x4E2HvFR+$)fkZS`d5hg@U#O2%<0Vz`R4m z*HFE$gFEUK;Rg)wh30^(C+I4!_rkp5l0bA(R53WM#GM!A3HXO&froqZ#ts*R1`H)s zV>rAptpMveB(LvaZ{LCWd017?aP^EhA-a=dd;eQE-n^(_Hz2uyE>`ExV^MrKerQ31 zI}z-po;6w*?%n^7F!de!t-5Qo*(hy?u%o zdI#rqQGX2yGArsaF}98LrG1C=Xxj$Dtj9htT`+K;pDq}jpLfVYhT1BJyiCY|qo(ADSr~W?bke`s*>RCx`P>;t{QKGg5e}pzl##FIj zo2BV@3~f@d&9Al%#|x_zUJ8PQVDIfN7VGo)@Y01v!v&2K7chc9gqXbDfE{nQeU!-| z0fTpJkATtJL$qgz_KaY=EZVi+9s$J1+O~OYp{2L?xA3+Eb93I}4beYMjEqjYG4Tfb z_G@4CH(y6Y18Tp;*D&<5@6ymOe0*r2;amf&YB=F9ZO~gY$tCxtNtgH~%7=cAt3SNx zi@xxFMD+aksq%V6w0zig_}jxb4@>6#(fgD3bN_y`J#+g$x_59y^q!X^qIc&+MDN-e z5&aS_-S}KYbo6s{(uUa^mTfqg3h_)w5SGTfKR;ylO>6^h$JZUP0$&MMS@OjG}0OY{O?I)$V6} z_F?QUqgwwC_UI!K(Nl9HqRX&N%#MhjfZs>b@Szd*hG?zS5G@0$QAH8aV~c2UA#J!r zZ``3X?$C@o1MaZ!+qUq`0k;cpPrS`P81eN8HX`2=ot{r+{MmiBp&B4W0=CS&oZsNQ zx}ILHrvovNx$bz~*}BVh68G1ISTg%$Mno57(|fY0+$^dg+U0W&wNmp?i_bh1HpNhy zMTS;U+210{7QM-Q+04$GZSSncvo$W#-w2CgPV&5ul1N4(VcSL|L z2*eH+pZrw~x}NhtFHGg!E|MH;^(oFHqEcc;7%VcKl*zHg+t{_qj-q z;bmoIQxk(PT3A+=m{?dw648hz^%#3NLZ(`@pe-?x;HwNjMG6*eRGd|Rr2Zs$o~nJ| zT=2(7pmvhBWAP|k^Q0n z^_Sz31z1K-&5#9Lz?5*KT z;BpNjJ>TH70#S5=Xm|*3PM%>oWIC%v{AUNw;>BhlN`FA?(R{>}%8?}yuZIzp`uEpj z_1qKa@6VT}vhI6gZTJDB1Yc!{aZUg8^ijH#51~6*bKp}{j)<4~OHHM66p^&uh_L@g z=kn$azW~RNAlrXS4%%p1)AGAov`)-3BAwvM)mwhgw!wkvj*y{&zKeXIQ^M;pguj(43_ z=O*VRSA?s;b;xxk?B1}a!cK%+!VAM!hkqH-KB6?@SmYCtH>2*0S{`-1nWkA$v(l_qCWAEk$>Ze%R77}TK$k9B}63@BwR@NzBOwd*}7xvA*~;3eZ6%1~#_d9lrFZS`%-+pcN5yY1_3KW$svu6w)T?IyRI-)>X8 zSKFOwcRfi;ic0E|G$?6&QhCyvq}@qxBvmJUm)t+OB>C~=mB}w9pGf{N`TJz0y|aB{ z`yTCwx1ZX6QTr|JtJOt$zOlZ?eLH;LcIew- zbcY!omUY;kDy23{^`+*dj!Jzbby4c3)Po&u9Ut$wvg1n~PjvjK;TK}{iX+L(- zbc*Wa>(r;y=uVGyI+xxjeN_6i^rzGJq`#GZDgD>ZhR&YOX`ORA7j}NM^Wx4gbUxJi zT<34^Nxo<0Jv;9?anHy1{MbeA(yU8rm;PPGbt&(%qRXx>uXp*ROKn%VYjoF+UHf$% z({)DIWnH&*{is_~x6*DKy1mlv-EP(0Zf1mJcr)(HSd?)nv}}?=+t9ikJ29HJ=XNt)#H^OM|ynMb7IeFJPPyG?6>`1>E5h+m)`qM|JMC44Dby>_31Yq=~pJhxqL zR_@;1w+7k=Mh)~1>@u*|z@vk7g9-*s9kgiB8-xBeSU=c0IAZYZ!3%~shfE#v=8#K6 z(}pe?x_anyLth;F^3Yd@9vk}RupYy5h7B4vf7sFc=zRtEZMyG9UYoqf^S&FNHGIJE zZTXt~w)ugiG2MjJ-EN6#2NXLQBrEu(jii5xR&%=9r&kJ&ori(*T0=i))d zT{Lc@Jd*IT8xetE*(13>x4?q0yBM+Z?SecMIVZwy%6K+p@eBzEt zbW+r$>`D74eK)!L;FePouqfC>kFG~=-u%V%t#aeT%{GwL22{Md6dBWA9eS^xO($6uahofR?5 zGb>@%L$emo+B)m#tP8Wg|HnVdS^2Q?-Ls=+FPJ0GS^vbqCw`babndw)2R`}byw{%E z^3=|!_RkNUKYacx3v3J8Ea<)9YQ?gJ%@(d-^yK1UOCpzi_H^5)r$7D2(uAe?OBXIZ zx~zD4=<@k1Tq{afoLHH>^5n{2SH-QGwd&&P&a2n1-nshtnus-pYu;X)xOU;%pVnop zTe$AbGtOs*KC}3lZ=TJ0_P6yr*T1&@{D#mC85^=TY<#ZebE`J$HZI!u#wM~UYtxEN zS2t&Fp0)YJ^Ie`lw58{ke{K0-%MUNm7fN4vdu#00Nn77|(fMM*i<@5jVOy7NpKt%i z_NTUQ+>Ii+%8<<`ohm6t0U z4muAe9_(>2@8HCP^A2u2Sb6Z=!K+oQDzd6WRlll-tCm!4tvXzFuIfsaa>#Kg@lf|e z`G=+)T72lmL$4kB@X(FJ+QW&5`yL*B_>sd)4sSVp`0)9|R}U*koJZOm>2W0Q$iyS_ zjy!i{|B-(lsXlV+sQGBz(e$IaN5>tVb#&#?okvd`{pjfRWB)jI>NV$U<6ist_<-Z< zj@O*H_rz-_emdFgWY)>yCm(`BWTFOBGC-qq;$PE8S<6Q-94pTuXYiAgO^Wuzqe zXi|aC>cdC-WV^@eNyB!M_o+Kr%4XEh*HqrlDV4rO!tYAMSL_?LKO^bjZ-z2bc?~ld zLPC>7qK`QxDoa#auiL@UZAMK&fi*p;z-puENxqtt^z`=0$fEmriqqkZN$tS4&hTBH zTwY#IH%j4mdM#SK7{xM-Hs{-Tpb_SF{$|oyE#0i81GF%~-AH*Z!HW?*@ zeWydBBti<;?37(CnrkIFY*%=+)8O#4T*fR0haApWxa=@kl;7&e_DAJLv8V)%#yx?AEDPBjaxO#)32RYij`Qlno4aN1 zw3!Pn6D{QyZn2onN#+c5p;jcsS&j2^MUSCQrahjKAK*!PH$>Ve5%W5jf+d|&@nC5=X8Z>*96*>jymIbUQSA+LoHunRb}C>45&#akjO#?KW;Zz*|+eIM}i> zJR(eXhKHbV$5JV4Nk+}DH5uUDUu$SmO~J1<1(pvIYYJ4FO)N+Rs)2U2wog`lIN`>{ z2sHXqTuz4^pOV_a8{>3P3Nra`?cTYYH&)Eq^4x+&iO*##4FOtN9tH1G^t?_Ys2^1Mc zAc3?ks~T$k$tG*Iza{O^lD5pUx3J)7Knr?L3o5tBig4SL?d(Lvxd>*Dut%6?pim=A z64+{{w`EI`R-2TNZSor|*``bx<-)@#OQSSO#1zturfhW(ohR3or>A*wv{QUuJWD`X zkd+3(aG6oOF#t}y#JNjqGtlVLIfXdPP=#Swx=M*EcPC<(CMDKD^!o4>L~}ubrKYf; zAkhN(nFtZ!vx2xG+-S!%pRBce<7Kak+O$9MuIUJRjq}EUb}1DE>`P(!G$PAWl{)MD zPv-9V@z^KjyI(l|%8o-y@l#{Q47_g)U8x*9{Zzqbu2Z(oSpNM>%B5|GKRhz`RLP00 zt9I{NeY*RAX*oIf4g> z5|~~3Q}Bwb;+3O(E3VQD4J2zcXfpEJXkEE(sgCR9KTxifks%mYAOX~cPJF~_p^xjR~FMzERw-}r!)aQZ)@tA*IIOwbhFW=&WLleMiymYqG!>m z&}}v7S#%og{wivc75@o(OgT!+Py!*-Y0BFA@9V!t&tx8(CS@bGU?MI3&R?N=GW79O8olc}nqLg_zUkN;S=x3#(Ih~&< zJCtb?Pc~By7ts>s*&>?R?Bql^>=%v#Onuc7mlnQKG|B&Ai#Wp1OQnl!^75g{kYSLHus zNnS^vnIz4Y&Pml$t)x+j-K-B0#IEBTqva%c!X&BSx~i-b3+e@j(=eHPZE2iY(ks^W z^HMpyS~*X93Jjq#?mQ152Ed8iZ<~#BF1$2u6xE=t=MX&xF@hx(SVuRh9w%+iR?_o3 zcHqjh4K++bm9>^M_nX<;WI2GLWu2aEkamEMQ~(ODVEP4-pOp#g1s4FYm5>_gkQ#ba40ZI|LMNWn zQC*mQB0(jVo1;KWNPrN?OKvICXboj3C<4=BB8ejlYM@j=K$;k4wRlo&R!gk-U|w-- zW5wTGqvyZ7t|YEpxNzn2`STs9BcH%(m08Nldh>de6Lv*8V1#m2Ii84hZqhD5kZDD#3*U?GU}N!GTuv9(ShNGx@({8@mf2i$y#kZ^|6})UHqVx zqiFdWzWlKpiJ3EIA|{5OH^Rzkt2qsAGt}RFS=i>VKo}1TlP5MnJo(M`Y-_|t*Eg=; zTpZftJAW8xz!gFe@MWltH0sMtTIQNcF?dZ%Mh$EgEMrPaVu9t0L;(br)8j#vV^H2` z;~V9^mO4FB+q%hg18aC4=V&P!QKMY0-snX)#~&m)z~053#e1FIwX&(^4(ZG7)>ev20p8# zWR?g%k<-+N!19lcs4`plD%_^BTW7e9t zUR;PE9z(SlkxDe;P68Vl<`36e^yX}%mQTR_T7HW?8x}2Nc85)h;KyJQ7*ndd{FmhnMK+{sM)oTUXLEIi|2fJ6+QmN!(p#FZg z?&w8jW~jbpM`bL{7RK8q{!v{rEe=pp(!YMQ!1Qhv)0Lp7LH_oket-}fN;DHUIrci3 zBhq9x8}$ZM>n%f&E`VY?y|xS(=4CW2!Zg(gAyNYr1EDplk02~67y!UA08DJ3oCZ5e zAT>rCZ--pspa;q6ki0Rwmwilgl^w&M&QD|e>#xN>Sn@vQ%C$Sy_v|i0aco>oZ0!~nXi>UP}SCf=huZS->{{0-KBuQFe13p zJ>X@TWcib4$Q3fnlJ7%7og5~|%N)vr>1a5rhB?*f2&zu2Q8_9x4V#K{V(A6M1(q`@ zs>KQpD=6>?QSYR*Kl9a__-@<-XxX;>_Ggf`8-S>v*+F1T_Yo{aL4q+M=4`Da%)!#5hewZ(o)Imzj;7HDf;EdM zGi$wNnxN2w$pPCWQCKICeP;j~ToX$TtQOTVQ9Ti?v}%f2V(+pVK@|^5(0retz~ar3+SEe*V~NTfR*j zw|DFV4~)&9_0f!f)y{n+e^JiA(@6hAgn}9zDw%|UK8}Mvye>EvG(?bz9g_|LndtRq z{s?s-VPh7yZ6hrUCJT!6lpq~zK*uRIaF%LX*?cL2L}IwGq#8{ts_QvMkVw%7uY*KB zr?h^~cq&L_^Ss$lvkjtRJZ0y#b6-=PvQs%3leYdS z16yNCmW!bIs^wZ(Dze3@TOYDRT92aEjO$H0(05%ZvPLav|5F>nVHPi`WD#C|o03c!@CX_QZBqRO*Heao zgE=4(!5XBXAQn~jU=7JvH-c&x93QfJ zwNkPMsffGhTK!pjiS#_?n_Ls-}mU7qb2v$arD5!8`sB zO)tw%r?!zc==uB0o*2CP$vtm&KmW;xcOG2&Xpd}=3Edbwea)azQ;Y8}%YSCnsjc(2 zJ#^ng`L?Z%5groVkR$DZyljV>>!tpDR|neR0*ue_PPEenld*-VnM^-0(IOL#Fj2`w zWs_`bskc-6`>i|65j5icme!6JQ3BuoqCNv|)>3|!U*?)*yt%79W(<1G+fB49w_)mlCj(E+s;t8Pt4dqE1~2f|ow6aml`VH{I+_)?n8JmO19 zbIM*fL<8|aKscaDI5Z37oG-=Bqote;(-*(Kv0|EwWfy;O^vin6Z@l{A#@Ce(m3^p+ zcHg22v!~4N*RlQZ!t%K$y8OWTz?u3ar6?|18^C>EF4{$zt?X0YQFis8Hwd?gOrcBY zS!KHN@)hMOt8^Y&Sw}lzwLM^$-I}AIZWGzzH!u^|QF0I@CEU}|aC5U{8Yjbc2a%ys z1EqsTSR4r&8m^&wG#HIip15h9wkA{$vSCE4wcN*P7N@bC%D5SUafuZgEeP5eE%11o z8>vxaGHJL3BPSyTjx4w_F%hP*PjIU6+{Cvny=!nMu|Pde6b>!^U^I%j9Bz@JJT6{_ zqjYVV;#~0>{pu9`MwvM;KFkrhjJ~Pdqd9uJ7j8k>@p#FYAqv8E9Na{t$)FVz?AaEu zU{dTO9NLyzrj;a9vk?ZjIU=8!C^1<~wLpYP8(y@@OiRtwY$g#!CRR}I_HA1=mEN{w;>iz;w86S&hs>$LGlhK|r!4f(3P zwcws9jvFe9C^r;|B~{%Vff`_@eKLH^AeD2gYTeC;yy;3uDJzuiQ;L{FvBMjGN_kmX ztIXDf-Kk(bSqITA?n#Cms)Q%&_s8mV5cz(aE1QJMhWuJcSV&oYVW}WXgQk#iL!ofm zRQ|-wh3$@YIg^+I3yf;5l{}|@5*uH?mMzm%ZdJN$slSEse#LlQF`k~> z=XYVe%bcEo3W3p@5A6cU&QS((!taJh7aTcBE|hP`4e*Bj7H2lxcmao)z7P_y2m~0g z3jl^1xlV2me@g|y>7jcL^FH;H1q^_ozHTeVe*`O>i4}$o=Z_^?SAGbKw2dGL7laok z;SLanBAD=OLLBD8P=n+sl*CfQ0#U~jGX}O(a0IF2vHmGo)CE_)%rv<9o9VVwHOg(} z6WWV5JMnDxil2wB}Yl3X;OHUf9BB7B-pa2C1;Cz50tUf98 zNd3VhM_8XDY-jy2gx1%wQZZT$81uy1hV15g0zLh0uIN7gqKpW zW##jS4=Y!$e-gi~+oqNLx4O`e8_+kR4623-A@3fH3+Wh=8Ny*z*7_^3p0^D26T?*l zd&fWz8R!lJtuRo7F2s^O1JOV|jnGqr9{dP{L$JIK_V#x$$1O%zb{4)v2v&kDu#6-lIE`E3L5D& zsguB7QYYd2K&=Tg35I*32rdc}zVXZBrCN0*(;&R0Jr|U2iw_^3LEk)I|2sQ8rM?R5 z8M_1i##}&h74weJx5tLmJTreEKF;|Z; z$er7@+XQt?Mql@%FFUF9hx~4*m3F$;zTM930->>?*6esY%AZ_zcGdWYkr~~guI$c6 zsy9X$6O8;@-Ax@+gW>n0Jyl0#ol6&|<6wU{0P9eUg17T(?G3c_&ZWaXW`kE1{k{h=m1t5#dY7;IczR zk2&`T5%ty&)sNNl4tna;$LbmKDTsQ6XXikOKS23C6y8K@%Fs$pcg$A3e1~YOwY6HV zHT7Y`5o*)%Ov5k(GiV#9lHn_8nn-XOjT1@4sy9N9kP*mU>h)3mQJrn~Mb<+$?U4>E zKP;}h0;v1Zq_NyBtjQseYBSX+nH|wjN9YKx(>5X+w~rwYRwzk^Laby^UkLdHmePm- zfT}OzgE282v(ox&%mtZmRjxI>{QL_qDTp@w!hTd{KxwR1roTXAaQkc$ZC-z%e!mzM zj{dy9TNQ()1R+K2wLY)G|W$+g;hRD?}hx z1a3DY7J>L$QAh}N0J8?6mEjctw=kL-nIlomLx>o-1uA8MFB*|;(NHf{(T#YDmp*cY zj%7OKGF|eSvgMntyS8lJzlq&nj|6}+N~swS4SN5^CzmaGTyVw`P+A7`XEatk+G5e< z2ck|OLFjSj8wnvWIh`64FKS`87n+2tqFV9*2<{*VPdICh@h5~F;zcg6C2V$BOKy?D zLoyEn-o50)X*zPrN9SIpwECMP{*&94&*r{&^F`%{2Icqm`-jz*PP(_x=`DNS?7y}D z`I5)8@{X)L@fjd10d9+dTP^A0ZwWggpP!?+S(~ne0sAz3&oLAV4F(2-P$`5rshSYN zf@{)cZ~gSTuwp=tP-Gr<>WDIuD@vipwsotR`7F#lS5pP6Hs0?F&9BCd){I*8`NA_a z!cGY0wi`(aQx&9*V6)o_@d{qETczB(UzO&EA<5%4nyR{fN}Y0zHRF5g?nhc+9v9Y0 z&`%H%=4brj<52GjWvl~PCvY0hsh-n=P)EXNxCf1KjE2EuWq8sS{SH68f^#~Zl#RPu z*`H1VLep8A`!p;Tx6x}{!mEd5uJxOYh{z$-1Vs-GuTl@(*n-5MbI|A;1YHB48r^D= zO`stkh{s1=VI9->H*YIpN0f*+XnaCabhlvCzHU_c+2yAM#vn?O@v9^ebc}yULPUB5 z(?x_wuy`kRI+60CBBmAZ;Bl6Y7M5U0H?USRjgYAhz7Xrkn3jbxmTfJy?yy!_r37ob zm07P?ez&lk%-?KH8PNVa&M&ehC5#Xg) z#Y4e9CTu78kUc}_bksdU72y;K{myX9z}_`{VqixMbb(=qfsHrJFt8B@ngd=Or{AtW zsONF|j`~bEt5VCb4q>apwuVWP3|FO<1TTg@$okE7+12pjHm&3D@bksFF5(=#)i@{w^&B!S32*>( zAWcaRT<^uGBvgwaEaI(39r7v$loC)RW(CWJrDTMO93Fz&YTgKm4tyi43(9lKieqqJ^WVlT(EX1q`D|wWJUj*9aQ%6fRF7xPsl2!o zGuM$<4-p+8Zy9RI7IqyA)6r5oog!UJ;U6Z@bjre!GsPX?3{OwG^$K_sOm@qkBZ9bl zwGCP}T%;p|#-#`(bPU2qhvynFuGNa);1PFBlHj}-B1@_ZI)FhhK;*Yn%1u&L z46H8XJJcY!M=GvkJfg0SU#z>r+b);Nw=KUj2ffh^$p7wErL@oQmel_B@=xV(ijL#y z7ni9>HB-%R?3Vl+{iDfdQS;2A&Ivx3>f0f_j`AR78_ida%C}eFZVx#BmStq<1jv(^ zO~exZ%rc5D1QpCDvth;v=fsH>l<`zOVLLNIf0O@U zziDnYfh8sn*Avzhz(ShWLp=a!o2XsdqdB|!4;fHRWU1U;vSASN7HI0RiqwG09sSVMq2k?ts=HCvQr%IhqaZ>TF~m+PS_XhW@X zRQjwzRR7qJE!9wZn2{tnP5?|GE7c=?cE>6Gpd3Z{H+=C#Z$r#^PFEp1oEyu45`MkJa6~W%dh)sB-$(m9J*JapbGh2e!Pi^_`V_*Ny7C zdp+%E(e}PJsG?}kiFyl*(CQwXu>XZsfOI1u?S*;(Q4!VI9}}K^!_;76rWVjI_AJ5! zAaLr+wYqeXxkd}h>jad4MRigTTU3>JtXC^sX@^#%qJrsTkzx>5VT??Ngv8FP)af4l z=-qF=edlc1qIJ}w{J8$9MT<~7uwdZwt;$8^SLJ8r0=ws{lXzmx#-oDbMRpHV0h>J0 z4`X&I+#9DRn;-zj2U43wuN@fT0*ygQ1OpCd3R1*!3Ns0#rrZ_Klw!NBc~n_K$3M6A zsZ&aW@-^&D?S9F-FJkV`(S5S`y0yYl#fbT6OsrYCPe0WhPk+saa89FsOBAcj5 z4KACBF)UYap;5UUnxk>qQq)Qhfeo=@u_D+i66i48d~w1l_i~XxQbFs;=jbM%7q~bx zH6)~RrFYRf1);Td^Hy%hvv)%9*8DucmJN(pi3|C- zHuh|d85SlZC`-#G@VDWLyWwZjT(d3O#Gi!74mim%&d? z@D!cg<6YXUxD2ryPD&JqR03?Z#B)(PlG*;G4pu8`sc$Al$7j+)>9TY~YJg?Z$ru?K zot)ts;3`DnfGaU`cJ#97&CxtsNVev(K0CUZ6cam0t8JGs0Jgxu(9jr5N`HG4gWHRE zu_%3llP03D!jn*=Y?#MM%;6-60YNa7IVGLMY@AvVjrGRF3zii{Wnc}M_M+A)O|91x zarveyGf`^haf4!{k~g|vd@U`y`1vDys_IXF`c-Ywyx}Dm-yG(D_Hs=P?S1rHBzYDU zOF5IHhR%NexZLU9AniD|Lo(SD`*mQAwFn|2DWhW!Vm8Vm%(m%5aAek$kcV7K07a zzL|-IX2Ig)!;s~)Iqadf{uZacztOB23{MFuLpVpskfF}DAS@U~6L~|RF|~sop){+; z2?}8|9>_?1(5(D|M@ALZt)O|bX-enxvMKeuoipoti@+Mjov%3fFpR5(R8IH1Ejrnh z#g^GOBVJ>V2p1V;W3Jv6W$te?OX}F)U~E;ks3i*++$!RkO$nmLXq$jRfWxjl_}~MI z;i>hH%vJ7Z`Cp#d3K+`Drrb(+Hh#)jDcw2qPWJ<J@#88AdiIGTJqGbk+ z6VK5BH-QMPK2;Wp3S70+BFQIQby7fK^a%G>gvlWCf-y5r%jeTYUnn+axTp-9bKn5H zjCHg^iLGBwZw*rNWk-ES1vyRJuS6sidm$#>)*r5svUIdSPX~xv1>E;9^_QJ^k}Ov2 zuk}*Hp1{~&%j8ggRaa;^&C|?tK6ZPix-{tfe)L@iUUicP{kFA?6I#x%A>1diR z3(7KUk)A##hO&~ZW$w-H6Yg_v$?T@?7>6axZ_NeaMmnrgNN%$*iw#jFm0UruSTvO> zo8n->T#0J?3AJj4L`ISe1Z-*i_Js)rrhd4bR(?LU+kFF`pEV?VOL>%`=Tk4F$o-bi zp2|+Gn6m9u{T4yrn{L#JOMTUkz6n8o&YwlebEP>T+E z`~SvPe{q$7<4>kq8TB`&5`(HN#Yh?SLLNpGmAEl}n<-oGw87e;+>$F>LUN%k#Hv8- z!=Mm$Sfi*H0zY0TBy4Q-$I4Y|{`OPqQhuza9g(X$?Es-jc&J>m@=qwu-<30K@kF=H zN|ACuxM?G#YcGsx!!xP6`Qsw8&8BGB4bcuNWf2(XZp}H3q}7lxVLL>@c96|d)LpiN zkRlKxlL1ex7pR5|QL)}=JBUh80h($&Kt)FBCVX(W@vv^*qB$NVQSJyNG#L-Y(3Qe^ zK)?-p9PlMI!q>$gOLcax$yz3DhFK;wxv5%Y)l331mlQ<-rA1{Q7+_5aD`@gC5DE3A zsiD!dzcjl2E=@i|7qzl7BqXTLg=rJi(d#$-smc*R2fce$8fov3 zS_YyaHlsEx3F%HDhO{tn%y781LOp_pg9&U^FN!=aESwpblY+Mnl%eAQqL0FjS@*hRQV-8EcJ_8jQ-NEnN0o zs|jTqLLmorSz|!zKjTq?M+6v6@hAwu()`{;dFXIy^stzBIzE3S>Lys+r|4{x>K zHf&4!5dVG4$1GT%vpRcT*FN3vUH#CSU4U$nfJ`$HR6E?C7GlZL=rwM*fZ8NYhNfJz zRC88yS%XX#3M(8=lSz0#dy)8Z%I5w?;V|2B2@e`JYB4-TZYw28mDPV*5{>yrWIR)2 z5#bhI5zJ*?_rzn$8s#@?ymvgURB}!ftXb%$d2H6m_B2}gtfGGIDZ$5p4);_-MA7q{pF3nKD$bsfc`G?v&XY@JNh8KEi19Qu4s;<7TVqH>4TyRP z5qLw|#Fni?xjb@EW)?vltBhNX2aMb(G;A`0-Rm8@97i17;l{p^IULN$wPBWU8m`ki z@R)o$1eU2$4#Nr)Xf+Xr5?WORoDfg}@){#h!J7u)-ikk1Lr|@vN&Kms`XvrTvxg(# zgg+5}@^wr@!lm(>^R{z)$=&B4yS!y|Oqd)UJMUz9Vz?aLykuhy8$xrG{eqS2YYv}1 z^fK#F|Jtb+eqPI>u@n>;D%6X7PPeAVa>C<0c5(V-%QCKd`L;N2Ko68^fED$2C8 z@Ws4ml}G4vXP{=@J{JrE}nO9zH%TqtDsVZ5tmUs~Frqf{P*GRU4_k=UO5pBpx)TTan~tvh3- zro1rX*^O$8JXX^3&EB2IvIR}9Hfw}q{$U&0gXXRv2x@m>`x>dp(S)gW3Ua@P@L zv_Hc^ehP8vgCQGPZz<%|kEM>P*4OG;G$_EO|LumM!N5K-P_rS)u-9KRZ50~-rA1rig^mR6LNq`Fg4LheLh0?`1c%gL@zTBhVE zd*~oqxopzatCoR%*%}$op6!2Z{V{qkjh0ulz5|s5XA?pa&H`?f|2tR!b|(JM0BV4C z4gj3^4+XF+RijoYWO0wc>eaI27FsF!3iG_C&a=qhO%w4`C@;4!6-K@OhPlDaEC?7x zIdg-iDkh{hej>_flFWO}$8i^y+2H!k`G@{DLoj5e+K7MFTnFnV3WBqw9nw12A3Iv?6^U_ZKAM%BtIn60v3sgc*9 z4N$LRIjH5!hjvNwN9yfjBE)8SSiMmDC#4~dP&q}!rfL~EG(s3{tD;H2R}!Pd+=BZ%HEFRc1E5psxr6UxgtPSV>8Ha zg^~XLaAL}Ix~<8u!L4?-6hKF4vk8Lw!hyD-LdCAhB~GVHYt;`lnao0CqvRSN!nX>R z;Hs3Q(h-;qc7?F~L;y#N8`@feno@o2%9ag{L7ZoHJhrbw=}-4pXySP%#BfF{4|d&j z4}a%OZ#?Js$DG}OZyNY*nC4yF4>`!+UN%g0*>pCYnS?fXi1?A-@raz{EOeGTmpb=4 zk2^0rwN7UUFQbuKOUP6+ieA8V!IEnLC8U}fZA4XF5JuJV5yk{igwNEDsi`Qvw{{S= zSbUEqb1%~w%KXLbTAk;ex8C~X)f1W-%d&4OpHy6UqyM&N+y8K}g7(_+E^O32w7C>5 zEdrGBWTf8^yNg5yBC8{Lq#Ala{VyUDyH14A0U?DU6H%v;&}e zg*ert7d{FfouX`9Ts(H^(ABRq~+&IBuIf1(=*|-pD0cnMVg=@`KRC~Z= zFv<_?z1~v2QZbWRu^-%=T#eCObFTO?GOuxhRVKMMfZ44+$-;2A9N#8c;xf2n(8$ z4zm#+a*~k!5O6}*Cn5X<)rCqEp|5aTs(7o>C`5}>(SmG2{&A(eR(YScQ{LaNT%c{0 z3*RgAPKew=J*n7Oq1>i2zBptQyGy2NiN|kY@=h*p`-M*Ca!|I3F$JXwVJak?h!_ef zC*&Lwq7ik!2(RYXhMW8o#Mt6V3Yq0k6h@8%RD5Ls4JbYqua(SNzGk_7AqY2@2G@n4anMsI`%4)QU$0i)=+GtQ_Cq$~e>ZdF1O`TW2C`BBJLxpnK-x#ync zJ?~lQaQJM}3fD-$qUS1Wm1mW`i25O$fMxzxWD)ROA_Hy4bh0~QI~(ik>)Ap4V>vWw z^5jYMmm-Sji=(^=t>=W^J4@4)mcJ*v zS9U|%+_YtBvO6s!jn`*S&z_epa|B$01W3!4TyLoX|62e>k$2t++NB66{RNsAU|!?f zz7n{}%m6Nme_62v=Ut#DB{)Pz)uj10)DWBwJ_-Ep7wRwRpX&e6cd+wW)^Wt*+KwOB zf!$^Qx&D^jfBR_Xyx*O7)1|ZSIyKSqwmwCFQvZ`ajXlh+V3)JiCzrCzzySXnb{W9u z`|;mKcH@HLpa18*pN7sI_|(Jt%e3}ERF^G91#l4f)yjBYCbJ*e6<|eyxpexb9P#$I zG{OJKJZ872dR(9RK4Gb!$>7g=4oy+Ir8*$>wDUyZoRMN8cy?!^17|GWrjh0-m9w&^ ztp8-=&N-{5FYI&gqb&F5Tke=Lb&i}dbHO{ePF5|Bg(Wwg^PN77mGc1?*WNTPNW12B zX@;W8Zz8+o#ytBvzP5hjL^`1!c8^yE*?wG+cz<3m@FFhDcQ*E2Oi~@P{Jj)K8a4IX zVwB>iKxk5vl#!WGOu3%`i^u^h%QHT_&Ps3l?z`Lcx3PYuw|)C9J_BF%V>SAEeSHmk zB<=L4q#H$DB$$UR(pg*NjSyYo%Iu1}p%ls9ei~UQP-deJ6QaOKnTxoMfTffwB@eZo zlrxfFviU39+dHZiQR1jU(O;L)FGHS6=jgk!7BM!%?p{fi2+YC;Ur?55Ze$|3(ceN7W|mbMFgCDFcLr zjmhXF5Glf=r<}@hzjXx6DY?Ovf%+1@SSeb-hxbc-Vu2UAI}W>wemm(xqxw#1c(RE3FL< z3~@ZN((F*z>Ro+~{0Q%?;MGrx>Jm1dH^~i_*AbJrBwi8;#-te#D0^ALYTl1cNWR5@&)xj*5-&)CO?Pec(6tU+-Rd^Q6xg_($&j?VNbpzqdf zxgq)O_J;EsMqOHS+k%;QRm^W>*Yl=HZ_d1~Y{rPOlkb>v!9DZu!G0Udm&rAlRi<=z ze59lWjzlt8Mh4e3tLuoDXYrA|4!s|ip?8B7n46Ro$y#rn4%DLLJ$6!KUux`0jWuY@ zsih&>t2rVx=Sb+Y)K46r5tQf!d}*^B#xYw6WlxhQQ^WM8$hE^m;Ctprh@6=#GLF(* zs_g8N_zm*MnjiZ8f-yHucxXjc#q6spYcFV+d*eLiyn+?C&MW@y`HSaFncGk?cEXJl z!8_6;qpe!ev;xH>`~fd8<7R0zl+004lZ8TjnBBQ--NeL))0<`~|5^BC=;=k!SuOCv zqwruu(s^;sVX0h(KxM=$`71jteX6Jk_)!3saEI;4(1@r28PW#uT%?T1w&{q7~2 zska=*=|Xl*9#FhFmSPK{6+z05IM^CVbHp9qDu=_1`eQ!I16?Z>AzMdlOd1smRrq-V zm>`N!a|x&J(*~AgD}!deJL|m5^a+Q)hQ#p%jI*RjD4xcCKVBCu}pvu0QnZ5ix3NJR6|M%29=NnmYu^kWfwiXY1|!UP5Q?< zdd3av_~8Z3Gx8eW!JQj$%Drc40d_7s?sYi$5#T?ZF8;Af13_- zR;o|c|8ncM-`>gwa*uvp4f-LDuhFkgJN+p-N`;{{0WjwU(ro=tc%%8~F(IKE@LX1w zyb=-j0-5`P5<2c@NBnG_pUw3%4Vg|LW!MpkHA`qH!Qyz+KA{du%@3tgd1)y|hxefD zF-L#U7=0&3mu_XX$*X`y>c_Pdeq3WmG`3G;yMXS~5dH+1;aN9Z2B5fko38huTbQ?* zK)1nNLb%I2me=tNx9K~LyObKwP=jX}9PcIbe0qj_b|jz8%V!$=3HG0C_E|Q2KbyUl z&6G}YrV*YqrPwKbB!==5FEscv0%C_0mm4bJObMIPsdsM~etz4VRB-HMCBQYoy zn-uhq>K|c|R06&;BSHbb5Rw|wnr1SDB2cu0k0IVjf@DT4sNRW;MR*{CBBotTr$Q-T zhYeV8<;?kG9=iL5mxq4%_MsEkFT4GGGpdny`$J={y7jsVH`gwow)=@isOr1EHh`7E z9#uA3XYhQW2x#3eY=0h|Kte6tYstrX{(K8^#nwDlSSsQFGh9Ct9Xm%$fw+^0@C%c? z{$IPAU5tAeSJUuP=uBgmcFcv1hV|EFE_#a=J;UgQ9oM6;7L6Wlm3hFDFJt!YEg|za zX!>2|ub981LOADu4J%dV->0&}sVtGo;;Af_$~5DR8Kd}9jQf_FLJavT#k2j0$*akAwr}&Jhco2uMCY<>QE@S42_xE5ocviCu;R9HYuc_ zpht7pIo4`>fxLGx&7nCw0ehV)d+I=IC8{7P#Y=cls^La}o?h9BpM=a)y4meiIulPtkKJ9mGCvyS;6iDB3eCve+B^Nxa?pI0I4lhSkZ( zTB_2W3BdkZS?_R;>J&nNYec1(kQiWKgv1~w2#H}XOFl5RO)Xv*le$Pu&+BJO<%SF} zKYpRW<^8p*Au+k;)ik`*f2OfX0*tv#L(XQj6p15-uR*|=gb0b4OXvGP3ODylG5fR3 z*+1BI_A7hNzUTGm(bi@5cl4NjkE>71yI367WA?_?G<#z%({S2!ojvb9dsE`5D$oW0 zygGiCCWXe?qaJ^)0%0UY3|wHyDN8U6{T1(cN7IF}tcF^kian=+1P zS&CqarUg=iN;soVl3jMi%6x%vodW?V5o|+>jA-yMLjrn|&Y~|7cPuQ-qrfc1z(u@P zM0#XKVeueiINAKZ0jzZV;#s%x@V4KMUp!|9Dv@5kfy;?|^k?~^y9-<*1W!z z)${MBuBzGdlHNk4N$e4M*u-SZ`#imE*I0%!rT6H}5)~Ul&IX%uwq3{>!yyEXwH;@i z+Ep%lUO!VBVMqeQ8OKI={l9i~mpxCz%aUeKA?>`bu~{^7Ax=9y2tW|<1x7HP z*x_Z14vf2c_OB6TZ(qK70vYy^)$;+{YJKoM2 zuAVtY!f6F;04`7Du$eh|;&Pa+hPBmWbapXdHFP}N-vie+Bn0uCS7nm_!?_)XC@q5xVmn7xJK_!sygDy+-X7S#ve{a^W_vzp4 zluu)hjUB(s67V5$0?Tw$naA=9jTJDihofM6|dg4DJG^mG-MtkHn70c&x84A?4=U(t`aH;b=4?T;PxsE{lz@Je1%lho6WK zFqe(PO#sWmBT4o%z9Uk8ozVqK6ZwI&4U-8?p=E=VPs_{87D*yt&V_kBu#`KNTtB63 z!Tm3tQ?qXICS8-~O>MaI`bD2ioch{~rKtHhpPf6Za#(H46^G)3Mo-}@1^#^VX8m6u z-Mnkdh;`M+jy=7GaOq3eKdOIc_3gW~?vD>Z3g8GA|Uubz3cmPo#G)6Zi z)TnK!P;IS~mI9;jbb&*M9VXe&S#Mvwyq(4;EX~ z2)-NTAAekZ%Yw@M*%dYS-h7+>vEC20w68Je=U*}9LA^=e^yX{x$?9*ynbA*ZjZyTb z*l5*Qdmq-`;!m@BySyiX#1wJ~5u>;IcOjQSA(w|>vB~ydxq2r23Gx+FarvlVjRbdV`+r+f&FedL)GFx& zBE_5F)l<~x()ge_p+-=^?D4A!LX?1(X;T)Wi))dGb3H3*ac#P`Tx-&rwc`}uwJFa^ zwx{jLa2);UsP+~-dow2FE1_sEVH`U$afm2e%+L9?fK%%myChSqX<5m?0ZD+9C;*9sj?YYe*BD78?pEx|?i7p(AWI9JOrLhy`PoFvr*P zZonst^?!dke-2xDLG9!B@iIUdCOm#$_U&U9JjQG&tLRsTPaoBFFrK{6dh_MEd*5qe zJCZZ9_rJHEWD=)DKOtub!jYUkFZQ@!XpiSxLVi{2B4<6XCjAFFV|c@Cv_JG~*NQWh zuBD-EDQ6g0=ni8R)8J zQWN-M#CnMhZb-aWYSs6ab{Nz#r!NpvJe88S*$W(@&l;cujI;%zi#u?|D8xaDl2MwpYN6cPi7Q@9Kx3Pv4}4Hx(}^&~ zI}lGJp5AzxX~Oz|Zw-ylnJpvRc%IIuCrfpc`U>`$h$XR0um-}P^9g^hy~V3_i{A*# z!P0>1h3&*H`PtaRy)b-APHs2LNsMiccaB}to;1cr5CMBQ*%Is?OESj(u5;{~AC0l| zFm|}0yH%F0mnl0eFLjPRiY)^T=95d=LUaCCNJWg77tqs0kMGq-|QFc-hk z3zdEI`m*VLS$$s?>&vvhOrrn$cKoXO+k#z4So9QSu>vIWgXv$S!=nF7IBEu43>#1& zk%UZJ26HmfMO6$!hfk)1Mo1XH^C$SvE)$}AP8)=R# zc4=z(3?oxq(inM!w5H3*w`3XcwpjfF@$N>n|BR74 z;{qSIq-auC%VcExHz z#NdSd(*yX_sJnX`;}GvP(BPUX0pP8qRYpR~qfJpBEy(UHze~|Zh5$8lWhErAKg3XJ z4*Xm$YVlGH9|%@0m3^4TE~V^?ivi`Qv~!QLJYac%<_VRAka9j#dEUNTTrPbfo89{8 zqa8(h4=)0GI|gvI!gAOCF88s;t*whs6|yf1{=QYeNxyvqt+$BjiJjhCtl=e+L#!e5 z;I(gU|DnZ&{6rV26n3WA>B4qomjsR77{zW3L{hrhvPQg+cDgZkjg(=&dGdEHzU~n~ zV`SRr#>h3M1xpr&H@&+BYmA)QIr2!v7E6VkP;|=a2N&5d=1kIRj64z=fNU31evyo5 z_c=o!fIX{otZQku5J`-aAj7M5FbV~0rL4}#%@$W_aEgTh@`%ov;AoH2HdbT!6C`v69IP0M6bCYzRN+~Kso z5%;jr8#L}w12Y}>I7i&$-!12!=^mtUjC+ifZZzkgfqTr%O8e#fg~l<)9*J#?z-Dj^4Ax1EBWR;hdiECL}uz;N(P51B)~MMAHg5keH|?=1auH;gc1w} zXb=&*VgXnRK!J2B5g&mBb4v*b(MW7!jg7=B)+jGYZc%ps8-G@w+D{B)O23u*lEW0F zROpGI_XJWEaJ9*(=FiPrajh8DZTOu6h^pB4#Nn3HqSx4OL-|rMgImQ?b{e zUaW?y*nluG5v~;efen1R0yE=ujjX(_vp5!eh1i#g;SlI2>4JD~UdtS{&MbwkMUOae zIuMT!NH##PiK;@Mwcg?Zf0e-wLjYuPbNChFC!RwRr=(d#;CcL^`U$Kzr zBqC4rV`+-#l&&Mpt4J@wF8~uN1lk9Y?uETt%!8ExWov1bF=q^V5gkD!q>ICuu~=p} zq~zsC6Or7s^csJrHx%+%F114r%8QSQiq9_7A&iZg0~7%Saw`$hDjh&bPw@$501fzr zuK++M`X(!&Vq*Ro{hM3~EK1=Olhz+(OE*3|+bk;rD(Nep`#`i-5 zgIgAI@*9#SUIySWWZw$~ytVz67Pr<-Qy#?Cs4~XYB=xu&z8S9eiLtk|c>Rt}d4^OS z#A{drsq#p-{~v3Tt%~IrMagc-ULlF1WK@nzRFdo@aWu3j6;Dz0oFGorybBSRQ z3I(+hBO6a4raw1O=K~#}??a7}Y(t!Fv2C?YcGyyFeQokgzKE~nvW16u9{4crlG|%_ z)*`|J6bl3DA4D+#pi9gF3^rN=+YoY*ohHqqNU@02g}|L-w+g~oqXtWx)2O`mn%4N* zYuP?z#-Lizlmv-b=9yFd#&%X%qc`%|?3L&wi<;6ka1sxu&xMaK>;JBhi5Pz0X*M~9)ff-BA6zD zL2zl!hg2ND{*r%z!2tE~JTZROGQK!;XR_{wS!ld=Vx25OE zxVoRP)y2rX>@#t7K*;)MEj`EXK5I}88}SK-Skx3^sXq5f&>gQMnNQ!DE6!HcQS7P}=yy849_n^Z^4br`SYeH7HP{T8i{1<||S;#@0YayBi6nIKf1bVkzrm zkYPIf&%CvL;?PS*?LWfrz;a z@0sjUmEvl&A2#QGC)$a zd(6ED{(@a9d`FS%L%2ugHNh-n-klM_9@zqRDQ;q14@ZfQ4rUp1H?D_`7KC*{y}<(D zYO0R+0kTCy?+Y!csV*rqTC4i%ra;)AL)j8ABWV(SE*&hGZGooGv;M9XY9(@mto7uu;f*Q zJ5!p4Ih6v@n*xGQi!afqPg;Q^E8((f22|%v>h2Ln4)#p9ji&@`zCAhL18|a>eEcTASBAb>*1H7Oc^$=EGX1kB zH`dmSEZ8;|dQQ(tkX1GsutDRnN?3YuLtj|F-`<9$;tddr4{qYpKx8 zbYzlcL6I3m&eDWzecTdC;hhm~$Q?`xC0BUKmyz5`GtHE?dEpslMO-v(_9MpVcl zjSbx_d@2rNNSt6V_ZV5)j;p~gfvag`E3yknLrM9FG?03(^D!{JWdU~QLr1MYLsg4g zbp$zo`6STR|1h2eK@i+;T}wvj*PcXZYuFN`thcs*+!BRb+vQ9W+^Axm2Ab$1;3{LTcOo7n?6mfuJ1@fv#Faf~ zIzq}aXW9!h&FcN@GacbD)&Q9R=IC+lB)og@yJ8OTCP-2~5$Cc)oZ^RDY|d_e>=IlJ z1`b?(xp6g4NMTDrPV#~gtGmmam;`yfR=hVF*$Sy3{3%^crnaQnx{r+guL%p2MkcEj zR)uM`j%o>}m_w5|OJZc4;9f+2OF$=NvA}M0c|2U&=VI$zY=sN7k1o(Yx0w}-cIl?$-7d|W+MTDwoTw<}H`z*Xyo>rMI@miXOQ@t6(P@*mM1*cSsY}+aJ564~ zO7wS30+Unso-i3qPTYHHH_4fS)uPA^9BsU_(Gv34;+=_Tv1X#F%vg-b6N<=<$mg-q z@EPg-Qtpoh%xs={tr%IH(Z+S= zE(H=mT#w`rXCwU?J@0_X5?GeaJ0P-zSOCS-(>n2VfXpg4AOdcj^y2=?|~{G*S;U>5(gD7n|}zr=y$^Ih`xUwZ_PV8a$U~4WxS~ zQrJ!Fjk0iK?9TN*t;^06zcEuPGxr6>+|F@yk2P=B=ExM!^r42m>scs977=(cG8<{+X9#`si)(w#xr_d#ktM(5mm{B^bEgMI zBfGm^i<+Qo5#K!tM50?lS88kJNL!t4Cpr_h+blMlCkAEc1TkiHHUO5Ee6r8fJ8vJqrRBXjmbPW-^|uo$aL034GU*^9T|Zff4}EmJZ#XlI21XvM z#~RC!8r&X_mW5IkcP!g2-KJ$^*rPKdL92a+mH5I;E-K398Ll-{CERM^aTBOtlxLoH zdeHtNw-lAbn2o4R2VrDMh(Ege`I3qugU6S@`s(WEue!EqMZLp5G zM2;Dk=z29IKMh>Jo7HSs9)$=_Ic3?RKEz=Ko(H^txhC`+Y2m z%jK{?g#MI1m&g8q*HQ;y3+{vQMRnil`=FM|ihBu?VcbgI9L-sp`%3Q8A$N?Pf9I96 zR5c_2u@NI4yD)9w!g*A~%qs9a3&E%+OXtT^vOp9~^)%?xW|=O{Gn<=OL?q4!#vw=o zTjqs&jJr~Re3h`qTR;Tsv^;2E=9TL}C5)#;#U0({G&6|`?^7-ja8r4O zz3CqPpS~NdBd5IJuzWXnB@2x>dk#HWn?*w1;xS;(hQ|kdt}=BY|B$mioITCiV$Q(Y zbpZz?tlAR><{xuS#u+=c;?rA<;*dJMnGb?>i;#XyHc_jutY6dc-GPYP`D?Ov>cP z6207je17$$S+gcxH-GNrv&*L=38Eaj^_pvLomqGF?X2qD(womMEv18zJ%+3m;@F7t zqYp_x>v`5otmrO>%2SlBI`1AS%7In%>an@+i=l>sUY4kqrMD%b^(Zno$tKXRn{F-_ zRbP7h?{+NMIQIhmm760sPF#M&oSW-$FGw5?^=UfX-L za){Xm557e|Q3f-MOF!X`2e6k>k}X{r@9Xg{a*A5#xJ>PtWJlvjXPvVF>8!&}w2AXM z_yeBK3TTrLL=>h%KsBlg4VbmidFIETCMMpP-gGUScKPLRPH(!-ER9Z^xrGX(vATzq zL;M@u-;Tb~n$2#P7b=QVe!z>~LnLHy}pQH(EaSUlGNaW!+H)mw5vi`{LS z$KvWcadjh&&1RZoKVn>+L07K=WS1KUC|xc63;o1Ss4cjf1XX31y#cPV%`$l}wJm8` zMkY|y8wB3UK4&&`M?z$Jp-VA42{ z^ca1NJJ1C};pl}Riv}_X(-l$+zIRcC$wCB@P>PcCQ60MBXWZ=v}CQG*0p<6=v(Xui$rh;%G{B3rG#8#t&#bDMHyqY9?bdC78Fb^;hR)P~9 z4I}fF##1k|SGU)dBJbr8F?hr2um52E3;F2JZ1^WkiC>RRzD`0Amvqmom z#E8oCo69Em3eoA^i`hokMR}*ifATy0I!10bM#9J?V&nz*x(YvXg1`UrLH2|8FYG_t z74&_y+9P&8$a>KFh4p8vl25F`5dxq7o&S@c;7XMDK_@w&u+cn56~vZEzJv5cLKQHV zWNRH77;^=^qKxcFSvkEf?P!^xc_Nk~Pzh7Hl#yf;JGi8j5v(g4ZBRlBU`pL2&q<>7 zfIgX@Sj8vtycO${-zAOpIlWsEDaBKf^rA-&o(j4huOJO4Lkqm&5U}k9QcL_wY7&?q zknP^6w~rUifCRm%s)Ut%MGkXkZ9(YIF1E(SmLL#%3xc3=1VQUv@&Ff8K@gH^bNQ-L zYrQZj%hd*OVeAyGKy7NDT-pk~@YCE{UqQIuop2m+94D$^XCO1Hp4W$_hvuP@Fa*&C z*%Z}+p$vyUz+3=D3T#lQ05q`d*2NMDY-(>6qB1cw3eE*bBl0a&f>RPO%+W$&nubeC zcyL3}fuE9}MK`2;e(J{qMH{S-Y}w z9@xI=z4tb47sw98s;H+DRt>HVqzqo4=&_V0-4?G2S!(@%hDHwitCy%)6qQ*LXgkga zsKZpWrdFNNTCX5~ZGbCckup5B%biWmUCw<(cYV9R(a-($0I66~11_0ztVk>2QA^M) z*^p9^&NQDKhy;P6($rjl`+Q(nB2W`b2ngh4@H;Cj|M{tJgZBBcP4_;eZSXy`_-Xl| ze)Ob%0o!p34G%xnv%h#yu5H_}{0sIeJ6iX<{faNxcJ?3L1TRYSax5R%h`1f z6g?gyY_A8zwU;FkJ$?bUmoUG6Y{|}(Tofb)Wd{Al>lM!^GN*aqTFTL+^h)Pk>oVB> zgn*RhL^zZcv4UUDWfBF*|d3iwD(Kp%Z zH9FI5r8!fzP683cfRrzdivOl>76@&;M4)BQuJZX(D&^im>Q~VWD+{GM85yd_o)%67 z)o`x_VCAB28N@@#=TbSmz+`}sip&o}vBK#T9jtQ-u=^;qN8DJbgO5@B24cn{7Z~Yk z)b7vu@$cJiYyEED8{a&h{GxFU%iFPbV#R%rFM^XOpQrZMAAaXpdGbqjz(0Qc+m?G; zld}@6@PR+BTKT(~ck8f1!NQK`Af{-1# z_sR(1h(>P2K5ZrC3(cc>RIec6w&R=NaRMQl&@P22!lkgsY5w(S5m<$B=pf<4eYpeB z#Hxc5oPT=L&g=9+yMCzbrKVOLd%0Zyr~d6;7{Ei5&CfhAWhb9XYfcfv3aoh)wZbFg zXBV1%V%-%|D(5NLRo3tQ?NA@R(yOGDBPqvIWK?dX%9gA|DC|hsOv+D_fj|^VP(5&2 z8Ri4^-i6(hvgHxH0MJeLD%JAvnOJ(>Pj78{^VRA4{_QD5mynkACynOPt@9J;;q#yrzKfCp;YxP}?PqK;sq16`q6Ox_pUNM9d8iaxR$IJ~q9 z&vGORGt<$oD%=$2;ne{)JFq0cZw#>N02>lu{Q``zbNqT6tG2NrHrCI^0yfFLl|fac zL-m*`O_0ua{-K>wLd7gc3lT&hRtvC`XNM52?4V!GrHw$WtC|E1MD}61LcdjieZ#S* z9-g&v*5p@@y~i$KcN|=-f2szT>PPgM?b7P`1)0}1JhWlm)n(^r$JB4%7@))X~5s1mHT5Kmt%@;((xcy27Xk3S@Kz0{&;xSFo6Z z%Cm&@G5V(H4W}x}CRzb$F0<^0h3`YmV`RM8HN?-<-f&Z@?5WOzz#wpnq8}NP10(<9 z{L0B!Ia!gj9c>YuVK15>hda8QkkaUIS_mrz+Xb4?Vgf=?3COZJLP{$7ULnNf=hq(l z=Cg0V_%0dXCDw(@mMr9j$#>Md@4K%t2tJ~l*l*cQ`T~7LGJwv-@N!S;H|k&Mr(jrv z!;MY>=n5y06+s5=h5}eu1AI@nMW&KOp_fa#W=lF0F;;|M{mS&~Cfuz*qzrF6xjRJd zCuEgu#e=X6fW(E>b5dA6=V4u%5LL>OE{m7ASz3xG%_I4P{$75rVsWywtWpfVc9B#L zm5>#xN@HovEjzS?KNPkkkP{Nh6~rPFK*UGDTWXC-nG>>IVBez6YCghi)>6`|5n>lH zkTL~wJ_!1(phr1TnlrX~aR2j%-gjRGtH?V)BdhrQ(U+$;UKCY(U8?^_8PYVR%5}f5 zaerGMIwBI6vvvP-=e=8!FLg>0u?C`-8dw9D+nNvziwN4lX1q~W42{ z4LsPiVPC~^Ozt8S$od7TcV>_WDabs_&aSsJGUc+1R^6?h(p*sI1!9K#8yM)^un=hDA+-;k>Mrf<|tHS zD<9gk_t1zX&#xl|bj?fp@Q3d{xbns3DMNYNMThi5TV9iIU;M;FI=-Sfr zGlsF+Mf>}@hJ19($`aS=)lExooWd7kSx0FDvje#T!JmFj_xW`XqbYp0L;36~x_l#UqGd*?o3jDD2X# zj)dE54+T2W8c=G;$N-q-!e_Kn22djhy=BNLC>?~SrVXw%4Y=$d`i-rh z+^gjOt@bx7m!|@Sv!g8`HxEy&N!H9Ut)(G2_cSQa(s)+5$`z-yK!%S|@1$mAgM3mT z;SER8WKc9sqJj=#+7bM-kSqqHmYLcMn#Il7xTYDz#;9s*@`HCz{Cx1qo2NgueBNEl z^)D)(xk~?72_RtFUw;QJmCZ+Y(;(GTw=D> zDx0k?QTdH3t5(?%m7S%cIb@2;X9X7r`Sl&rcUBNwE;dPTc;cFKhoo1s7kKRu zF#cC>y5g9$5)23pC^ zX~4Ebr~}p{Od9|Ovm=IR(@JUz`U7p&+mC##^THuR-h6WPeM=rthOgQEmRy;{HjM`(Rp+@_5z_wn$_2z7oV}pk zU&ZPWv+#SlJE3{4P}DRx^d>JZqXVPZqz&wKCsF=OsQ7o%4f zVOq&`2ZN2dK#k8B4&wo*H&$f`=7a3Z^NtETBBA@@=x|eIM@dp{&|I7Kh5!8d+vJZ){Z;*M z*ppluj$?fRBq#)I>iGCM;jy7fAzq1^ooc6w^F5^kXhUD7y*eQ;2Pr5qbyh=;f?iiRk*U~I(mk|)I<<}hDxTqoZ(l9KF_cW3+ZPa z2Ykow>#RON$LH5rj9WF(0Is{|@2zyCBauFC16=)V8-^luvZz|Ud9{Y0t zCZ?(WlQYuUs*^0DfAe#4PpY2JKCr>HE#O(n@AX>EvW)goE%woE*hg8?#<(^%@Oj{; zfLs}11F2=XpVAB0c>Ps~r4RI1z|{&xPd}l}mZ?>HDF7eJz7kbR|CMBvzLa51fUodN zh%uM3YDAai>i(JW%tYq$%%;p;nfo%WMVTxU#WPWlB@syv`;84szC9jMJTp!oH1Wc# zHFpLc8`fOMH);DqnHg~@^3?!&#%f@zfB^%kcAvKUk5iUhc<~=bmM@vQVXA)kg<@y% z3;JP{RGrlK=?(Y&juq?g-gPg#pB2MQ*Y&?9|Gs%M@6CRL$cIceFL7QNkq>FwizZGD zP$iz>I&M%EOzDQ^ zH)1OkhcRL+V+xEo3<1!x{9$8c6R#-Vq=?z9#EV7b2mxloa8WGi>{zeNP#2_{$i9fU zl*ln+*1yV|iFX=-oS;!QwAY+gzoyND(2{vkjbj~T;I+$n-Ky$;y>7JiY; zwfNVs*Bf5hy!bT{dlh*;!t$`Iuv&y=@2DdutnWE0LX92kg{K#+8i;2{q+#&_YaAIA zoNYjvMJ0Khu0u4WE}$uvI;$ga8ro%Km_)r78CuXv2u7MsiDQUON``>| zmu&>UEx9nlcHQ;*1Mll^>nML?13!AAX3fJdos?_VB|kl9-4J#Uo62h0gJU19`7f+S zfwKl~TP55!zCMbhi0XDb@=W4u@uvT;F-uf<%KOC#{UFN-#^TL`{~6Xt49xLYFdO`T zc8A0+mnP$JZxmdXh8L_85S{Zt?a z2wgQ+r)i#OeZ()}<=d~aD#mibc)|OpJW6M05PJ3K3x>@PK#K_MBCx0eGEqtf;XwZ& zkn_W|qR4f?44ARogTcAe2ltNk$}Nqei~SD;Y{zGR-@Bn7bKUz$(Be;il-&Kg|9(%! zR{5&`Nv_f-?)%8%KXo5-ExH3wbOHRSW<0MSl^qwx^PGWN8@>}hGNvOdpk~llcsORS`?4$X;%NIZ?!tUj5@A+0YFI zAAb7T-}@Nzqw0A}YjPDbjjIm6z3-zYF)!>u%z}2HUz+-Y=9`Cen>OGOY(Sq+0-C&? zDr1hgj=Ok;Ypjb8B5N$5)>?vocb(T!*I$ZDO-MiOL$UzOBcQFK7&?K4s>^ck_YTFkxmsEH6I==23n z&*{B|t0`C1Y@Ldo_%dD12X-R336ZO2qCQ<`^E}M@k?&B5>^UKE5Z0bM^ zKt3oJ*nsyy%wQ$)4DUGE7P7c%CCMP*4b)jIE~Spit}djzA~OijhWe2ktt60#2r9XG z_&_1vMtOM>XecBm{(DM4fPBj6r`|XvQj#Q`kbs4=FcZ3SCsqMp3mrx~m2?j+vYp^P2_4q)UQ%nEXT z#0E|wR$1!`DW@!2okI?|)H+$RfJqoKLwQ6LDB+ooY9CQh(txP~2SAnaBsQX92YL<& z!5`=kV1@B1x=JXoKi9Ud`R4i0xOif>zTgMn6W7yP>vMU*H~g>cij&8cY5Gse>)*!H zbwdb{ZpG6R*M(1dJ3eBv{dRjJ+GqmqFwkCMAB&D!7E6VDtotXoJjjg*RR}t{c8YX| zbPoUxh#;3q)zXy^eMOn6Np%0R~WJPyAVlmS>5Dq=LlP6(JFOj1%bxMTwT#V5rS zlEU^9E;bYy!niPK3Oq=`=!PE;q02K^?B!WG{GYdmyDMqCuOsnk9bVQD|U?8c7Ae{frJN3`> zQ$O6l^-Xq-K66KN%bwrQ-1g*zSDEF#ub+pyjk+!MJ^bLD$#>40v+|8U zE+$~Cv>5M|a_gFO^^1}h?;?(R(o*k5UT)R!**VtXR_?Z2qt-rvhB;1&hK}~Be$^ZH z<|9L4AyGB9o`!s)+e!!ks-H8f@h50HVr*nOKtK_#Lfx(v?afH31#(&L;%BT@m0xgR zli!wn=^%(~kK8wXrP6Y8xE%dG3!SPUeI{loG}LBOLz$HzVC;qTw6}zPQfJiwo=E6F zJds1XD_(E0QX%XC>oMz(R@K2%d0+kk|B9dFY60S@R-7r4Qm;%`<|&HO$9Bl}rR~2q zwE5KR_CD+o`;z?^QQ3Wz)SpXx0FWf99?5JC4bg2DSux=mWq5UiNvO~+hGY&;4Dk{H z^lTwkLc)}1K1^=gwv7*bH~BWn4o(@8C>(e|H?@B$-hx+Zh-bUW!g<=we(V0d`%$-C z>z?N3{oLodFLBFGcbc1ek{pj~&>%_*{=pM?G{gf)iGiWY^W()c{Qr zmK|vfdIMjR-V{G)H;JD&cYIA44E)@*?(qBh;_FHHxq(Fjx&dn= zPAI(3h_o(lx4BcGT7V=1LiTwq6Mc+d34g~Lv<5x@jIip+l@UHT!umv5YJ}NAxC4*i z3oonij`i|EUX~A6&&yPFY0UDB^wfD8Jc`GYa$S%O41ONuc|nH3Wyw)zvjjXsmdPka zbQ?i!kzNz4MhIqdknjg8=e(j6z|Rov77E4Fv6uq~L9HN+87V=V^Jaa_h&wj_Zp!e> zCfqb@VDh`avbips&CUzhU`y+%lUts;I`hSTlkZf@+YUy<(cq183RcF%ao~iRAy%d* zVu4O$>VV)x^gBmB1$V!8F5n2f$000}YOoo3ovJ zwrxlr>Ntey9hmPBf{$*Z9>|v;N4@ADC957+oq{I4R)fo$l-bdabDr!kqwfurEV+u{ zR)Bzgx%cx^V}op!wx4bC zY|9c0x7AW#>e^i}q=@>1o)usqrm_Ak&Jq9tH^DP-s2nT`bqs<}k892bDweEUdTGM+ zz*%7Yr;KgO-SFdvpEejq2N@nTlk>2;bmDoXx$!HnbFr~5Hpo@!`q?GVwlA@Ba6Q?P zzC9)J5 zW6TpqARX%+lkI#(9TQI5+}sw!gn!!5xFCM z>|qX|9;_rcRW`c2T1h0}#`z=CBCwoGAr~sZ za7FwTyi>!)5LO(S_9utqKBf*5^E)@LxyOC4wj;Y9z(nZPlP=W=d@A{AJ~SPg%~5b+ znI#OyWX?2==50I06h7EPQvfWh%l$F*FxcB8gfBZhUO3mcjJn!71KPNDxMfk6OZ4l9tUHHitosBfIhU@+{0KSZN0joW zcwzb}G$}6vmrWf&ip#)(L7410I18P%y?QsDSq>5~qSvm0OAj`ZPR<>I0Ge ziX|I1EcZXVW!ILiuk3i9-8`+Xe(DVqCvsmxBBDy z`XBIIWspd}&?^CS`Ob1GX$pFIwajM5f-n& zN9?`yfPp|56(~3%>ivG^uD8k#(lUsd(ry)nClphM6(Hbk#Dai;1Mm(oED8QZCbprHHzFznMa$M_yffG4y7i-N2Tp$c;mM&>?){6t z8#INE<8{xexlI?If9P);_5U72(&rO4g_Xb0V$IXa+FnThhuzL@m`k~L+HGS*4kd`_ z{kRuImvneN`{HLKG!0N$h0__WkTX4DWdE02n}7gNtWqek6Xbgyb_aRZVRypj1vdzI zK_EmV^`^y48xaeRZ;|5zBoBG`P+eGK<`YQ}1<6vDx9FBb z`b%u6e%Cx+Va+}K(31#Je*HR&>j$gGEY*kVPqvIlNR{Pc_8!dMLe-1BGD~id=gP}u zMI5yNY)i;uCloKo)UdurIuDa0_nl5w#glxym47WawYC zp5h7UH-c~iSu~~CM_{2rCUKsf`w5PUV26`cpxUX@C^M0r0I*oRHFmGhsU|?3rpTB; zckfV~@TPkRlLc`cLm272$4-+vJVRNT(wvMoj|BjoCmzvs$g1)f$-WyWQ95lW8$qXbll2J^q5GHRAXY z-_okwu#}I-{T`3s?n0MQiFuqLf`b9m-G?Ld)+E4f?XJyp)HMU(;W>1O1Zw#b106tJ;BE zilH{A#Osd5Y;uL$onGP3u}P8o$n?m(h!Tlpd$STdV{CDZ-4SE4m?ISgCSgkT5m7a~ zVG(7aUD9z}&^E#T7w9F*zMXDlX$^_Mm~nW3y$%eMCpX=Ha?!KpO@Djm<6WQr>&Vx0 zTeh(@ea}kXIP&r}RVzk3^!sgP&hz&^yy>D1V_RNajafHA7WzRJoYLK*zT$brKahVq z5(k*D%3=@Mp=$9hIfgGCGJ1Y3v9YPPSvGz*XOs9$;HmGC;bSmatq|st#ocIUli)jZ zsX}r#<6N}KPOr)xBXJHPCAuDHB zU;w%vGH(Z1jxj}cIk*Z9cpR}0I%_;&lDAqM93@$uSda)@O`I^u)4vPuFXXw2?#qN! z2>F8!>Fd$F+ucC`7Jul^>=z+-%gR?CZ8-0ye{|lE^Yt=X9ZEhKw8A@+x z?8P_8&3ZsDaxGBVhwMMN8N4f{7Auh=ZI7p=*s5$iVy(3DuWTm)CbFRiO)J?8xpff7x9W!d7x8%gHs%(BPLghN8;Zw+*@yQp zJ|#R5DJ2T}O_)HQ7FGY`0$D}s9cWJ~AP$r$wGZ2(VfTT?1GaM?-hVLK-_qaV{BW;4 zKkeGf@{_Z8WAtd-TnNSVOLn?97v%5ZE&+&Ta$-danzQvH&3;)FZGDngFW##9rw3Nec~wq zb}3CTfb1PyVb%mXB$8lsLJR1?r58^}F1WztrMQbS{8X#lOfd$*_Akz@ONA#b7|X@i zI8yPnhz|)$V=a>`90g~VYL8PzY_*zd zr=z~=glONq%f8QUDYBOXzUqTLN!t74Dmd`%okzYOw?H$83Jw z4@QFnxJVZ&pjAT@J1yN#IV7AqPG^cppw8LHYTkM3&#kR5yw$V~;yCG<8SDTFlzj^KD&>$%_h8!zsETR{_DO$B+>)@+ zcClI{Tf!1TG{UegC^-d_L2O{^ElO@ITzfM&=1fp%;QF^ z>{dLnSGqA?ZLL;SrE@ZFx80l!A(HqmSTSNgzQL{&$OTqwX#GuaG;04%IaOD}j;vY8 z<1l9=xGv0DeFT+)uIe-`3O}1u>j(~En*7NV>t;UQHumuo>oCE#1Ukfs3RoSfWQunE{s@lBOa&WKhFepD{n=`Q!&m_5Q3A@*oP_czgdtRg+jjqX* zw_^x6kiSGR2o%AP{mzH4W=;Bd^qO16vliSNxIwy z2?d)!C;kIY%oq>N=VW<=HiNjPaAW63ZP z!{I@{(~wxPvQ{81I@YUm3V07FYN1|O@FSoc)2_`@wH)Dy z6qNkUBh465M-^FjTKQrtyMywuUU?L_lUbE_OVz8q{&g&v{Ck{_G8FhOT~|fpb*af#6m$0?;x#Fr9j%tAie<0$Fq}seu~)m|b{{~G>R=S?ab7Lr6Pfsy%o00Qwpe9% zkRM{#;2nnv2()J-%SJr4Q(vw> z$1a^bVf?fyu+GE@htuvu{qH&~u!naa{osvVM?QX&-ac6#4!nJ6bVUApaT{!)KAfd+ zSiK-8SKN+DqhcX+xpX_Cu(BlbWwB@J)Exxjt&|ix8fArBU5P+I@+Kf3=D|oI2_I#Z zj#5?`i3y1rVNvLHrooak9iD7okrOo__i z#FgC51mj3#r$udv^oVyPSSO`)Ej^Yl<6q6~m&h7IzMN1gf^r)u*>cbh;Jp}p^w3;z zb+HQwnNTWX7nD0Emb25u^agDxUkH9sgPp#W&DIy%9Me8SNBECN>HUZ&bQtT-Qm;3( z?a(&^og^Xw0^{?Jc*ITIG^?f>2z$joGNGUr?0?_Hkvc@fL>15c>2 zb5uS%MWsz}*jd_P5!Fj7ev^vbNg9Wq_LEgV%xJkS4dn)qMNUE?m5-Ev!nO+kfM^l3 zYPK(wo=)Sv-5)zy+s=LKPfCA7X|gag9udQUxW4j)w7+I=UzUmL$bOcIS(TX(Wu2&1 z){$Pt+9Y;)HL=U%_wvt#wMtf$>%m%q@#%*ux#2H}f4o)xgrU$8AUI%gkdEMnZ*fJu z>9@K+>b`}$ja2BBu=6OjMW+Rx1y-Wdik<3oaVhoc4uCw>F16X;@Ro29qA^HmJDwH} zHbRTbVrvGPF(oMxDau8w9?Qb|8*=y4YJs9bo)2<=V9dxqk^`v}5r-b209hzV-gC;F zjgriK=VYk&gpQgtw?D6>FwDM)-H@NK9 z%WkH%O?e^M)63upC;S?bY+7z*bI0E*+-b0vNtY#iS+876xs3YMTe#D(_o2Tfy#fQ{ z1!Ub?;oT#DjS89wOX~F|==Hk8&}@-0%eClSihhElBua?H9)vEPaaoFnC~JzcF(K_a zE90cqb z1(tf8f;W3XhcrG9oe;i*6$E2QIDM^FY-F{x!>~hcWyeD`c%>pUBPh;^>(3tz{8N5B zZUD$jz>ui$<2{6{Z{x@N{--bFh9_}B#9lhw7x-t~dt8sKBlgmnzQ7NBGUeI!!FnKm zJmOQ9`32J`Ggk;^DxclMkEbyE$+CpvEjU3y97ddnX^Je7js`Q8JM{d8lH)G3e^tx( z7;ya|+ylKOa=#PTw;VP8Q+_{gz~l1R5WU}t>mV?>eU+YI?}$!*1wJS01TC{TWCK z6=}}+7B62li2p_3CpJqHH>2(B7s6@5s3J!5{J77p&Q^b-{zfgTcZfR|u$N%kFpXBd zTlfjM%oR?&zsPECPProrSNAzf`KsMD*}`e}ubJ&Sw%VryJs!IYE&wh>|K%ZfZFUwz zZKE844UJKDo3c%x05T<-b{KYY+DqCiu#dDBvq`;MPoqzyQF6m^FDP)g&O%6;41S+7 z8QrUHpOoa(+}?@_@qXli`^@xrx}$by#L!8xM)9^Gr77ZH65m2edoeDy$Wx~hMT=Q4 z>^9M)-Dp%>8^#lhot_}plwl1eM>kKIMt=SGrn6^OdG2e>>ihDnnxG-YsbxI1s+PR| za+`QsK>wsYdrWWNKF$A4(~>jZ)3kJD;`v49=;~V*fCq&8@;U(6hZ8P9TQ!h}LC5jG z(5jvio`*;mj3!R?l0hwjMv;`!Z;%DAOb|RRaz1>PBkWL>sf4JIC0vk>R(ucxiFqvc zK?NHkTu8qr3fIz)rm-JM?P-uNALBls;yx}e7Eg6pdGQw(6va@vJr3hbcGJriC9PW9&M)Af=Y=?=jRBFc$T=WZ z+uF|2%$Lgam`Dodr+?l#Z^2!{SJHQDHf~r8u?{KLbp0bl%D#g%v%t^Q9`D=R&a#ks zYj;C6+U|Cnd-E)dhY|r?0>53Y?yYB8#HizjMZW!#`3e*!bBfo>X`e)St%KzG$51Py zPBIUk3Otg-0#7Byu_WPM57k)D^SRE>PCkVmymXY9@37i4s1Y{?L|xSw)A?|#cIX1Ful zLf@m73RY3?Nl6h*M=jcPxP%-irIy*{i|2QhrTg686wgBM8t*CZCGQol>Uqygo-aMu zJ)+m+^{9${UOixVT`CO@o%i5yP;4Fa4d%{!SOCytf%$w7YAr?iVDTp}z!mha72lW* zIJS_RfwZceTWnJm%VGb`Z+`H4CN94F>qVVk)#gX~R7DE-V0T>}e^UB-@#_D)<=vJg ztG`~@`PbUKUe(o+Uc!VQKg!B~^q6#Z&eWNAj2gRe=G0Zv<;g5`t)=G|v!^M)m^Pc< z+4rb)7Vj(`J!a9&X|S%Y2nYBJGL8)DBz_JEaMa5`<8;O9+{!Hxs)S$S9Dqk!_%rvp z_$7ax=TGtMDJ)HXA$W}Wb}S-oT&?p26A-;T#cgwM9UR1LLpX_&|I==gW6*4n&b|@qSb=B{S))=b-&X9D+IrKGLf;A zut?}4KPiTR3W=sW^vGvJ zH5(Ce?^>w{ybR4X1%d~<5ko=uK3O$VMR`LhczFC08eQg}FgWq?9K!dbz* zw=zChJlVQva~sK0=XM6V&hpheRP0yaa*!T_FG zCj0~@rYr`=N-C5JC;gQ@=h(}i{J*?BmMMMRPw0wIzp!LUzt(r&SyY3{6u*R;HS)sO zkFYWpzB+w%5P1EmbODLT&y zra9_1x&=R8!~>~ZswFi&HImw%`c&%0RJA+Roodc%4~ph?_|p{c^bMy|a`h=EFo|KB zLz(OnQw3$ia0{{oi*NUYA32$JVE4KGrIc<|A~^!)Al2l9pdqyA$dm)qlXlLulD%wQ*> zhTKlK(=sc2XZBCBh3uoDLXL{wDnSF4Zn|o_>Ht8CM=iNsX~#3WQoJ5D22s;xJT4$< z7l&2!^4D<1VG(?diND--1}@XzB+2{;6^kMJnl!`$e37$?+>E6P2ZX$!Rq#nUZlRsc zfjfgP;+?_a17CZ2MnmJ=U5AhEo5Bz4&e_d>5W4r70}rfwX8-0VpWLI`H7E3^k3(~^ zp8xT)hYck0zU%+O?jId{@yR_W=Kkr^PyYlx{3GO3eTvoKg#|e~UgLAmR~ywjojP@) zgImaI$>q;#9Zxx)cf8~fgN&&iC`F(aGQv8IYnf5+^QELMv#L{;Qryam&cZ_=FZUij zq^B&QoP7Z~EUysA%P73t*=1#F5MRWSq(X?nq3f(%5v9V?#dhiI%}=z>Nvznke*WFk zb6X#lF1|IREXsyRdyoJ0({$eoM=tx~fv29nPuhJ_diMgqc?ApneApb!z86b?vcfFL zlA>CySK=6Vjuf(bu!pe`n!<0+N}@}Rusxad$hEDnn%pO#8~8h&{+r5AEP=&BNp zzsnlxa#^hDNZxQ+UFO03cpSlCGEVSXVSO%Z&7GdRELX^#ltVm6M00$q3%^973&G|n zczvm@t(KmXzB+QikgWL4wD1mT>9%d;o#8(gcVW~u82>r(+7z4fjKiWco-w^-VroS0 zSvt-Of0yu@z&|NGEAT6Y`(ZY4XK)O|!}Pic%)THxOat2HWvQLyGiHiCE~bv~TIfg=da zZ>}5^ddkq)#O2q{tU4q;R6ps%$FBe<7`^x@>-EPKN1wfmw@bTL{V8wPDmL)1OoduU zzq$(N_wuFEXVg~v^>4&3S#w$?{TQu9?dR8_Kk;$a+C76C8IJ*3>P*4I6(?Kc1i2>T zKwZb4HL*ucY^sTkG_is3v%{uimr!Ml1MNMF?)s&2*V(x15U}M7e6D=gTn488HMz{1%eY*Y%f1e=_d@JUh#d{FM?);co#Gf} zj^KW`-3*-hH|~}q-woO!-&cD5AMVx??~S`<$al+Nhcnok3}($>960&e*M9b%pPliu zqki@%ho`brh&%H#p(a7YSUIhxGQv9CrRs_DKgt?GV*ZT>sEN9r0iOFDJzb5=?_ zfp*3^>~G=-e*G9K>o^hy;C8z3d>l$Q!G8vtYzcTYJ!G+>kR@YUyrKBwki_;WuKFXr zspX7B^qMe^G4lCFrZajGj&BEY6kY@~eP+BIzpgioHt<;nrZ%|YiD}_FFo9Rd8b#Sk zm0fGKr6k5{QD(1F+n^N!06H)d8YBXV9~eU;zs8}XypZ8QczHuo5*Vt0vQVH66DzC` zYGl87k)68wOMZD(Mq$Bs{DDQPLEpWwKzO2S&+8kyMJ$|Mh}DgeWn4+z!i~EmqtSGf zCM6Rv#|>z=OuQ@-m4*zzk=^Brk)SxYg+1LTP70{HtG@PkQM2#ciTGUN@7RjZH9-3u z{(og!O_HpF{W)H3%lFcsbuNAK_sBHO-+qZM*r3VqN zF7;lZ4~oE4%K=!e)#_EK$SfR!6AiI))O!FeA4RBu-XlXkS@J=J^QF`) zYXK%E&-<(@+kHsS@klocrXI4_@>}?e(CLY}{W6R@ax=(|1@b5$(J85@L4+sy>||pP z`g#TtcMvlZL_EG_GN258^0FtEKla%219R_qdf6k7FM9Ua@Ok}OS_aJgL+hM=EhFPI z_<83KJ-Ff6hv%Q$vhD@e|HPc;VbhMhFt4e321e_1#0M|K1Lg$A%f-~s7$Ih?R+n2i z#2lRYkWq(eCFq5Ws+QY}L&k+>xNcTtL8LcSDqODU^W2fWO|j~VqpWd^n&0O8?7R05 z9dm3;`An6=CSz~!V5`Kan1y_lFqequrRuWmG+|t3#!vmOBWc#3>VzYjpK`U7x9$C@ z{bCwx0bvH8M*ia{OdC9OmtMBwI|*v|H7sriM3GWPz=Z+ILCb`HcxT7t$0l#@Y@D}j z(&JONt!Y@eWXhvcAHAo3?(!**P2IMxZm!_mH!mJrv2Si|tosW*R?y1|G;IgBUyQ0m z%=r9xKa|7eL97By>8 zGYc-Eeke1pJm2U=j|~bfBx=J0hL~0&A_oqS29a}$Eeknp%imbv6;dO+x?$6-@1)bK z*hz_7yNR9L&cw%!6+%&K=s+X%bs)Zzsdzoqj;unx5 zIzWIJGw|@N3+hW8yC@&bwKOI8F9t#3!z00$ibTLzrpCj0V~4FJ(_E6_1ur0_$RY-w z1yd04VyH-B^x8Dx$?h`#4SK%7UYX8b*^BI#XQXx5ptrYeO1x$!enRN3fKJQr{if@cS9Ttu@=5Ut@o!j& z>Z8AU{5S7exx66=?^t<)ep4oY8S*A7VxL274os#gVU}sZdKn0uN}(P z+()<-!pBZ&%PY_6pV5w7{<2N&kzRiE zndzfm#HY)+3iRGW*_c`m;9PJ|Ba~yc(Y=KhX7+2E^Z*@_?1Y*?sf2`vAb}-|Zn-!# z$@GmIo?N<4n!u0yf4|;O#pV}JQ>x7$eFdMyz7Wsx7ttXd=Z@=ih};>pj|d=0qB=L2 zW;FL^oslnmKHbrgeLKWY=iJfcG{4r4zyC<8;y=5-4yU0%ZqjP8iZzc|_;eVE==jYK zxlya+qZ;>-jsa7o)(3v%biX;AJ^?jPJ_9?Y{0TtcYUNKLFYj%iphmGIFa$>V&uX1N z8{aTlt={>l%XW4wT&0!3rEi1(lQI!A;&$VuV(3v?>m|YbiR$RTN@Q~;CxGlo z%B#03rCgDQHua(1tl+UHq<41hdK@L!FS1uZ|3HeZV|8qx^mFMX?vceG6grdKqOI}X zwssWWfdtVJ0Rqoaz5~Z!GHB9eV1QtEi0ltGwOM1(`2l%Asq^3SXobuLVh3aItwAM_ z?$FUgI|wxBA=G!UMbXum8nU5tk19;`Z0zL{ySVSj+TT`wsMOs7YsF zgSCbGF59+!>s|cmwF9?3V#{Hx=bu*JGq3ZZ8*_9XzDYmO!)b#15;PavrD9kYI*Z`= zgM7qs-cO7d8TWfx=|p?rVkB8ZjZtKbN0hVJl$&D~ne4G9eWhFo6iUZ?>-#>iaNW}z zKo5LwTjS)m!2?IA&d;0w{)C-t)*pOvH+x*Fer|NUbm8cfJ1Hp#FsNb&URs1Ky@3;%(0wq(0IPQVe!JsglpDxB;VP(>CK2v%FDZ;x~ zOzm!hFfZY^2pw20C^-yY?CSUkeX23z67S@A-zB5_lHG`ZS_|LFzXUanPrH;3+$^u1 z)J~w9dY|`dSSNSe6Lox75 zHrFMC%JT=JW7C?k&Kws5h&$X^XY#z#ZnQ%$RhC!KLB!%c4Fu7c1J<6RfU4QXoEoH& zXzTA@dH>#Z5B)@%Qe%3oVba*414r?R)gD$g`LVm#KXdM6_uu#_`$t!_tU`TXI~SAI zg6sba%t4kM>l@4sLxtKlZW1?*o5jroig+n<0#R=bj6ASeNt51H!&_M~HpYQ^FeNavC z56dBnlbq!eGIE%dxkZZ*0Le?=F|{~+Y)v*`!uSww75ggOj0e6%!;cL~Zq*SOLI zO1TWf@g1fYIKRs1{Gzx8CqDza4Z{HlQ(Pd}$ji?FO$nC?1kJR`XldFkIAh7V)$=UB z#`^*aLCABRlY9>Id%eAz%FCOhUT?Iyyu7KmchjaZW3s~bbdP!T;HNJ#ePYa@^a7(X zCnb@LEO2>Pr%mx}F)uHFQ7LOF?I`6-OY=RR z&U}`i&!<^HZc&(*S6C?ckv7hGBTx!4ZL%`PZu|t{O*4#%CLyI0R5Y8h8iCOD8D?JN zDOaR7UYb$1Lqo!|22);ysaNyU`DxuxcJJYLXq@3x6y>n**ceXK^-Jv^n_gH}YDmdW zO)v19T>VO2c|nIGnCB|(r*>Xzy*66-$!7(gj8KLrR9RDBbk}`mZ^*tkJ+Ca^mz$ZD zk{T_q%8Y%}ua7w`63mDMOcmt$BOT`_gh%9K5WnDN`y0m@x)5fwa(bB>4iVxcjtO!Y zb~R2~J-kdu)CKU~Gy_u-)7A|b;Nz<5hbrXa)?t=m&ky6Hbzsc()igIZaZMRbd0d_~ zk8jFr%BxT{C0Iq1OCfQUx701+Mg{6ZXERPhNTnh{Hipx96%q8{u zvZj`o4(jE=&#vO8KKu9c{GqS556BtTIdA>7@Yulv4{KoQhR?3P!HBNr;olguKuyA|lA2_XJt+`Sk1Q{MdAs&cUym2fwO+ z+}mkvUmDw%h637YD4?B&0@~o3n=;!f&k>alTvr(98Uf1_lE&jAH=kN#R%sv@$W7uM+|-cbE-H`bWfa(q zA!BMy*cj>4zqZ2hqU8M*|KZ?+dpGsU?VID&X}5w4w%Rpf{@VLCRCj;GM}&>ETI^UY z$cjXtwRB>IiiCSga(+N_5WE zX(cT_4oe334EVxIDb0bDB*JKr#!ax4O6c9Hq~t^}ka(O)WRf@~3UoEY_R0xizsc(a z+YNYiW#h3`&GQGP>)m1R{taU4lPO`3K7G*q=7|e@2HyhqjouSZ>Hf?ccI&O--kF)@ zVH-F%Gkb@v&Vg%=Ego>k{Kfr23EhA3{5u9LKDK7y=<(x6vp?4?Ubt+)fMp98*Nk5~ zJUcHjx$=!S?zumE_*(2a%AJ{@SqdCyF%|`}GEQY9WfU+0P^Us8kV}aq883nT6_?0} zVG8yGF^pV)LJY&@&+ZOo+R}R%9P!Da?(;H>TQ)QvT#F!)%Okdsa8m$JD)1#9T%X!2L+hqb@3~%j{rcxBBUmePP%&yNwH-tXPeLXX z62hWD5crNLYl*UWlm(-Vivj|gauf^bp($dxrM z_$dM@>?3zD-tn!|2WU+ro}36gKxtn=6e>NXQmH&dj_yIJO;k9Ni)<#Jv6kg2zj=ac zlygy0P!r*rktL z;^n=Zc|KntPel27QPf_fVm0Nt@B(n4wQB*Y?l4uqRhwbr|Ihnu`1|Lo2L<6DdQEI! z-#|kNVz#64RL^*C!T2;gR~{Olu8$z#n^xTJv0KFKc9jgKi2hnOlz^`z19li9pxLfe|AaJZ=x&n=n!g`Y@&dTs99*O=#-XPE2EoN=v=-n9+6?%q>IH>QsN zY}2L>cMco2^TSQ||HtFQhCTitw0Z<-xe({xqYX*Jy5W2bO^a`#5oCKl`)O$Pb`>mbVF0ay)P`7 z^lbm^0+;GFizUBua7lLlwfA>F!OC|(`NWfa&ZhHQhYZS?I0M^vFdJyT#4x+1ZF4lOJmzG8IYl&6-=ePT+{$&~W3 z{RXs_I8eLTI93t2;ah_W)kWKYlWFiIPB%%C?{-⪚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 literal 0 HcmV?d00001 diff --git a/src/java.desktop/share/fonts/DroidSansMonoSlashed.ttf b/src/java.desktop/share/fonts/DroidSansMonoSlashed.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8c44b47edc5882630da72658926f5d295717ad62 GIT binary patch literal 117744 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