Compare commits

...

118 Commits

Author SHA1 Message Date
Alexey Ushakov
494538456e JRE-29 fontconfig lib crashes CLion on OSX
Disabled fontconfig usage on OSX

(cherry picked from commit 431e14429c)
2021-03-30 13:05:01 -07:00
Vitaly Provodin
c3c036d404 exclude tests spontaneously creating windows during test execution 2021-03-30 11:22:35 +07:00
Alexey Ushakov
50b6157d02 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 f3f2667a4c)
2021-03-30 07:00:37 +03:00
Alexey Ushakov
acea4b6fe7 Added logging for freetypeScaler via env variable OPENJDK_LOG_FFS=yes
and for screen resolution in freetypeScaler

(cherry picked from commit 091d74a791)
2021-03-30 07:00:36 +03:00
Alexey Ushakov
1c9640f037 JRE-34 IDE Crashes During Startup
Added validation of dpi settings coming from xserver

(cherry picked from commit b1c49c3b27)
2021-03-30 07:00:36 +03:00
Anton Tarasov
48c5e06b44 Add build.gradle 2021-03-30 07:00:36 +03:00
Anton Tarasov
ad38c88a4f JBR-2031 [mac] jcef deadlocks with a11y on start
(cherry picked from commit 4f44b37f08)
2021-03-30 07:00:36 +03:00
Alexey Ushakov
e460a1bae5 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 48e7b547ae)
2021-03-30 07:00:36 +03:00
Anton Tarasov
4220144423 JBR-2019 provide getWindowHandle method for jcef
(cherry picked from commit 7ae706b629)
2021-03-30 07:00:36 +03:00
Anton Tarasov
42792b4124 Comment assertion (originally JRE-965)
The assert line crashes debug hotspot.

(cherry picked from commit a00074a86c)
2021-03-30 07:00:36 +03:00
Anton Tarasov
8e73bd4a32 JBR-1976 [jcef] need mouse-transparent window on Windows
(cherry picked from commit b60fac96b4)
2021-03-30 07:00:36 +03:00
Anton Tarasov
a608e0214e JBR-1834 [linux] runtime hidpi switch is broken
(cherry picked from commit eaa04303a7)
2021-03-30 07:00:36 +03:00
Anton Tarasov
c34b9a7411 JBR-1824 export NSWindow::setIgnoresMouseEvents to java internal API
(cherry picked from commit 4399dc382c)
2021-03-30 07:00:35 +03:00
Anton Tarasov
8f54a1614b JBR-1802 com/sun/java/accessibility/util/8051626/Bug8051626.java: access denied ("java.lang.RuntimePermission" "getClassLoader")
(cherry picked from commit eae772aca9)
2021-03-30 07:00:35 +03:00
Anton Tarasov
75dcd6b30c JBR-1795 Project opened from Welcome screen goes to backgound after loading
(cherry picked from commit 322526458a)
2021-03-30 07:00:35 +03:00
Anton Tarasov
b2b9b16864 JBR-1609 Jupyter Notebook eventually causes IDEA to become unresponsive on Mac OSX
(cherry picked from commit 8ae0be8eb6)
2021-03-30 07:00:35 +03:00
Anton Tarasov
3862d9bf20 JBR-1786 Weird white border for IDE window
(cherry picked from commit 4b09614a0e)
2021-03-30 07:00:35 +03:00
Vyacheslav Moklev
622fe9e427 JBR-1552 Invalid screen bounds in full screen mode
Check is window is not in undecorated state

(cherry picked from commit 5547701e2c)
2021-03-30 07:00:35 +03:00
Vyacheslav Moklev
4bb810b2ad JBR-1509 Client area size is wrong in Borderless mode
Fix client area size

(cherry picked from commit 00d32e58dc)
2021-03-30 07:00:35 +03:00
Anton Tarasov
dc4a48544b JBR-1770 [windows] frame does not open as maximized
(cherry picked from commit d9dfc3c6c5)
2021-03-30 07:00:35 +03:00
Anton Tarasov
e1c709ef37 JBR-1693 difficult to input Japanese text with "Fast" Key Repeat
(cherry picked from commit 12de3e287e)
2021-03-30 07:00:34 +03:00
Anton Tarasov
fa81b1cacb JBR-1429 Scale is huge due to GDK_SCALE
(cherry picked from commit 1c3477df2e)
2021-03-30 07:00:34 +03:00
Anton Tarasov
f43e603d5d JBR-1669 IDE-managed HiDPI mode is broken
(cherry picked from commit 461b0b5cd4)
2021-03-30 07:00:34 +03:00
Anton Tarasov
6cc7bfd07d JBR-1650 propagate custom decoration title bar height to native
(cherry picked from commit f6fc65d014)
2021-03-30 07:00:34 +03:00
Anton Tarasov
de09bf2b76 JBR-1629 Maximized window cut at the right and bottom
(cherry picked from commit 9e768377db)
2021-03-30 07:00:34 +03:00
Anton Tarasov
20b1c7d259 JBR-1492 Not able to start Intellij Idea 2017.2.5 with modified vmoptions
(cherry picked from commit e7ca6db66b)
2021-03-30 07:00:34 +03:00
Anton Tarasov
10d5e47a41 JBR-1427 pycharm jupyter preview stuck and no response when click on preview.
(cherry picked from commit 1746b04686)
2021-03-30 07:00:34 +03:00
Anton Tarasov
b3556109eb IDEA-210154 Borderless UI: Top frame of IDEA window is blue
(cherry picked from commit 2dd4163bc4)
2021-03-30 07:00:34 +03:00
Anton Tarasov
6c69e2534d JBR-1365 force IDE-managed HiDPI on Linux for fractional scales
(cherry picked from commit f092ff3962)
2021-03-30 07:00:33 +03:00
Anton Tarasov
a3f5f7f5d8 JBR-1351 Borderless UI: Bold frame around IDEA window appears on non-HiDPI display
(cherry picked from commit 06d35de069)
2021-03-30 07:00:33 +03:00
Anton Tarasov
57b8ad802e JBR-1313 wrong insets for non-resizable custom-decorated frame
(cherry picked from commit 9179718cb6)
2021-03-30 07:00:33 +03:00
Anton Tarasov
72a173b3c1 JBR-1293 do not modify client bounds when custom-decorated frame is set undecorated
(cherry picked from commit cb188edaab)
2021-03-30 07:00:33 +03:00
Anton Tarasov
702c99869d JBR-1278 allow native border and shadow for custom decoration mode
(cherry picked from commit a879ad5739)
2021-03-30 07:00:33 +03:00
Anton Tarasov
e9245a9bdc JRE-1232 forwardport: JRE-1228 support custom frame decoration
(cherry picked from commit d2820524a1)
2021-03-30 07:00:33 +03:00
Anton Tarasov
a86fe44692 JRE-1162 [jdk11] support on-the-fly DPI change on linux
(cherry picked from commit c06c4c69d3)
2021-03-30 07:00:33 +03:00
Anton Tarasov
5ea0fb7166 JRE-1142 [jdk11] hidpi is not detected since Ubuntu 18.04
(cherry picked from commit be4f8c0d9d)
2021-03-30 07:00:32 +03:00
Anton Tarasov
d9efc8a0be JRE-1111 [JDK11] java/beans/Beans/TypoInBeanDescription.java crashes at libawt_xawt.so+0x4a30d
(cherry picked from commit b89e6aed0b)
2021-03-30 07:00:32 +03:00
Anton Tarasov
853010aa47 fix JNI_OnUnload definition
(cherry picked from the commit  3571e39071)

(cherry picked from commit 1019d8f0f2)
2021-03-30 07:00:32 +03:00
Anton Tarasov
3d65b6a862 JRE-981 IM workaround does not work anymore
forward port of 2d7c29b in JetBrains/jdk8u_jdk

(cherry picked from commit f3ccc53e02)
2021-03-30 07:00:32 +03:00
Anton Tarasov
6a1428166b JRE-938 [windows] Frame.setMaximizedBounds not hidpi-aware
(cherry picked from commit cc97899923320e1fa17f5e44975c4a0f0ba51014)
(cherry picked from commit ccfe65be7f)
2021-03-30 07:00:32 +03:00
Anton Tarasov
4582d0e1ea JRE-907 macOS: add ability to check for scaled display mode
(cherry picked from commit e496262aa1)
2021-03-30 07:00:32 +03:00
Anton Tarasov
88a47a1432 JRE-934 Diff viewer errors are not visible on HiDPI Linux
(cherry picked from commit 641a09dd52)
2021-03-30 07:00:32 +03:00
Anton Tarasov
d5b7ece30c [jdk9] HiDPI scale is not detected on some linux desktops
(cherry picked from commit 9279d80110)
2021-03-30 07:00:32 +03:00
Anton Tarasov
488956a719 JRE-681 [windows] direct drawing into frame graphics may have wrong translate
(cherry picked from commit 6ea1d45fd1)
2021-03-30 07:00:31 +03:00
Anton Tarasov
fa7d3c7f7e Read org.gnome.desktop.interface/scaling-factor
(cherry picked from commit 277357ae73)
2021-03-30 07:00:31 +03:00
Anton Tarasov
b8b72b83af 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
2021-03-30 07:00:31 +03:00
Anton Tarasov
f869aba81b Do not scale base font in HiDPI mode on Linux
(cherry picked from commit 6fb2c36529)
2021-03-30 07:00:31 +03:00
Anton Tarasov
712266e1de Allow HiDPI mode on Linux
(cherry picked from commit 34234263fb)
2021-03-30 07:00:31 +03:00
Anton Tarasov
3d2f8238c0 JRE-772 swing returns incorrect FRC when AA is off
(cherry picked from commit a161897d908aa10da6306c06452c5d6317fed2f0)
(cherry picked from commit 2bf5a7ca5c)
2021-03-30 07:00:31 +03:00
Anton Tarasov
53c2c3c4c0 JRE-729 [windows] unreasonable IME activity consumes CPU
(cherry picked from commit c3040dd1fe1bf6c03c746c76f685629fd0a8e670)
(cherry picked from commit ba22b31a49)
2021-03-30 07:00:31 +03:00
Anton Tarasov
8fa718c913 JRE-711 Horizontal grey lines appear in every window in IntelliJ Idea
(cherry picked from commit 62000130d86e5831d81cfb24659386c6930f84cf)

(cherry picked from commit e2d1655703)
2021-03-30 07:00:31 +03:00
Anton Tarasov
16a1d72839 JRE-681 [windows] direct drawing into frame graphics may have wrong translate
(cherry picked from commit ab6dee4c1fc453ad3cb5adb69fc243e550d184ae)

(cherry picked from commit 6ea1d45fd1)
2021-03-30 07:00:30 +03:00
Anton Tarasov
de8764b0fb 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 6ce31e0a32)
2021-03-30 07:00:30 +03:00
Anton Tarasov
1bae8fa078 JRE-616 [linux] notify when dpi correction factor is applied to fonts
(cherry picked from commit f57d41f3118bfd773c99ce32d58cfae16931be6a)
(cherry picked from commit 6246abc72f)
2021-03-30 07:00:30 +03:00
Anton Tarasov
197d298a7a JRE-612 [windows] icon in frame title is not dpi-aware
(cherry picked from commit dec04385177a2abb677add909d3b94f94c62a14e)

(cherry picked from commit 38466cbab0)
2021-03-30 07:00:30 +03:00
Anton Tarasov
943203af26 JRE-604 [fps] frame's client area is one pixel beneath frame's borders
Adopted.

(cherry picked from commit ef2870ee38)
2021-03-30 07:00:30 +03:00
Anton Tarasov
4b2c5cf1c4 JRE-596 [windows] popup positioning is broken with JRE-573
Adopted: moved to AwtWindow::Reshape

(cherry picked from commit c5cc28d85d)
2021-03-30 07:00:30 +03:00
Anton Tarasov
34fc4b7515 JRE-577 Goland 18 displays out of memory
(cherry picked from commit 2daaf21e420d4af15d3b1bfeb3f896074bea1e61)

(cherry picked from commit 9ea2011948)
2021-03-30 07:00:30 +03:00
Anton Tarasov
aa02d716e6 JRE-573 [windows] window client area bounds mismatch
Apply only WmEraseBkgnd

(cherry picked from commit afa68f7ad6440303c6417be3f675b1c4644b6014)

(cherry picked from commit 0651b45e13)
2021-03-30 07:00:30 +03:00
Anton Tarasov
57dd59a003 JRE-489 -Dswing.bufferPerWindow is fractional scale unfriendly
(cherry picked from commit 5e183c397b)
2021-03-30 07:00:29 +03:00
Anton Tarasov
aafb1191e0 JRE-310 check for Windows8.1 when enabling ui scale
Was "don't fallback on fractional scale" in JBSDK9.

(cherry picked from commit 263d8641974d263075c93f11c4db6208754d7325)

(cherry picked from commit deeda6fada)
2021-03-30 07:00:29 +03:00
Anton Tarasov
e9a6cbf160 JRE-382 Three AWT-tests become hanging starting since master-875
(cherry picked from commit 7d492101db8fcbb3d285fd8e9669f74b0e0fce8f)
(cherry picked from commit b965f85c1b)
2021-03-30 07:00:29 +03:00
Anton Tarasov
785902ea16 JRE-373 [macos] nativeCreateNSWindow deadlocks with a11y
(cherry picked from commit 72c77a992bbf1b95b82ffc08cb2f4f3bc36b3657)

(cherry picked from commit aa09fa2c85)
2021-03-30 07:00:29 +03:00
Anton Tarasov
ee1cb56b18 IDEA-172422 Popup at the wrong place on the second monitor (new hidpi)
Adopted: moved to AwtWindow::Reshape

(cherry picked from commit 11a0911d65)
2021-03-30 07:00:29 +03:00
Anton Tarasov
064aa036d6 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 985908cf10)
2021-03-30 07:00:29 +03:00
Anton Tarasov
2de22a7dcc JRE-269 JLabel doesn't scale <code>text</code> HTML fragments.
(cherry picked from commit 9ef72b6c3a477e4225f9b98e30fa9190613520e4)
(cherry picked from commit c17bc728ee)
2021-03-30 07:00:29 +03:00
Anton Tarasov
d23122c877 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 aeea6c1ca3)
2021-03-30 07:00:29 +03:00
Anton Tarasov
2793f41307 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 adb3a4be16)
2021-03-30 07:00:28 +03:00
Anton Tarasov
08f8426030 JRE-119 [suppress updateGC() for WFileDialogPeer/WPrintDialogPeer]
updateGC() is called from WWindowPeer.<init> 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 cec49aaa38)
2021-03-30 07:00:28 +03:00
Anton Tarasov
b1d9b6b03b 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 7d1d43bfa1)
2021-03-30 07:00:28 +03:00
Anton Tarasov
a274c553d5 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 60be76b725)
2021-03-30 07:00:28 +03:00
Anton Tarasov
73ba848167 JRE-119 [ask if ui scale is enabled natively]
(cherry picked from commit 801f45875fd8699edcbda5896210cec191062261)
(cherry picked from commit 20edebdefa)
2021-03-30 07:00:28 +03:00
Anton Tarasov
f67132e47d 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 fd615a5b45)
2021-03-30 07:00:28 +03:00
Anton Tarasov
79a4fed7ce IDEA-148854: AppCode crashes randomly every 15 mins or so
(cherry picked from commit 02f9a5fbb4924ff67c8a04c15e490acfcc750003)
(cherry picked from commit b8f4b4a9ed)
2021-03-30 07:00:28 +03:00
Vitaly Provodin
42aa96fd93 updated JTreg exclude list 2021-03-30 07:00:28 +03:00
Alexey Ushakov
3015c667b6 Resolve merge compile problems on mac
(cherry picked from commit d1ed8ab118)
2021-03-30 07:00:27 +03:00
Anton Tarasov
6d046a162c IDEA-152524 can't compile fontconfig changes on Windows
(cherry picked from commit 4c8351fecf)

(cherry picked from commit 5faebc73d5)
2021-03-30 07:00:27 +03:00
Alexey Ushakov
1640b1d467 IDEA-57233 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

(cherry picked from commit 0456745afb)
2021-03-30 07:00:27 +03:00
Vitaly Provodin
7a51e510e2 JBR-2922 add JCEF to jbrsdk binaries
& fix a misprint in get_mods_list
2021-03-30 07:00:27 +03:00
Alexey Ushakov
1917f47560 JBR-2807: JDK15: update modules.list to resolve jbr build failure
removed nashorn modules
2021-03-30 07:00:27 +03:00
Vitaly Provodin
60276ac788 JBR-2130 remove module jdk.pack 2021-03-30 07:00:27 +03:00
Vitaly Provodin
45273dc4b5 JBR-2922 add JCEF to jbrsdk binaries
& fix a misprint in get_mods_list
2021-03-30 07:00:27 +03:00
Vitaly Provodin
cee4f40055 JBR-2912 add JBR 15 builds with DCEVM 2021-03-30 07:00:27 +03:00
Vitaly Provodin
4517c6b4aa JBR-2864 initial commit of DCEVM patches reworked for 15 2021-03-30 07:00:26 +03:00
Vitaly Provodin
56a09c3f28 JBR-2812 remove --with-import-modules from configure for aarch64 2021-03-30 07:00:26 +03:00
Anton Tarasov
1b3967d813 JBR-2812 bundle jcef in jmod format instead of modular-sdk
Build test-image with non-jcef build target
2021-03-30 07:00:26 +03:00
Vitaly Provodin
7425b5503e JBR-2787 fix copying jcef files into jbr/jbrsdk binaries 2021-03-30 07:00:26 +03:00
Vitaly Provodin
178dfaaf7b JBR-2758 refactor building scripts to apply patches adding required modules instead of excluding
Add jogl and gluegen modules to support jcef osr mode
2021-03-30 07:00:26 +03:00
Anton Tarasov
5907d2098d JBR-2016 add jcef module and export packages to it
(cherry picked from commit cf997f71c6)
2021-03-30 07:00:26 +03:00
Vitaly Provodin
d5d363b040 JBR-2473 modify building scripts to add dcevm clauses, add git config to docker image
(cherry picked from commit 2620c62848)
2021-03-30 07:00:26 +03:00
Vitaly Provodin
832a3d1bf1 JBR-2473 add initial set of DCEVM patches
(cherry picked from commit c0c0a96cf4)
2021-03-30 07:00:26 +03:00
Vitaly Provodin
99603ec384 JBR-2395 eliminate JavaFX from JBR 2021-03-30 07:00:25 +03:00
Vitaly Provodin
7a49718e36 JBR-2409 fix prameters for configure 2021-03-30 07:00:25 +03:00
Vitaly Provodin
0a7fd94711 JDK14: exclude dependencies on jcef in x86, fastdebug builds 2021-03-30 07:00:25 +03:00
Vitaly Provodin
0d3bbf8b17 JBR-2396 fix CONF names 2021-03-30 07:00:25 +03:00
Vitaly Provodin
b4f2cbd524 JBR-2394 replace --disable-debug-symbols with --with-native-debug-symbols=none 2021-03-30 07:00:25 +03:00
Vitaly Provodin
e503627d72 add exec permitions to configure 2021-03-30 07:00:25 +03:00
Vitaly Provodin
86a7574548 split checkout before building JBR+JFX or JBR+JCEF on two separate commands 2021-03-30 07:00:25 +03:00
Vitaly Provodin
0db5138e8d change BOOT_JDK, fix target names 2021-03-30 07:00:25 +03:00
Vitaly Provodin
4ddcc63ee2 JBR-2291 add vendor info into bundles 2021-03-30 07:00:24 +03:00
Vitaly Provodin
e9322f1287 JBR-2324 address new layout in mac jcef 80.0.4+g74f7b0c+chromium-80.0.3987.122 2021-03-30 07:00:24 +03:00
Vitaly Provodin
3cda26ca28 JBR-2320 add jdk.attach module into JBR 2021-03-30 07:00:24 +03:00
Vitaly Provodin
b565e55c4d JBR-2217 provide JCEF-only (no JavaFX) bundle for master/202 branches 2021-03-30 07:00:24 +03:00
Vitaly Provodin
f77d77d42b JBR-2212 add scripts for linux_x86, linux_aarch64, linux_x64_fastdebug, osx_fastdebug, windows_x86 2021-03-30 07:00:24 +03:00
Vitaly Provodin
d874254942 JBR-1643 fix intermittent fialures of Windows builds at make/Init.gmk:304
combine images and test-image into one make invocation
2021-03-30 07:00:24 +03:00
Vitaly Provodin
6b4d94958d JBR-2181 create two separate JBR bundles with JFX and JFX+JCEF 2021-03-30 07:00:24 +03:00
Vitaly Provodin
e9d4b683bc JBR-2148 modify signapp&build scripts to match to the new layout 2021-03-30 07:00:24 +03:00
Vitaly Provodin
18f8caf5a4 JBR-2084 modify scripts to sign Contents/MacOS/libjli.dylib as a a normal file 2021-03-30 07:00:23 +03:00
Vitaly Provodin
7e87597920 JBR-1821 notarize JBR bundles as a standalone app 2021-03-30 07:00:23 +03:00
Vitaly Provodin
3d2327c79c JBR-2162 move building scripts from TC to JBR repo 2021-03-30 07:00:23 +03:00
Anton Tarasov
b3422198cc JBR-2016 add jcef module and export some sun.* packages to it 2021-03-30 07:00:23 +03:00
Vitaly Provodin
4f16251c65 JBR-2014 add jdk.hotspot.agent module to jbr 2021-03-30 07:00:23 +03:00
Vitaly Provodin
01c4f317cd JBR-1286 add jdk.compiler into JBR 2021-03-30 07:00:23 +03:00
Vitaly Provodin
d647fc1e36 JBR-1199 add JBR modules list for jlink 2021-03-30 07:00:23 +03:00
Vitaly Provodin
ee992c7cbd Update docker script to create jdk15 build env 2021-03-30 07:00:23 +03:00
Vitaly Provodin
85e467d8c6 JBR-3045 add pressing ESC to close the dialog after test completion
(cherry picked from commit 44d8b28b0b)
2021-03-30 07:00:22 +03:00
Vitaly Provodin
6b9e957239 JBR-3040 press the button END at the beggining in order to avoid text selection
(cherry picked from commit 1c2bf33db2)
2021-03-30 07:00:22 +03:00
Vitaly.Provodin
239bfeaed1 updated JTreg exclude list 2021-03-30 07:00:22 +03:00
138 changed files with 29195 additions and 260 deletions

0
configure vendored Normal file → Executable file
View File

View File

@@ -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"

View File

@@ -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

View File

@@ -0,0 +1,54 @@
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
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"
}
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
echo $(ls $__mods) | sed s/\.jmod/,/g | sed s/,$//g | sed s/' '//g
}

View File

@@ -0,0 +1,84 @@
#!/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/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 \
--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} \
--with-boot-jdk=${BOOT_JDK} \
--enable-cds=yes || 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-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 ...
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-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 $?

View File

@@ -0,0 +1,137 @@
#!/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:
# <empty> 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)
#
# Environment variables:
# 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')
JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64}
source jb/project/tools/common/scripts/common.sh
function create_image_bundle {
__bundle_name=$1
__arch_name=$2
__modules_path=$3
__modules=$4
[ "$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 "$__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
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"
}
WITH_DEBUG_LEVEL="--with-debug-level=release"
RELEASE_NAME=linux-x86_64-server-release
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=""
;;
"fd")
do_reset_changes=1
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
RELEASE_NAME=linux-x86_64-server-fastdebug
;;
esac
sh configure \
--disable-warnings-as-errors \
$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 $?
make clean CONF=$RELEASE_NAME || exit $?
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
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
jbr_name_postfix="_${bundle_type}"
fi
# 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 $?
# 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 $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

View File

@@ -0,0 +1,81 @@
#!/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/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 \
--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} \
--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 $?
JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number}
BASE_DIR=build/linux-x86-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 ...
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 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 $?

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,139 @@
#!/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:
# <empty> 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)
#
# Environment variables:
# 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')
JCEF_PATH=${JCEF_PATH:=./jcef_mac}
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
__arch_name=$2
__modules_path=$3
__modules=$4
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/$__arch_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 $?
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" "$__arch_name" || do_exit $?
rm -rf "$tmp"
}
WITH_DEBUG_LEVEL="--with-debug-level=release"
RELEASE_NAME=macosx-x86_64-server-release
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=""
;;
"fd")
do_reset_changes=1
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
RELEASE_NAME=macosx-x86_64-server-fastdebug
;;
esac
sh configure \
--disable-warnings-as-errors \
$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 $?
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
JSDK_MODS_DIR=$IMAGES_DIR/jmods
JBRSDK_BUNDLE=jbrsdk
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
jbr_name_postfix="_${bundle_type}"
fi
# 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 $?
# 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" "$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

View File

@@ -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

View File

@@ -0,0 +1,94 @@
#!/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" \
"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 \) \
-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 \;

View File

@@ -0,0 +1,138 @@
#!/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
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"
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 -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"

View File

@@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
From 960dafbeeba190911955c208b611fecc15d66738 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
From 39df5f163d4a0f1fd6b92313a5570808f19d5e20 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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<vm_class_loader_data> 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<mtClass> {
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

View File

@@ -0,0 +1,135 @@
From 5af1daedc86b5fec0f222cbdda3afbdf518985ea Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,57 @@
From 19d2274a5dff6e6b31474252b45e5e7484f0180b Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
From ca47ab5a0a6ce8e2644736f323a335a957311af9 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,26 @@
From 7e236beee0375656d1955fc1168143c1639fb7f1 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,25 @@
From d56e73885111b386771f564ec6beb305338993df Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,71 @@
From 7ebad43ed45805b0a3736c510f708ff17697ba7e Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,26 @@
From 5c7e5f245f79d7e8575461dab0c356ed74c8e9a3 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,193 @@
From 6ffac6e5064ec6633fdbeb8520333dca00bc6a62 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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 <init> 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

View File

@@ -0,0 +1,26 @@
From dc675de6ac42819b8536827ea450fcad13a97448 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,183 @@
From 1d682efa88c716e1849163d5abff3a3367581d16 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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<HeapWord*>(q) != compact_top || (size_t)q->size() != size) {
+ if (force_forward || cast_from_oop<HeapWord*>(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

View File

@@ -0,0 +1,942 @@
From 297f564f6af79fb824f5b4e9119f1d3d0c827fb0 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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<Method*>* _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<Klass*>* local_interfaces() const { return _local_interfaces; }
+ Array<InstanceKlass*>* 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<vm_class_loader_data> exchange = _holder;
+ WeakHandle<vm_weak_data> 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<HeapWord*>(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<HeapWord*>(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<HeapWord*>(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<HeapWord*>(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<HeapWord*>(old_obj) + original_size < cast_from_oop<HeapWord*>(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<HeapWord*>* 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<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(new_obj), size);
}
} else {
- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size);
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(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<HeapWord*>(q) >= cast_from_oop<HeapWord*>(new_location) && cast_from_oop<HeapWord*>(q) < cast_from_oop<HeapWord*>(new_location) + new_size) ||
+ (cast_from_oop<HeapWord*>(new_location) >= cast_from_oop<HeapWord*>(q) && cast_from_oop<HeapWord*>(new_location) < cast_from_oop<HeapWord*>(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<HeapWord*>(tmp_obj), cast_from_oop<HeapWord*>(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<HeapWord*>(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<HeapWord*>(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<HeapWord*>(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<HeapWord*>(old_obj) + original_size < cast_from_oop<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.
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<int> &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<Method*>* VM_EnhancedRedefineClasses::_old_methods = NULL;
Array<Method*>* 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<HeapWord*>(o), cast_from_oop<HeapWord*>(_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<Klass*>* old_interfaces = the_class->transitive_interfaces();
+ Array<InstanceKlass*>* 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<Klass*>* new_interfaces = new_class->transitive_interfaces();
+ Array<InstanceKlass*>* new_interfaces = new_class->transitive_interfaces();
for (i = 0; i<new_interfaces->length(); 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<Klass*>* local_interfaces = parser.local_interfaces();
+ Array<InstanceKlass*>* 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<Klass*>* local_interfaces = klass->local_interfaces();
+ Array<InstanceKlass*>* 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

View File

@@ -0,0 +1,25 @@
From 336cab4f72c6e642e3077ea8d1a4860de33f5a4d Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,133 @@
From cea4e2cca3c37233c728be7235f8f9d8be136cb5 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,211 @@
From 4f88dcec830d39452f69d1117729469fdb768a8f Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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<oop>* _oops_to_add;
+public:
+ AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {};
+ bool operator()(WeakHandle<vm_resolved_method_table_data>* 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<oop>* oops_to_add = new GrowableArray<oop>();
-
- 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<oop> 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<vm_resolved_method_table_data> wh = WeakHandle<vm_resolved_method_table_data>::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

View File

@@ -0,0 +1,88 @@
From 5379e56465d3d3930ec7ea91b1c64db2cdf70170 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,67 @@
From c6ea68e66d37d70739f7b0ee74131322b4526a68 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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<Klass*>* _affected_klasses;
--
2.23.0

View File

@@ -0,0 +1,43 @@
From 507d97966c7145d0ae2533459cc504c7b0d6d5b6 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,32 @@
From b516b615c20fafa2094dfb9f4cb08245b26418d0 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,29 @@
From c6498946006879314bdc6218ee72da5d9c88f237 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,24 @@
From 86c27155386c1c40642c99c63a242d1f5d8601a5 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,54 @@
From 025d0d2903963fb79f83cf0d90418783d3ef6813 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,28 @@
From 27aabfefe7d799545049bb81ba19d4ed2ff6379c Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,28 @@
From 9b405cb642d5935c39c8dbd522ea2fdecfc29ef3 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,91 @@
From 40fe40884d4efc50864bb3f2dd88f0a2e7122d5a Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,27 @@
From 29920b076b4ad96d85adbce0a1d947e5022ba3ad Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,49 @@
From 1f13b20ab5553182680045b7d7324ff92da7e7f0 Mon Sep 17 00:00:00 2001
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
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

View File

@@ -0,0 +1,119 @@
#!/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:
# <empty> 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)
#
# Environment variables:
# 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)
JCEF_PATH=${JCEF_PATH:=$WORK_DIR/jcef_win_x64}
source jb/project/tools/common/scripts/common.sh
function create_image_bundle {
__bundle_name=$1
__modules_path=$2
__modules=$3
[ -d $__bundle_name ] && rm -rf $__bundle_name
echo Running jlink ...
${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"
RELEASE_NAME=windows-x86_64-server-release
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=""
;;
"fd")
do_reset_changes=1
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
RELEASE_NAME=windows-x86_64-server-fastdebug
;;
esac
sh ./configure \
--disable-warnings-as-errors \
$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-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 $?
else
make LOG=info CONF=$RELEASE_NAME clean images || do_exit $?
fi
IMAGES_DIR=build/$RELEASE_NAME/images
JSDK=$IMAGES_DIR/jdk
JSDK_MODS_DIR=$IMAGES_DIR/jmods
JBRSDK_BUNDLE=jbrsdk
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
jbr_name_postfix="_${bundle_type}"
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 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 $?
do_exit 0

View File

@@ -0,0 +1,63 @@
#!/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/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 \
--disable-warnings-as-errors \
--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 \
--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
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}
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

View File

@@ -0,0 +1,77 @@
#!/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:
# <empty> or nomod - the bundles without any additional modules (jcef)
# jcef - the 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)
#
source jb/project/tools/common/scripts/common.sh
JBSDK_VERSION=$1
JDK_BUILD_NUMBER=$2
build_number=$3
bundle_type=$4
function pack_jbr {
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}
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 $?
}
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/$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 $?
fi
pack_jbr $bundle_type
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 $?
fi

View File

@@ -0,0 +1,42 @@
#!/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
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
JBR_BASE_NAME=jbr-$JBSDK_VERSION
IMAGES_DIR=build/windows-x86-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

View File

@@ -73,6 +73,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
@@ -167,7 +168,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), \
))

54
modules.list Normal file
View File

@@ -0,0 +1,54 @@
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.aot,
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.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.sctp,
jdk.security.auth,
jdk.security.jgss,
jdk.unsupported,
jdk.xml.dom,
jdk.zipfs,
jdk.hotspot.agent

View File

@@ -1147,7 +1147,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree *loop, ProjNode*
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;

View File

@@ -1,6 +1,5 @@
#include "version.rc"
#define IDI_ICON 2000
#include "java_rc.h"
/////////////////////////////////////////////////////////////////////////////
//

View File

@@ -0,0 +1,6 @@
#ifndef _JAVA_RC_H_
#define _JAVA_RC_H_
#define IDI_ICON 2000
#endif // _JAVA_RC_H_

View File

@@ -82,11 +82,11 @@ public class AquaImageFactory {
}
static Image getGenericJavaIcon() {
return java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() {
return checkValidOrStub(java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() {
public Image run() {
return com.apple.eawt.Application.getApplication().getDockIconImage();
}
});
}));
}
static String getPathToThisApplication() {
@@ -500,4 +500,23 @@ public class AquaImageFactory {
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;
}
}

View File

@@ -78,6 +78,7 @@ import sun.java2d.SurfaceData;
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
@@ -1510,4 +1511,17 @@ public class LWWindowPeer
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];
}
}

View File

@@ -99,7 +99,7 @@ class CAccessible extends CFRetainedResource implements Accessible {
@Override
public AccessibleContext getAccessibleContext() {
return accessible.getAccessibleContext();
return accessible != null ? accessible.getAccessibleContext() : null;
}
public void addNotificationListeners(Component c) {

View File

@@ -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.Character.Subset;
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;
@@ -292,6 +297,18 @@ public class CInputMethod extends InputMethodAdapter {
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) {
@@ -587,6 +604,7 @@ public class CInputMethod extends InputMethodAdapter {
final String[] retString = new String[1];
try {
if (fIMContext != null)
LWCToolkit.invokeAndWait(new Runnable() {
public void run() { synchronized(retString) {
int location = locationIn;
@@ -639,6 +657,7 @@ public class CInputMethod extends InputMethodAdapter {
final int[] returnValue = new int[2];
try {
if (fIMContext != null)
LWCToolkit.invokeAndWait(new Runnable() {
public void run() { synchronized(returnValue) {
AttributedCharacterIterator theIterator = fIMContext.getSelectedText(null);
@@ -714,36 +733,38 @@ public class CInputMethod extends InputMethodAdapter {
final int[] rect = new int[4];
try {
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;
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));
// 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)) {
// 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 (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);
}, (sun.awt.im.InputContext)fIMContext, fAwtFocussedComponent);
}
} catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(rect) { return rect; }
@@ -758,12 +779,14 @@ public class CInputMethod extends InputMethodAdapter {
final int[] insertPositionOffset = new int[1];
try {
LWCToolkit.invokeAndWait(new Runnable() {
public void run() { synchronized(offsetInfo) {
offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY);
insertPositionOffset[0] = fIMContext.getInsertPositionOffset();
}}
}, fAwtFocussedComponent);
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.
@@ -813,4 +836,63 @@ public class CInputMethod extends InputMethodAdapter {
// 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;
}
// Executed on AppKit
static void invoke(Runnable runnable, sun.awt.im.InputContext inputContext, Component targetToAppContext) throws InvocationTargetException {
AtomicBoolean runOnAppKit = new AtomicBoolean(false);
// 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();
}
}, targetToAppContext);
if (runOnAppKit.get()) {
runnable.run();
}
}
}
}

View File

@@ -25,6 +25,7 @@
package sun.lwawt.macosx;
import java.awt.AWTError;
import java.awt.Color;
import java.awt.Component;
import java.awt.DefaultKeyboardFocusManager;
@@ -51,6 +52,7 @@ import java.util.Comparator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.security.PrivilegedAction;
import javax.swing.JRootPane;
import javax.swing.RootPaneContainer;
@@ -61,6 +63,7 @@ import com.apple.laf.ClientPropertyApplicator.Property;
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;
@@ -323,26 +326,36 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
} else {
bounds = _peer.constrainBounds(_target.getBounds());
}
AtomicLong ref = new AtomicLong();
contentView.execute(viewPtr -> {
boolean hasOwnerPtr = false;
long nativeWindowPtr = java.security.AccessController.doPrivileged(
(PrivilegedAction<Long>) () -> {
try {
return InvokeOnToolkitHelper.invokeAndBlock(() -> {
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 (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());
}
});
}
if (!hasOwnerPtr) {
ref.set(nativeCreateNSWindow(viewPtr, 0,
styleBits, bounds.x, bounds.y,
bounds.width, bounds.height));
}
});
setPtr(ref.get());
setPtr(nativeWindowPtr);
if (target instanceof javax.swing.RootPaneContainer) {
final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();

View File

@@ -85,27 +85,15 @@ import java.awt.peer.TaskbarPeer;
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.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.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;
@@ -494,9 +482,9 @@ public final class LWCToolkit extends LWToolkit {
public Insets getScreenInsets(final GraphicsConfiguration gc) {
GraphicsDevice gd = gc.getDevice();
if (!(gd instanceof CGraphicsDevice)) {
return super.getScreenInsets(gc);
return InvokeOnToolkitHelper.invokeAndBlock(() -> super.getScreenInsets(gc));
}
return ((CGraphicsDevice)gd).getScreenInsets();
return InvokeOnToolkitHelper.invokeAndBlock(() -> ((CGraphicsDevice)gd).getScreenInsets());
}
@Override
@@ -725,12 +713,19 @@ public final class LWCToolkit extends LWToolkit {
},
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 (!InvokeOnToolkitHelper.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()).getSystemEventQueueImpl().postEvent(invocationEvent);
}
}
doAWTRunLoop(mediator, false);
checkException(invocationEvent);
}

View File

@@ -1106,6 +1106,17 @@ JNI_COCOA_ENTER(env);
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
@@ -1115,7 +1126,12 @@ JNI_COCOA_ENTER(env);
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);

View File

@@ -158,9 +158,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, "<init>", "(IIII)V", ret);
ret = (*env)->NewObject(env, jc_DisplayMode, jc_DisplayMode_ctor, w, h, bpp, refrate);
DECLARE_METHOD_RETURN(jc_DisplayMode_ctor, jc_DisplayMode, "<init>", "(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;

View File

@@ -94,6 +94,7 @@ class GTKEngine {
static enum Settings {
GTK_FONT_NAME,
GTK_ICON_SIZES,
GTK_XFT_DPI,
GTK_CURSOR_BLINK,
GTK_CURSOR_BLINK_TIME
}

View File

@@ -45,6 +45,7 @@ import java.util.Map;
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;
@@ -1446,6 +1447,18 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
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.setXftDpi(dpi);
}
}
static ReferenceQueue<GTKLookAndFeel> queue = new ReferenceQueue<GTKLookAndFeel>();

View File

@@ -30,8 +30,10 @@ import java.awt.geom.AffineTransform;
import javax.swing.plaf.FontUIResource;
import java.util.StringTokenizer;
import sun.awt.AWTAccessor;
import sun.font.FontConfigManager;
import sun.font.FontUtilities;
import sun.java2d.SunGraphicsEnvironment;
/**
* @author Shannon Hickey
@@ -161,11 +163,15 @@ class PangoFonts {
*/
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);
}
if (value instanceof Integer) {
dpi = ((Integer)value).intValue() / 1024;
if (dpi == -1) {
if (dpi == -1 || SunGraphicsEnvironment.isUIScaleEnabled(dpi)) {
dpi = 96;
}
if (dpi < 50) { /* 50 dpi is the minimum value gnome allows */
@@ -175,6 +181,12 @@ class PangoFonts {
* 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.

View File

@@ -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;
@@ -93,6 +94,10 @@ import javax.swing.JRootPane;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.ComponentFactory;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction;
import sun.awt.AppContext;
import sun.awt.AWTAccessor;
import sun.awt.ConstrainableGraphics;
import sun.awt.EmbeddedFrame;
import sun.awt.RequestFocusController;
@@ -612,6 +617,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
long eventMask = AWTEvent.INPUT_METHODS_ENABLED_MASK;
private static final boolean INPUT_METHODS_DISABLED;
/**
* Static properties for incremental drawing.
* @see #imageUpdate
@@ -633,6 +640,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
s = java.security.AccessController.doPrivileged(
new GetPropertyAction("awt.image.redrawrate"));
incRate = (s != null) ? Integer.parseInt(s) : 100;
INPUT_METHODS_DISABLED = java.security.AccessController.doPrivileged(new GetBooleanAction("awt.ime.disabled"));
}
/**
@@ -1189,7 +1198,15 @@ public abstract class Component implements ImageObserver, MenuContainer,
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) {
@@ -1623,6 +1640,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
* @since 1.2
*/
public void enableInputMethods(boolean enable) {
if (INPUT_METHODS_DISABLED) return;
if (enable) {
if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0)
return;
@@ -5148,6 +5166,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
boolean areInputMethodsEnabled() {
if (INPUT_METHODS_DISABLED) return false;
// in 1.2, we assume input method support is required for all
// components that handle key events, but components can turn off
// input methods by calling enableInputMethods(false).

View File

@@ -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 final class DisplayMode {
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 final class DisplayMode {
return refreshRate;
}
private boolean isDefault() {
return isDefault;
}
/**
* Returns whether the two display modes are equal.
*

View File

@@ -1397,6 +1397,11 @@ public abstract class Toolkit {
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(

View File

@@ -3984,6 +3984,31 @@ public class Window extends Container implements Accessible {
}
}
private volatile boolean hasCustomDecoration;
boolean hasCustomDecoration() {
return hasCustomDecoration;
}
/**
* Set via reflection (JB JdkEx API).
*/
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 *******************************

View File

@@ -118,4 +118,20 @@ public interface WindowPeer extends ContainerPeer {
* Instructs the peer to update the position of the security warning.
*/
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; }
/**
* Returns platform window handle.
*
* @return the window handle
*/
default long getWindowHandle() {
throw new UnsupportedOperationException("unimplemented");
}
}

View File

@@ -27,7 +27,10 @@ package javax.swing;
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;
@@ -1612,7 +1615,8 @@ public class RepaintManager
*/
protected void paintDoubleBuffered(JComponent c, Image image,
Graphics g, int clipX, int clipY,
int clipW, int clipH) {
int clipW, int clipH)
{
if (image instanceof VolatileImage && isPixelsCopying(c, g)) {
paintDoubleBufferedFPScales(c, image, g, clipX, clipY, clipW, clipH);
} else {

View File

@@ -62,7 +62,7 @@ import java.util.HashMap;
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
@@ -385,6 +385,11 @@ public class UIManager implements Serializable
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",

View File

@@ -27,14 +27,13 @@ package javax.swing.plaf.basic;
import java.io.*;
import java.awt.*;
import java.net.URL;
import java.security.PrivilegedAction;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import sun.swing.SwingUtilities2;
/**
* Support for providing html views for the swing components.
* This translates a simple html string to a javax.swing.text.View
@@ -45,6 +44,14 @@ import sun.swing.SwingUtilities2;
* @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>)
() -> Boolean.getBoolean(
"javax.swing.rebaseCssSizeMap"));
private final static String JLABEL_USER_CSS_KEY = "javax.swing.JLabel.userStyleSheet";
/**
* Constructs a {@code BasicHTML}.
@@ -63,6 +70,12 @@ public class BasicHTML {
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);
@@ -411,6 +424,10 @@ public class BasicHTML {
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());
}
}
}

View File

@@ -1923,9 +1923,24 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory {
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<view.getViewCount(); i++) {
forwardPreferenceChangeToView(view.getView(i));
}
}
private void dropIndexChanged() {
if (editor.getDropMode() == DropMode.USE_SELECTION) {
return;

View File

@@ -292,6 +292,15 @@ public abstract class FlowView extends BoxView {
strategy.changedUpdate(this, changes, getInsideAllocation(a));
}
/** {@inheritDoc} */
@Override
public void preferenceChanged(View child, boolean width, boolean height) {
super.preferenceChanged(child, width, height);
if (strategy instanceof TextLayoutStrategy) {
((TextLayoutStrategy) strategy).syncFRC(this);
}
}
/** {@inheritDoc} */
public void setParent(View parent) {
super.setParent(parent);

View File

@@ -24,7 +24,10 @@
*/
package javax.swing.text;
import sun.swing.SwingUtilities2;
import java.awt.*;
import java.awt.geom.AffineTransform;
/**
* A class to perform rendering of the glyphs.
@@ -221,6 +224,15 @@ class GlyphPainter1 extends GlyphView.GlyphPainter {
@SuppressWarnings("deprecation")
void sync(GlyphView v) {
if (metrics != null) {
AffineTransform frcTx = metrics.getFontRenderContext().getTransform();
AffineTransform newFrcTx = SwingUtilities2.getFontRenderContext(v.getContainer()).getTransform();
if (frcTx.getScaleX() != newFrcTx.getScaleX() ||
frcTx.getScaleY() != newFrcTx.getScaleY())
{
metrics = null;
}
}
Font f = v.getFont();
FontMetrics fm = null;
Container c = v.getContainer();

View File

@@ -33,6 +33,7 @@ import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
import javax.swing.event.DocumentEvent;
import sun.font.BidiUtils;
import sun.swing.SwingUtilities2;
/**
* A flow strategy that uses java.awt.font.LineBreakMeasureer to
@@ -280,6 +281,18 @@ class TextLayoutStrategy extends FlowView.FlowStrategy {
return pos;
}
/**
* Synchronize the strategy if the container's FRC scale changes.
*/
void syncFRC(FlowView fv) {
AffineTransform newFrcTx = SwingUtilities2.getFontRenderContext(fv.getContainer()).getTransform();
if (frcTx.getScaleX() != newFrcTx.getScaleX() ||
frcTx.getScaleY() != newFrcTx.getScaleY())
{
sync(fv);
}
}
/**
* Synchronize the strategy with its FlowView. Allows the strategy
* to update its state to account for changes in that portion of the
@@ -293,6 +306,8 @@ class TextLayoutStrategy extends FlowView.FlowStrategy {
Container container = fv.getContainer();
FontRenderContext frc = sun.swing.SwingUtilities2.
getFontRenderContext(container);
frcTx = frc.getTransform();
BreakIterator iter;
Container c = fv.getContainer();
if (c != null) {
@@ -335,6 +350,7 @@ class TextLayoutStrategy extends FlowView.FlowStrategy {
private LineBreakMeasurer measurer;
private AttributedSegment text;
private AffineTransform frcTx = new AffineTransform();
/**
* Implementation of AttributedCharacterIterator that supports

View File

@@ -767,6 +767,7 @@ public final class AWTAccessor {
*/
public interface ToolkitAccessor {
void setPlatformResources(ResourceBundle bundle);
void setDesktopProperty(Toolkit tk, String prop, Object value);
}
/*

View File

@@ -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<LinkedBlockingQueue<InvocationEvent>> invocations = new Stack<>();
// invocations should be dispatched on proper EDT (per AppContext)
private static final Map<Thread, InvokeOnToolkitHelper> 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.
* <p>
* If Toolkit posts invocation events caused by the callable, those events are intercepted and dispatched on EDT out of order.
* <p>
* When called on non-EDT, the method invokes the callable in place.
*/
public static <T> T invokeAndBlock(Callable<T> 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> T invoke(Callable<T> 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<InvocationEvent> currentQueue;
synchronized (invocations) {
invocations.push(currentQueue = new LinkedBlockingQueue<>());
}
FutureTask<T> task = new FutureTask<T>(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());
}
}

View File

@@ -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 class SunDisplayChanger {
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<DisplayChangedListener> cloneSet;
synchronized(listeners) {
cloneSet = new HashSet<DisplayChangedListener>(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 class SunDisplayChanger {
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<DisplayChangedListener> cloneSet;
private void notifyChanged(Consumer<DisplayChangedListener> 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
synchronized (listeners) {
cloneSet = new HashSet<DisplayChangedListener>(listeners.keySet());
// Preserve "weakness" of the original map to avoid OOME.
WeakHashMap<DisplayChangedListener, Void> cloneMap;
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

View File

@@ -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;

View File

@@ -371,8 +371,9 @@ public final class SunGraphics2D
// 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 WWindowPeer.getGraphics
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));

View File

@@ -40,15 +40,18 @@ import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.peer.ComponentPeer;
import java.security.PrivilegedAction;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.AccessController;
import java.util.Locale;
import java.util.TreeMap;
import sun.awt.DisplayChangedListener;
import sun.awt.SunDisplayChanger;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
import sun.font.FontManagerForSGE;
import sun.font.*;
import sun.java2d.pipe.Region;
import sun.security.action.GetPropertyAction;
@@ -65,17 +68,50 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
private static final boolean uiScaleEnabled;
private static final Object UI_SCALE_LOCK = new Object();
private static boolean uiScaleEnabled;
private static Boolean uiScaleEnabled_overridden;
private static final double debugScale;
static {
uiScaleEnabled = "true".equals(AccessController.doPrivileged(
new GetPropertyAction("sun.java2d.uiScale.enabled", "true")));
uiScaleEnabled = FontUtilities.isMacOSX ||
("true".equals(AccessController.doPrivileged(
new GetPropertyAction("sun.java2d.uiScale.enabled", "true"))) &&
(isWindows_8_1_orUpper() || FontUtilities.isLinux));
if (uiScaleEnabled && FontUtilities.isWindows) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
System.setProperty("swing.bufferPerWindow", "false"); // todo: until JRE-489 is fixed
return null;
});
}
debugScale = uiScaleEnabled ? getScaleFactor("sun.java2d.uiScale") : -1;
}
protected GraphicsDevice[] screens;
private static boolean isWindows_8_1_orUpper() {
if (!FontUtilities.isWindows) return false;
String osVersion = AccessController.doPrivileged(new GetPropertyAction("os.version"));
if (osVersion == null) return false;
String[] parts = osVersion.split("\\.");
if (parts.length < 1) return false;
try {
int majorVer = Integer.parseInt(parts[0]);
if (majorVer > 6) return true;
if (majorVer < 6) return false;
if (parts.length < 2) return false;
int minorVer = Integer.parseInt(parts[1]);
if (minorVer >= 3) return true;
} catch (NumberFormatException e) {
}
return false;
}
/**
* Returns an array of all of the screen devices.
*/
@@ -289,7 +325,27 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
}
public static boolean isUIScaleEnabled() {
return uiScaleEnabled;
Boolean enabledOverridden = uiScaleEnabled_overridden;
return enabledOverridden != null ? enabledOverridden : uiScaleEnabled;
}
/**
* Overrides isUIScaleEnabled() to false for fractional scale on Linux.
*
* [tav] todo: temp until fract scale is supported on Linux
*/
public static boolean isUIScaleEnabled(int dpi) {
if (FontUtilities.isLinux) {
if (uiScaleEnabled_overridden == null) {
synchronized (UI_SCALE_LOCK) {
if (uiScaleEnabled_overridden == null) {
uiScaleEnabled_overridden =
Double.compare(dpi / 96.0, Math.floor(dpi / 96.0)) == 0 && uiScaleEnabled;
}
}
}
}
return isUIScaleEnabled();
}
public static double getDebugScale() {

View File

@@ -178,8 +178,8 @@ public class SwingUtilities2 {
Map<Object, Object> hints = (Map<Object, Object>) 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);
@@ -1251,6 +1251,14 @@ public class SwingUtilities2 {
GraphicsConfiguration gc = c.getGraphicsConfiguration();
AffineTransform tx = (gc == null) ? null : gc.getDefaultTransform();
// [tav] workaround deadlock on MacOSX until fixed, JRE-226
if (!FontUtilities.isMacOSX && tx == null && !GraphicsEnvironment.isHeadless()) {
tx = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration()
.getDefaultTransform();
}
Object aaHint = c.getClientProperty(KEY_TEXT_ANTIALIASING);
return getFRCFromCache(tx, aaHint);
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,24 +25,40 @@
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "jvm_md.h"
#include "sunfontids.h"
#include "sun_font_FreetypeFontScaler.h"
#include <stdlib.h>
#if !defined(_WIN32) && !defined(__APPLE_)
#include <dlfcn.h>
#if defined(_WIN32) || defined(MACOSX)
#define DISABLE_FONTCONFIG
#endif
#include <math.h>
#ifndef DISABLE_FONTCONFIG
#include <dlfcn.h>
#else
#define DISABLE_FONTCONFIG
#endif
#include "ft2build.h"
#include FT_LCD_FILTER_H
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_BBOX_H
#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
#ifndef DISABLE_FONTCONFIG
/* Use bundled fontconfig.h for now */
#include "fontconfig.h"
#endif
#include "fontscaler.h"
@@ -50,6 +66,24 @@
#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 MAX_DPI 1024
#define ADJUST_FONT_SIZE(X, DPI) (((X)*DEFAULT_DPI + ((DPI)>>1))/(DPI))
#ifndef DISABLE_FONTCONFIG
#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:
@@ -81,7 +115,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;
@@ -97,12 +136,135 @@ void z_error(char *s) {}
/**************** Error handling utilities *****************/
static jmethodID invalidateScalerMID;
static jmethodID getDefaultToolkitMID;
static jclass tkClass;
static jmethodID getScreenResolutionMID;
static jfieldID platNameFID;
#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);
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;
static jboolean logFFS = JNI_FALSE;
#ifndef DISABLE_FONTCONFIG
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 DISABLE_FONTCONFIG
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) {
char *fssLogEnabled = getenv("OPENJDK_LOG_FFS");
if (fssLogEnabled != NULL && !strcmp(fssLogEnabled, "yes")) {
logFFS = JNI_TRUE;
}
invalidateScalerMID =
(*env)->GetMethodID(env, FFSClass, "invalidateScaler", "()V");
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 DISABLE_FONTCONFIG
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;
}
/* 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;
}
static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) {
@@ -265,7 +427,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;
}
/*
@@ -537,6 +699,33 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
return ptr_to_jlong(context);
}
#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 = 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
#define FT_MATRIX_OBLIQUE_XY 0x0366A
@@ -559,30 +748,220 @@ 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;
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, context->ptsz, 72, 72);
errCode = FT_Set_Char_Size(scalerInfo->face, 0, ADJUST_FONT_SIZE(context->ptsz, dpi), dpi, dpi);
if (errCode) return errCode;
if (errCode == 0) {
errCode = FT_Activate_Size(scalerInfo->face->size);
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 DISABLE_FONTCONFIG
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);
(*FcConfigSubstitutePtr)(0, fcPattern, FcMatchFont);
(*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;
}
}
if (fcHintingSet && !fcHinting) {
fcHintStyleSet = FcTrue;
fcHintStyle = FC_HINT_NONE;
}
if (fcHintStyleSet && fcHintStyle == FC_HINT_NONE) {
fcHinting = FcFalse;
}
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);
}
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
setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, FT_LOAD_DEFAULT, FT_RENDER_MODE_NORMAL);
}
else if (context->aaType == TEXT_AA_OFF) { // No AA
setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet, FT_LOAD_TARGET_MONO, FT_RENDER_MODE_MONO);
} 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 ");
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 ");
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 ");
break;
}
}
}
if (fcRGBA == FC_RGBA_UNKNOWN) {
if (context->aaType == TEXT_AA_LCD_HRGB ||
context->aaType == TEXT_AA_LCD_HBGR) {
setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet,
FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD);
} else {
setupLoadRenderFlags(context, fcHintStyle, fcAutohint, fcAutohintSet,
FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V);
}
}
}
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
@@ -599,7 +978,7 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative(
jlong pScalerContext, jlong pScaler) {
jobject metrics;
jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my;
jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my, txx, txy, tyx, tyy;
jfloat f0 = 0.0;
FTScalerContext *context =
(FTScalerContext*) jlong_to_ptr(pScalerContext);
@@ -615,7 +994,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,
@@ -678,6 +1057,20 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative(
scalerInfo->face->size->metrics.y_scale));
my = 0;
// apply transformation matrix
txx = (jfloat) FTFixedToFloat(context->transform.xx);
txy = (jfloat) -FTFixedToFloat(context->transform.xy);
tyx = (jfloat) -FTFixedToFloat(context->transform.yx);
tyy = (jfloat) FTFixedToFloat(context->transform.yy);
ax = txy * ay;
ay = tyy * ay;
dx = txy * dy;
dy = tyy * dy;
lx = txy * ly;
ly = tyy * ly;
my = tyx * mx;
mx = txx * mx;
metrics = (*env)->NewObject(env,
sunFontIDs.strikeMetricsClass,
sunFontIDs.strikeMetricsCtr,
@@ -900,18 +1293,52 @@ static jlong
GlyphInfo *glyphInfo;
int renderFlags = FT_LOAD_DEFAULT, target;
FT_GlyphSlot ftglyph;
FT_Library library;
FTScalerContext* context =
(FTScalerContext*) jlong_to_ptr(pScalerContext);
FTScalerInfo *scalerInfo =
(FTScalerInfo*) jlong_to_ptr(pScaler);
if (isNullScalerContext(context) || scalerInfo == NULL) {
return ptr_to_jlong(getNullGlyphImage());
if (logFFS) {
fprintf(stderr, "FFS_LOG: getGlyphImageNative '%c'(%d) ",
(glyphCode >= 0x20 && glyphCode <=0x7E)? glyphCode : ' ',
glyphCode);
}
error = setupFTContext(env, font2D, scalerInfo, context);
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());
}
@@ -957,6 +1384,8 @@ static jlong
}
ftglyph = scalerInfo->face->glyph;
library = ftglyph->library;
FT_Library_SetLcdFilter (library, context->lcdFilter);
/* apply styles */
if (context->doBold) { /* if bold style */
@@ -1107,7 +1536,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;
}
@@ -1170,7 +1599,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;
}
@@ -1193,7 +1622,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;
}
@@ -1635,3 +2064,12 @@ Java_sun_font_FreetypeFontScaler_getGlyphPointNative(
return (*env)->NewObject(env, sunFontIDs.pt2DFloatClass,
sunFontIDs.pt2DFloatCtr, x, y);
}
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM *vm, void *reserved) {
if (libFontConfig != NULL) {
#ifndef DISABLE_FONTCONFIG
dlclose(libFontConfig);
#endif
}
}

View File

@@ -347,7 +347,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
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.

View File

@@ -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 @@ final class XWM
{ 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];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@@ -37,6 +37,7 @@ import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.SunGraphicsEnvironment;
@@ -68,10 +69,27 @@ public final class X11GraphicsDevice extends GraphicsDevice
private DisplayMode origDisplayMode;
private boolean shutdownHookRegistered;
private int scale;
private final AtomicBoolean isScaleFactorDefault = new AtomicBoolean(false);
private static volatile int xrmXftDpi;
private static volatile int xftDpi;
private static final int GDK_SCALE;
private static final double GDK_DPI_SCALE;
private static final double GDK_SCALE_MULTIPLIER;
public X11GraphicsDevice(int screennum) {
this.screen = screennum;
this.scale = initScaleFactor();
int scaleFactor = initScaleFactor(-1);
synchronized (isScaleFactorDefault) {
isScaleFactorDefault.set(scaleFactor == -1);
this.scale = isScaleFactorDefault.get() ? 1 : scaleFactor;
}
}
static {
xrmXftDpi = getXrmXftDpi(-1);
GDK_SCALE = (int)getGdkScale("GDK_SCALE", -1);
GDK_DPI_SCALE = getGdkScale("GDK_DPI_SCALE", -1);
GDK_SCALE_MULTIPLIER = GDK_SCALE != -1 ? GDK_SCALE * (GDK_DPI_SCALE != -1 ? GDK_DPI_SCALE : 1) : 1;
}
/**
@@ -295,8 +313,11 @@ public final class X11GraphicsDevice extends GraphicsDevice
private static native void configDisplayMode(int screen,
int width, int height,
int displayMode);
private static native double getNativeScaleFactor(int screen);
private static native void resetNativeData(int screen);
private native Rectangle pGetBounds(int screenNum);
private static native double getNativeScaleFactor(int screen, double defValue);
private static native double getGdkScale(String name, double defValue);
private static native int getXrmXftDpi(int defValue);
/**
* Returns true only if:
@@ -410,10 +431,7 @@ public final class X11GraphicsDevice extends GraphicsDevice
@Override
public synchronized DisplayMode[] getDisplayModes() {
if (!isFullScreenSupported()
|| ((X11GraphicsEnvironment) GraphicsEnvironment
.getLocalGraphicsEnvironment()).runningXinerama()) {
// only the current mode will be returned
if (!isFullScreenSupported()) {
return super.getDisplayModes();
}
ArrayList<DisplayMode> modes = new ArrayList<DisplayMode>();
@@ -507,7 +525,8 @@ public final class X11GraphicsDevice extends GraphicsDevice
*/
@Override
public synchronized void displayChanged() {
scale = initScaleFactor();
xrmXftDpi = getXrmXftDpi(-1);
scale = initScaleFactor(1);
// On X11 the visuals do not change, and therefore we don't need
// to reset the defaultConfig, config, doubleBufferVisuals,
// neither do we need to reset the native data.
@@ -537,24 +556,66 @@ public final class X11GraphicsDevice extends GraphicsDevice
return scale;
}
public int getNativeScale() {
return (int)Math.round(getNativeScaleFactor(screen));
private double getNativeScale() {
isXrandrExtensionSupported();
return getNativeScaleFactor(screen, -1);
}
private int initScaleFactor() {
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
public static void setXftDpi(int dpi) {
xftDpi = dpi;
boolean uiScaleEnabled = SunGraphicsEnvironment.isUIScaleEnabled(dpi);
double xftDpiScale = uiScaleEnabled ? xftDpi / 96.0 : 1.0;
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
X11GraphicsDevice x11gd = (X11GraphicsDevice)gd;
synchronized (x11gd.isScaleFactorDefault) {
if (x11gd.isScaleFactorDefault.get() || !uiScaleEnabled) {
x11gd.scale = (int)Math.round(xftDpiScale * (uiScaleEnabled ? GDK_SCALE_MULTIPLIER : 1));
x11gd.isScaleFactorDefault.set(false);
}
}
}
}
private int initScaleFactor(int defValue) {
boolean uiScaleEnabled = SunGraphicsEnvironment.isUIScaleEnabled();
if (uiScaleEnabled) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
if (debugScale >= 1) {
return (int) debugScale;
}
int nativeScale = getNativeScale();
return nativeScale >= 1 ? nativeScale : 1;
double gdkScaleMult = uiScaleEnabled ? GDK_SCALE_MULTIPLIER : 1;
double nativeScale = getNativeScale();
if (nativeScale > 0) {
return (int)Math.round(nativeScale * gdkScaleMult);
}
if (xrmXftDpi > 0) {
return (int)Math.round((xrmXftDpi / 96.0) * gdkScaleMult);
}
if (xftDpi > 0) {
return (int)Math.round((xftDpi / 96.0) * gdkScaleMult);
}
}
return defValue;
}
return 1;
/**
* Used externally for diagnostic purpose.
*/
public String[][] getDpiInfo() {
int dpi = xrmXftDpi != -1 ? xrmXftDpi : xftDpi;
String xftDpiStr = dpi != -1 ? String.valueOf(dpi) : "undefined";
double gsettingsScale = getNativeScaleFactor(screen, -1);
String gsettingsScaleStr = gsettingsScale != -1 ? String.valueOf(gsettingsScale) : "undefined";
String gdkScaleStr = GDK_SCALE != -1 ? String.valueOf(GDK_SCALE) : "undefined";
String gdkDpiScaleStr = GDK_DPI_SCALE != -1 ? String.valueOf(GDK_DPI_SCALE) : "undefined";
return new String[][] {
{"Xft.DPI", xftDpiStr, "Font DPI (X resources value)"},
{"GSettings scale factor", gsettingsScaleStr, "http://wiki.archlinux.org/index.php/HiDPI"},
{"GDK_SCALE", gdkScaleStr, "http://developer.gnome.org/gtk3/stable/gtk-x11.html"},
{"GDK_DPI_SCALE", gdkDpiScaleStr, "http://developer.gnome.org/gtk3/stable/gtk-x11.html"}
};
}
/**

View File

@@ -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,30 +24,222 @@
*/
#include "systemScale.h"
#include "jni.h"
#include "jni_util.h"
#include "jvm_md.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
static int getScale(const char *name) {
char *uiScale = getenv(name);
if (uiScale != NULL) {
double scale = strtod(uiScale, NULL);
if (scale < 1) {
return -1;
#ifdef __APPLE__
# include <xlocale.h>
#endif
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 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;
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_uint32* fp_g_variant_get_uint32;
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);
}
return (int) scale;
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_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);
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");
}
return -1;
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;
}
double getNativeScaleFactor() {
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);
}
/* [tav]
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",
"scaling-factor");
if (value && fp_g_variant_is_of_type(value, "u")) {
result = fp_g_variant_get_uint32(value);
fp_g_variant_unref(value);
}
}
/* [tav]
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;
}
double getScaleEnvVar(const char *name, double default_value) {
char *uiScale = getenv(name);
if (uiScale != NULL) {
locale_t c_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
double scale = strtod_l(uiScale, NULL, c_locale);
freelocale(c_locale);
if (scale > 0) {
return scale;
}
}
return default_value;
}
double getNativeScaleFactor(char *output_name, double default_value) {
static int scale = -2.0;
double native_scale = 0;
int gdk_scale = 0;
if (scale == -2) {
scale = getScale("J2D_UISCALE");
scale = (int)getScaleEnvVar("J2D_UISCALE", -1);
}
if (scale > 0) {
return scale;
}
return getScale("GDK_SCALE");
native_scale = getDesktopScale(output_name);
if (native_scale <= 0) {
native_scale = default_value;
}
return native_scale;
}

View File

@@ -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,8 @@
#include <signal.h>
#include <stdlib.h>
double getNativeScaleFactor();
double getNativeScaleFactor(char *output_name, double default_value);
double getScaleEnvVar(const char* var_name, double default_value);
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@@ -37,6 +37,8 @@
#include <sun_awt_X11GraphicsConfig.h>
#include <X11/extensions/Xdbe.h>
#include <X11/XKBlib.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#ifndef NO_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
@@ -1728,7 +1730,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));
@@ -1778,8 +1822,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,
@@ -1937,14 +2018,103 @@ 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
* Signature: (I)D
* Signature: (ID)D
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
(JNIEnv *env, jobject this, jint screen) {
return getNativeScaleFactor();
(JNIEnv *env, jobject this, jint screen, jdouble defValue) {
// in case of Xinerama individual screen scales are not supported
char *name = get_output_screen_name(env, usingXinerama ? 0 : screen);
double scale = getNativeScaleFactor(name, defValue);
if (name) {
free(name);
}
return scale;
}
/*
* Class: sun_awt_X11GraphicsDevice
* Method: getGdkScale
* Signature: (Ljava/lang/String;D)D
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getGdkScale
(JNIEnv *env, jobject this, jstring envVarName, jdouble defValue)
{
const char* name = (*env)->GetStringUTFChars(env, envVarName, 0);
double value = getScaleEnvVar(name, defValue);
(*env)->ReleaseStringUTFChars(env, envVarName, name);
return value;
}
/*
* Class: sun_awt_X11GraphicsDevice
* Method: getXrmXftDpi
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getXrmXftDpi
(JNIEnv *env, jobject this, jint defValue)
{
int dpi = defValue;
#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.
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)) {
dpi = atoi(value.addr);
}
}
}
XCloseDisplay(display);
}
#endif
return dpi;
}

View File

@@ -2479,6 +2479,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:

View File

@@ -2739,6 +2739,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:

View File

@@ -316,6 +316,7 @@ typedef enum
{
GTK_FONT_NAME,
GTK_ICON_SIZES,
GTK_XFT_DPI,
GTK_CURSOR_BLINK,
GTK_CURSOR_BLINK_TIME
} Setting;

View File

@@ -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
@@ -811,7 +811,7 @@ SplashGetScaledImageName(const char* jarName, const char* fileName,
#ifndef __linux__
return JNI_FALSE;
#endif
*scaleFactor = (float)getNativeScaleFactor();
*scaleFactor = (float)getNativeScaleFactor(NULL, 1);
return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength);
}

View File

@@ -51,6 +51,11 @@ import sun.java2d.windows.WindowsFlags;
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 final class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
public Win32GraphicsEnvironment() {
}
private native static void setProcessDPIAwareness(int level);
protected native int getNumScreens();
private native int getDefaultScreen();

View File

@@ -70,6 +70,11 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
super(target);
}
@Override
public void updateGC() {
// nop
}
@Override
void create(WComponentPeer parent) {
this.parent = parent;

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